I have a tabview that I want to pass multiple widget to it depending on which screen the user navigated to. The first screen only contains two children while the other one contains four children. I have conditionally passed four Widgets to the other one but it only picked three meaning that my conditions are wrong and it's also giving me this error. Controller's length property (4) does not match the number of children (3) present in TabBarView's children property.
From the attached image, you will see that I tapped on the Archdiocese text and it's returning me the national screen which supposed not to be so.
I really need help on how to navigate them all sequentially
The Paytype there is just an enum
Expanded(
child: Container(
clipBehavior: Clip.hardEdge,
margin: EdgeInsets.symmetric(
horizontal: context.smallPadding,
),
decoration: const BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(cornerRadius),
topRight: Radius.circular(cornerRadius),
),
color: white,
),
child: DefaultTabController(
length: 4,
child: Scaffold(
extendBodyBehindAppBar: true,
resizeToAvoidBottomInset: false,
backgroundColor: white,
appBar: AppBar(
elevation: 0,
toolbarHeight: 0,
backgroundColor: white,
bottom: TabBar(
indicatorColor: AppColor.kColor700,
labelColor: AppColor.kColor700,
isScrollable: true,
padding: const EdgeInsets.only(
bottom: 10.0,
),
labelPadding:
const EdgeInsets.symmetric(horizontal: 10),
indicatorPadding: EdgeInsets.zero,
indicatorSize: TabBarIndicatorSize.label,
unselectedLabelColor: Colors.grey,
labelStyle: TextStyles.t3.copyWith(
fontSize: FontSizes.s14,
),
unselectedLabelStyle: TextStyles.t3.copyWith(
fontSize: FontSizes.s14,
),
tabs: [
const Text('All parishes'),
if (widget.payType != PayType.paygroup) ...[
const Text('Favorite parishes'),
] else ...[
const Text('Favorite groups'),
const Text('ArchDiocese'),
const Text("National")
],
],
),
),
body: TabBarView(
children: [
//All parishes
BlocProvider(
create: (context) => sl<BeneficiaryBloc>(),
child: PageParishes(
payType: widget.payType,
onPressed: (parish) {
if (widget.payType == PayType.payparish) {
//Navigate to a payparish screen
Navigator.push(
context,
CustomRoute(
child: MultiBlocProvider(
providers: [
BlocProvider(
create: (context) =>
sl<BeneficiaryBloc>(),
),
BlocProvider(
create: (context) => sl<HomeBloc>(),
),
],
child: PagePayParish(
parish: parish,
),
),
),
);
} else {
//Navigate to a parish groups screen
Navigator.push(
context,
CustomRoute(
child: PageGroups(
parish: parish,
),
),
);
}
},
),
),
//Groups
widget.payType != PayType.paygroup
? PageRecentParishes(
onPressed: (parish) {
//check if it's parish
if (widget.payType == PayType.payparish) {
//Navigate to a payparish screen
Navigator.push(
context,
CustomRoute(
child: MultiBlocProvider(
providers: [
BlocProvider(
create: (context) =>
sl<BeneficiaryBloc>(),
),
BlocProvider(
create: (context) =>
sl<HomeBloc>(),
),
],
child: PagePayParish(
parish: parish,
),
),
),
);
}
else {
//Navigate to a parish groups screen
Navigator.push(
context,
CustomRoute(
child: PageGroups(
parish: parish,
),
),
);
}
},
)
:PageRecentGroups(
onPressed: (parishGroup) {
//navigate to paygroups
Navigator.push(
context,
CustomRoute(
child: MultiBlocProvider(
providers: [
BlocProvider(
create: (context) =>
sl<BeneficiaryBloc>(),
),
BlocProvider(
create: (context) =>
sl<HomeBloc>(),
),
],
child: PagePayGroup(
parishGroup: parishGroup,
),
),
),
);
},
),
widget.payType !=PayType.paygroup?const PageArchDiocese():const PageNationalGroup()
//National and Archdiocesan groups
],
),
),
),
),
),
Could you use an array of tab models to keep your tab metadata together? Something like this:
class TabModel {
const TabModel({
required this.title,
required this.child,
});
final String title;
final Widget child;
}
@override
Widget build(BuildContext context) {
final tabs = [
TabModel(title:'All parishes', child: AllParishesWidget()),
if (widget.payType != PayType.paygroup) ...[
TabModel(title:'Favorite parishes', child FavoriteParishesWidget()),
] else ...[
TabModel(title: 'Favorite groups', child: FavoriteGroupsWidget()),
TabModel(title: 'ArchDiocese', child: ArchdioceseWidget()),
TabModel(title: 'National', child: NationalWidget())
],
];
Expanded(
child: Container(
...
child: DefaultTabController(
...
tabs: tabs.map((tab) => Text(tab.title)).toList(),
...
body: TabBarView(
children: tabs.map((tab) => tab.child).toList(),
),
),
),
}