I'm implementing corresponding dropdowns (where the options of the second dropdown depend on the first like so) that uses a list of objects in this format:
List<State> states = [
new State(stateId: 1, stateName: "New York", cities: [
new City(cityId: 1, cityName: "New York City"),
new City(cityId: 2, cityName: "Buffalo") ...
And the widget code is like so:
children: <Widget>[
DropdownButtonFormField<int>(
decoration: InputDecoration(labelText: 'State'),
value: selectedStateId,
items: states.map((State state) {
return new DropdownMenuItem<int>(
value: state.stateId,
child: new Text(states.singleWhere((x) => x.stateId == state.stateId).stateName),
);
}).toList(),
onChanged: (int newStateId) {
setState(() {
this.selectedCityId = states.singleWhere((x) => x.stateId == newStateId).cities[0].cityId; // set to first city for this state
this.selectedStateId = = newStateId;
});
},
),
DropdownButtonFormField<int>(
decoration: InputDecoration(labelText: 'City'),
value: selectedCityId,
items: states.singleWhere((x) => x.stateId == selectedStateId)
.cities
.map((City city) {
return new DropdownMenuItem<int>(
value: city.cityId,
child: new Text(states
.singleWhere((x) => x.stateId == selectedStateId).cities.singleWhere((x) => x.cityId == city.cityId).cityName),
);
}).toList(),
onChanged: (int newCityId) {
setState(() {
this.selectedCityId = newCityId;
});
},
)
],
When I change the State dropdown in this example, I get an error: "There should be exactly one item with [DropdownButton]'s value: 1. Either zero or 2 or more [DropdownMenuItem]s were detected with the same value".
The "1" in the above error corresponds to whatever the selected city value was prior to changing the state, so I know that the error relates to the fact that it's still looking for the old selectedCityId and it is no longer in the item list, but I'm not sure why as I've changed that value in setState. A key to this issue, I believe, is the same exact code works if I just change the DropDownButtonFormField to regular DropDownButtons, but I'd like to use the built in label text that comes along with the former.