So your DropdownButton selection in a dialog won't update Value in your Flutter App?

If you have an alert dialog containing a DropdownButton widget you might notice that when an item is selected its value does not update as you intend. Whenever you click on an option within the DropDown you want it to display the selected value.
So let's assume it a simple app you are showing the user a dialog box with options of payment to choose from and the quick code for that is as below:
class HomePage extends StatefulWidget {
@override
HomePageState createState() => HomePageState();
}
class HomePageState extends State<HomePage> {
String? chosenMethod = 'none';
Future<void> showOptionsDialog() {
return showDialog(
context: context,
builder: (BuildContext context) => AlertDialog(
title: const Text("Select your payment method"),
content: SizedBox(
height: 100,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: DropdownButton<String>(
hint: const Text('Select one option'),
value: chosenMethod,
underline: Container(),
items: <String>['M-PESA', 'Cheque', 'Credit Card']
.map((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(
value,
style: const TextStyle(fontWeight: FontWeight.w500),
),
);
}).toList(),
onChanged: (String? value) {
setState(() => chosenMethod = value);
},
),
),
],
),
),
actions: <Widget>[
TextButton(
child: const Text("Close"),
onPressed: () {
Navigator.of(context).pop();
},
),
],
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
children: [
Text('Your Method: $chosenMethod'),
const SizedBox(height: 10),
TextButton(
onPressed: showOptionsDialog,
child: const Text('Choose Your Method'),
),
],
),
),
);
}
}
I believe this may be an issue with how flutter builds widget because when I placed the DropdownButton widget outside of the dialog it worked, however placing it within an alert dialog causes it to fail. I also noticed that if I clicked on an option in the DropdownButton and then exited and clicked on the dialog again the selected item would change. However, I want the selected value to change without the user having to tap out of the dialog and then back in.
setState will only update the current StatefulWidget's Widget Build function.
Did you know that setState only updates the current StatefulWidget's widget build function? Therefore we will introduce the StatefulBuilder inside showDialog.
For your case just add StatefulBuilder as a parent of your DropDown widget, and use StateSetter when you want to update the StatefulBuilder's children. It will only update the widget tree defined under StatefulBuilder builder function as below:
Future<void> showOptionsDialog() {
return showDialog(
context: context,
builder: (BuildContext context) => StatefulBuilder(
builder: (BuildContext context, StateSetter setState) => AlertDialog(
title: const Text("Select your payment method"),
content: SizedBox(
height: 205,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: DropdownButton<String>(
hint: const Text('Select one option'),
value: chosenMethod,
underline: Container(),
items: <String>['M-PESA', 'Cheque', 'Credit Card']
.map((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(
value,
style: const TextStyle(fontWeight: FontWeight.w500),
),
);
}).toList(),
onChanged: (String? value) {
setState(() => chosenMethod = value);
},
),
),
],
),
),
actions: <Widget>[
TextButton(
child: const Text("Close"),
onPressed: () {
Navigator.of(context).pop();
},
),
],
),
),
);
}
That is it for today see you in the next article
Don't fail to Follow me here on Hashnodeand On
Twitter @ JacksiroKe | Linked In Jack Siro | Github @ JacksiroKe




