Is your feature request related to a problem? Please describe.
I'm frustrated when building a list of widget depending on a BLoC state like in the example below (without condition ATM) :
Describe the solution you'd like
Want to use the BlocBuilder to create a list of Widget and maybe also be able to use the spread ... operator.
...BlocBuilder<List<Widget>>(/*omitted*/)
First example :
AppBar(
actions: BlocBuilder<ProjectListEvent, ProjectListState>(
bloc: _projectListBloc,
builder: (BuildContext context, ProjectListState state) {
widgetList = <Widget>[];
// Conditional Action
if (state is ProjectListLoaded) {
Widget dropDownWidget = DropdownButton<ProjectSort>(
items: [
DropdownMenuItem<ProjectSort>(
value: ProjectSort.name,
child: Text('Name'),
)
],
onChanged: (value) {},
);
widgetList.add(dropDownWidget);
}
/*...*/
// Non state conditional Actions
Widget iconWidget = IconButton(
icon: Icon(MdiIcons.delete),
onPressed: () =>
_projectListBloc.dispatch(ProjectListDefaultCleared()),
);
widgetList.add(iconWidget);
/*...*/
return widgetList;
},
),
);
Second example (with spread operator ...):
AppBar(
actions: <Widget>[
// State conditional Actions
...BlocBuilder<ProjectListEvent, ProjectListState>(
bloc: _projectListBloc,
builder: (BuildContext context, ProjectListState state) {
widgetList = <Widget>[];
if (state is ProjectListLoaded) {
Widget dropDownWidget = DropdownButton<ProjectSort>(
items: [
DropdownMenuItem<ProjectSort>(
value: ProjectSort.name,
child: Text('Name'),
)
],
onChanged: (value) {},
);
widgetList.add(dropDownWidget);
/*...*/
}
return widgetList;
},
),
// Non state conditional Actions
IconButton(
icon: Icon(MdiIcons.delete),
onPressed: () =>
_projectListBloc.dispatch(ProjectListDefaultCleared()),
),
/**/
],
);
Describe alternatives you've considered
I considered using the BlocBuilder to create the entire "action".
AppBar(
actions: <Widget>[
BlocBuilder<ProjectListEvent, ProjectListState>(
bloc: _projectListBloc,
builder: (BuildContext context, ProjectListState state) {
if (state is ProjectListLoaded) {
return DropdownButton<ProjectListSort>(
value: state.sort,
hint: Text(AmasyLocalizations
.of(context)
.projectsSortHint),
onChanged: (value) =>
_projectListBloc.dispatch(ProjectListQuery(sort: value)),
items: [
DropdownMenuItem<ProjectListSort>(
value: ProjectListSort.name,
child: Text("Name"),
)
/*...*/
],
);
}
return Container();
},
),
BlocBuilder<ProjectListEvent, ProjectListState>(
bloc: _projectListBloc,
builder: (BuildContext context, ProjectListState state) {
if (state is ProjectListLoaded) {
return IconButton(
icon: Icon(MdiIcons.delete),
onPressed: () =>
_projectListBloc.dispatch(ProjectListDefaultSelected(projectId: null)),
);
}
return Container();
},
),
],
);
Hi @axellebot 馃憢
Thanks for opening an issue!
Can you please provide a bit more information about how you want BlocBuilder to be used? I'm not sure I completely understand the problem you're running into.
Thanks! 馃憤
Hi,
Want to use the BlocBuilder to create a list of Widget and maybe also be able to use the spread ... operator.
Let's forgot about the spread operator (...) for the moment.
For example if a widget property (like Row widget) need a widget list (aka children for Row widget), is there a way to make the BlocBuilder returning a list of widget instead of a widget ?
Since children are the only "conditionnal" content I don't want to wrap the Row widget into a BlocBuilder.
This way instead of having this :
return BlocBuilder(
bloc: bloc,
builder: (BuildContext context, State state) {
if (state is X) {
return Row(
children: <Widget>[
Text('X'),
Text('X'),
],
);
} else if (state is Y) {
return Row(
children: <Widget>[
Text('Y'),
Text('Y'),
],
);
}
},
);
I want to be able to do this :
return Row(
children: BlocBuilder(
bloc: bloc,
builder: (BuildContext context, State state) {
if (state is X) {
return <Widget>[
Text('X'),
Text('X'),
];
} else if (state is Y) {
return <Widget>[
Text('Y'),
Text('Y'),
];
}
},
),
);
For this I was thinking about using Template and specifiying the type of return by the BlocBuilder.
Extra : This way we can also use it for non-widget stuff (Don't fin any non "broken bloc pattern" example)
Just made examples from the first comment more understandable. https://github.com/felangel/bloc/issues/379#issue-461032060
I can't find any example where the Widget.build return a List
Processing the conditional list of widget before using the list of widget seems to be possible with BlocListener use :
List<Widget> conditionalActions = [];
BlocListener<ProjectListEvent, ProjectListState>(
bloc: _projectListBloc,
listener: (BuildContext context, BlocAState state) {
conditionalActions.clear();
if (state is ProjectListLoaded) {
Widget dropDownWidget = DropdownButton<ProjectSort>(
items: [
DropdownMenuItem<ProjectSort>(
value: ProjectSort.name,
child: Text('Name'),
)
],
onChanged: (value) {},
);
conditionalActions.add(dropDownWidget);
/*...*/
}
},
child: AppBar(
actions: <Widget>[
// State conditional Actions
...conditionalActions,
// Non state conditional Actions
IconButton(
icon: Icon(MdiIcons.delete),
onPressed: () =>
_projectListBloc.dispatch(ProjectListDefaultCleared()),
),
/**/
]
,
),
);
@axellebot after thinking about this for a while I'm not sure it's feasible because flutter requires build to return a single widget. The approach you mentioned works and you can also use something like the Visibility widget in BlocBuilder to conditionally hide certain elements.
Thoughts?
I'm not sure it's feasible because flutter requires build to return a single widget.
@felangel I also ended with the same though.
Well let's close this issue for the moment and wait a potential new flutter feature.
Most helpful comment
@felangel I also ended with the same though.
Well let's close this issue for the moment and wait a potential new flutter feature.