Deselect stops working when controller is added
divan opened this issue · 8 comments
Hi, thanks for a great plugin.
I use it in a custom FormBuilderField, and needed a way to initialize selected buttons. It wasn't obvious how to set init values, but eventually I made it by adding GroupButtonController. All worked well until I discovered that deselecting buttons stopped working.
If I remove controller, deselecting works again (but no way to set init values).
Any hints on what can be wrong? Is it a bug or I'm doing something wrong? (maybe there is a way to preselect buttons without controller?)
Hi @divan! Cool nickname 😄
It's hard to understand your case from the description. I have not seen such a mistake yet.
I can help you if you provide an example of your code.
From you description I understand that your situation similar to my when I create TalkerScreenFilter in my another package
Okay, I started testing example code, and it worked. so I figure out that it was my mistake – I put controller.selectIndex()
into the build()
method 🤦
While we here, quick question – is there any way to preselect buttons without controller? It would be really handy to use GroupButton from stateless controllers and be able to init with parameter.
So in my code the class looks like this:
class MyField extends StatelessWidget {
MyField({Key? key}) : super(key: key);
final ctrl = GroupButtonController();
@override
Widget build(BuildContext context) {
return FormBuilderField(
builder: (FormFieldState<dynamic> field) {
return GroupButton(
onSelected: (index, isSelected, _) =>
print('$index button is selected'),
buttons: ["12:00", "13:00", "14:30", "18:00", "19:00", "21:40"],
buttonBuilder: null,
enableDeselect: true,
controller: ctrl,
);
},
);
}
}
FormBuilderField
is a class from a form builder library, which simplifies form creation a lot. As a part of this simplification it injects initial values into the fields via some obscure magic (InheritedWidget maybe, I don't know). So the initial value is set automagically and accesible via field
param of the builder.
Now, the challenge is how to use that field.value
to set initial value of GroupButton's selected buttons. That's where I put controller code into the builder
and got this weird behaviour.
I probably need to explore more how to properly init fields in this form builder, but I think having something like value
or initialValue
in GroupButton would simplify this task a lot. Also will remove the need to have a controller.
Still puzzled how to init values in this use case..
So my initial code (the one that broken deselect feature) was:
class MyField extends StatelessWidget {
MyField({Key? key}) : super(key: key);
final ctrl = GroupButtonController();
final items = ["12:00", "13:00", "14:30", "18:00", "19:00", "21:40"];
@override
Widget build(BuildContext context) {
return FormBuilderField(
builder: (FormFieldState<dynamic> field) {
if (field.value != null) ctrl.selectIndex(items.indexOf(field.value)); // <-- this breaks deselecting, but otherwise works as intended
return GroupButton(
onSelected: (index, isSelected, _) =>
print('$index button is selected'),
buttons: items,
buttonBuilder: null,
enableDeselect: true,
controller: ctrl,
);
},
);
}
}
You can make MyField StatefulWidget
And write this initialization code in initState
if (field.value != null) ctrl.selectIndex(items.indexOf(field.value));
Didn't notice Formbuilder 🤣
You can raise FormBuilder to a higher level
FormBuilder ->
MyField (StatefullWidget) with initState(){ if (field.value != null) ctrl.selectIndex(items.indexOf(field.value)); } ->
GroupButton
You can raise FormBuilder to a higher level
Hmm, not sure I got how to do this.
@Frezyx don't want to steal your time here. so the last question – did the GroupButton API has a selectedButtons
property before and then was removed? If so, what was the reasoning for the change? Right now it seems like having inititialValue
or selectedButtons
field would simplify this common task a lot.