I am trying to make dependent multilevel dropdown first contains states list and second contains cities list, all the data fetched from API. Initially, I load state dropdown, when I select the state then cities of that state load if I select city, the city selected successfully but when I change the state value then an error occurs. What is the right way to reload the second dropdown if changes will make in the first dropdown?
Error: There should be exactly one item with [DropdownButton]'s value: Instance of 'City'. Either zero or 2 or more [DropdownMenuItem]s were detected with the same value
Future _state;
Future _city;
@override
void initState() {
super.initState();
_state = _fetchStates();
}
Future<List<StateModel>> _fetchStates() async {
final String stateApi = "https://dummyurl/state.php";
var response = await http.get(stateApi);
if (response.statusCode == 200) {
final items = json.decode(response.body).cast<Map<String, dynamic>>();
List<StateModel> listOfUsers = items.map<StateModel>((json) {
return StateModel.fromJson(json);
}).toList();
return listOfUsers;
} else {
throw Exception('Failed to load internet');
}
}
Future<List<City>> _fetchCities(String id) async {
final String cityApi = "https://dummyurl/city.php?stateid=$id";
var response = await http.get(cityApi);
if (response.statusCode == 200) {
final items = json.decode(response.body).cast<Map<String, dynamic>>();
print(items);
List<City> listOfUsers = items.map<City>((json) {
return City.fromJson(json);
}).toList();
return listOfUsers;
} else {
throw Exception('Failed to load internet');
}
}
State Dropdown
FutureBuilder<List<StateModel>>(
future: _state,
builder: (BuildContext context,
AsyncSnapshot<List<StateModel>> snapshot) {
if (!snapshot.hasData)
return CupertinoActivityIndicator(animating: true,);
return DropdownButtonFormField<StateModel>(
isDense: true,
decoration: spinnerDecoration('Select your State'),
items: snapshot.data
.map((countyState) => DropdownMenuItem<StateModel>(
child: Text(countyState.billstate),
value: countyState,
))
.toList(),
onChanged:(StateModel selectedState) {
setState(() {
stateModel = selectedState;
_city = _fetchCities(stateModel.billstateid);
});
},
value: stateModel,
);
}),
City Dropdown
FutureBuilder<List<City>>(
future: _city,
builder: (BuildContext context,
AsyncSnapshot<List<City>> snapshot) {
if (!snapshot.hasData)
return CupertinoActivityIndicator(animating: true,);
return DropdownButtonFormField<City>(
isDense: true,
decoration: spinnerDecoration('Select your City'),
items: snapshot.data
.map((countyState) => DropdownMenuItem<City>(
child: Text(countyState.billcity)
.toList(),
onChanged: (City selectedValue) {
setState(() {
cityModel = selectedValue;
});
},
value: cityModel,
);
}),
class StateModel {
String billstateid;
String billstate;
String billcountryid;
StateModel({this.billstateid, this.billstate, this.billcountryid});
StateModel.fromJson(Map<String, dynamic> json) {
billstateid = json['billstateid'];
billstate = json['billstate'];
billcountryid = json['billcountryid'];
}
}
class City {
String billcityid;
String billcity;
String billstateid;
City({this.billcityid, this.billcity, this.billstateid});
City.fromJson(Map<String, dynamic> json) {
billcityid = json['billcityid'];
billcity = json['billcity'];
billstateid = json['billstateid'];
}
DropDownButton: In Flutter, A DropDownButton is a material design button. The DropDownButton is a widget that we can use to select one unique value from a set of values. It lets the user select one value from a number of items. The default value shows the currently selected value.
You have to make cityModel = null
in onChanged
callback of State dropdown.
setState(() {
cityModel = null;
stateModel = selectedState;
_city = _fetchCities(stateModel.billstateid);
});
There should be exactly one item with [DropdownButton]'s value: Instance of 'City'. Either zero or 2 or more [DropdownMenuItem]s were detected with the same value
This error occurs here, because the value
you are passing not in the items
of DropdownButtonFormField
(city dropdown).
When you select a State, you are fetching new list of city list and passing it to CityDropDown but forgot to clear the previously selected city(cityModel
).
You can also refer this example: DartPad
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With