Despite multiple entries here that seem to have a similar issue i can not get this really working.
I have a Setup of two depended DropdownButtonFormFields where the second changes to another list after the first is changed.
The following error is provided
════════ Exception caught by widgets library ═══════════════════════════════════
There should be exactly one item with [DropdownButton]'s value: GreenBananas.
Either zero or 2 or more [DropdownMenuItem]s were detected with the same value
'package:flutter/src/material/dropdown.dart':
Failed assertion: line 827 pos 15: 'items == null || items.isEmpty || value == null ||
items.where((DropdownMenuItem<T> item) {
return item.value == value;
}).length == 1'
The relevant error-causing widget was
DropdownButtonFormField<String>
lib/…/testing/test.dart:242
══════════════════════════════════════════════════════════════════
I simplified the example and reconstructed the error to get a better analyse on the issue and get more valuable input from you guys :)
class InputRowTest extends StatefulWidget {
@override
_InputRowTestState createState() => _InputRowTestState();
}
class _InputRowTestState extends State<InputRowTest> {
List<String> list1 = ['Apples', 'Bananas', 'Peaches'];
List<String> list1_1 = ['GreenApples', 'RedApples', 'YellowApples'];
List<String> list1_2 = [
'YellowBananas',
'BrownBananas',
'GreenBananas',
'GreenApples'
];
List<String> list1_3 = [
'RedPeaches',
'YellowPeaches',
'GreenPeaches',
'GreenApples'
];
List<String> _fromparent;
int _fromparentint;
//String selected;
@override
void initState() {
_fromparent = list1_1;
_fromparentint = 0;
//selected = list1[0];
super.initState();
}
@override
Widget build(BuildContext context) {
List<List<String>> subLists = [list1_1, list1_2, list1_3];
_fromparent = subLists[_fromparentint];
DropdownButtonFormField ddff = DropdownButtonFormField(
//value: selected, //list1[0],
//items: list1.map((category) {
value: _fromparent[0], //Seems this value wont change.
items: _fromparent.map((category) {
return DropdownMenuItem(
value: category,
child: Container(
child: Text(category),
),
);
}).toList(),
onChanged: (val) => print(val),
);
return Center(
child: Row(
children: <Widget>[
Expanded(
child: DropdownButtonFormField(
value: list1[0],
items: list1.map((category) {
return DropdownMenuItem(
value: category,
child: Container(
child: Text(category),
),
);
}).toList(),
onChanged: (val) {
setState(() {
//selected = val;
_fromparentint = list1.indexOf(val);
});
},
),
),
Expanded(
child: ddff,
),
],
),
);
}
}
I found a workarround on the issue.
It seems like instead of rebuilding the DropDownFormField, Flutter just considers it as completely ok to keep it. In this case it is also even pretty stubborn.
As i could not find a way to rebuild the Field, I created a pretty nasty but working. Also still requires some polish.
I basically let flutter believe I provide a different widget each time.
class InputRowTest extends StatefulWidget {
@override
_InputRowTestState createState() => _InputRowTestState();
}
class _InputRowTestState extends State<InputRowTest> {
List<String> list1 = ['Apples', 'Bananas', 'Peaches'];
List<String> list1_1 = ['GreenApples', 'RedApples', 'YellowApples'];
List<String> list1_2 = [
'YellowBananas',
'BrownBananas',
'GreenBananas',
'GreenApples'
];
List<String> list1_3 = [
'RedPeaches',
'YellowPeaches',
'GreenPeaches',
'GreenApples'
];
List<String> _fromparent;
int _fromparentint;
Widget ddbff;
var selected;
bool chance;
Widget ddff(List<String> list, bool chance) {
return (chance)
? DropdownButtonFormField(
value: list[0], //Seems this value wont change.
items: list.map((category) {
return DropdownMenuItem(
value: category,
child: Container(
child: Text(category),
),
);
}).toList(),
onChanged: (val) {
print(val);
},
)
: Container(
child: DropdownButtonFormField(
value: list[0], //Seems this value wont change.
items: list.map((category) {
return DropdownMenuItem(
value: category,
child: Container(
child: Text(category),
),
);
}).toList(),
onChanged: (val) {
print(val);
},
),
);
}
@override
void initState() {
_fromparent = list1_1;
_fromparentint = 0;
selected = list1_1[0];
chance = true;
ddbff = ddff(_fromparent, chance);
super.initState();
}
@override
Widget build(BuildContext context) {
List<List<String>> subLists = [list1_1, list1_2, list1_3];
_fromparent = subLists[_fromparentint];
chance = !chance;
ddbff = ddff(_fromparent, chance);
return Center(
child: Container(
child: Row(
children: <Widget>[
Expanded(
child: DropdownButtonFormField(
value: list1[0],
items: list1.map((category) {
return DropdownMenuItem(
value: category,
child: Container(
child: Text(category),
),
);
}).toList(),
onChanged: (val) {
setState(() {
_fromparentint = list1.indexOf(val);
});
},
),
),
Expanded(
child: ddbff,
),
],
),
),
);
}
}