Reputation: 6465
I am in the process of developing a widget that consists of a dropdownbutton
in Flutter. This widget creates dropdownmenuitems
after making a request to a url the user has passed in.
I have seen the call being made and the response being valid, but when I use setState
to update the data source for the dropdown I get the following error:
'package:flutter/src/material/dropdown.dart': Failed assertion: line 560 pos 15: 'items == null || I/flutter (11514): items.isEmpty || value == null || items.where((DropdownMenuItem item) => item.value == I/flutter (11514): value).length == 1': is not true.
I tried researching this error and found no helpful answers. The code is below:
class _MyWidgetState extends State<MyWidget> {
List<DropdownMenuItem<String>> _data = [];
String _selected = '';
@override
void initState() {
super.initState();
_loadData();
}
void _loadData() async {
if (widget.urlToFetchData.isNotEmpty) {
var response = await http.get(widget.urlToFetchData);
if (response.statusCode == 200) {
Map<String, dynamic> jsonResponse = convert.jsonDecode(response.body);
jsonResponse.forEach((key, value){
setState(() {
this._data.add(new DropdownMenuItem(
child: new Text(value.toString()),
value: value.toString(),
));
});
});
} else {
print("Request failed with status: ${response.statusCode}.");
}
}
}
}
@override
Widget build(BuildContext context) {
if (_data.length == 0) {
return new Container();
} else {
return Column(
children: <Widget> [
new Text(
widget.dropdownLabelTitle
),
DropdownButton(
value: _selected,
items: _data,
hint: new Text(widget.defaultOptionText),
onChanged: (value) {
_selected = value;
widget.valueReturned(_selected);
setState(() {
});
}
)
],
);
}
}
}
Now, I am fully aware that at the initialization of the widget, the items field in the dropdownbutton is initialized with an empty list, but I thought that by calling setState when the http call finishes, it will update the value.
I have tried different methods of updating the data(by creating a local list and then using addAll
or just by assignment), but I get the same error.
Anyone know how to solve this issue?
Upvotes: 3
Views: 10023
Reputation: 4239
It's will be workable. You have to insert at least one data in array and in value.
List<DropdownMenuItem<String>> _data = ['Select One'];
String _selected = _data[0];
or you can do like this ---->
List<DropdownMenuItem<String>> _data = [];
String _selected = '';
_data.length > 0 ? DropdownButton(
value: _selected,
items: _data,
hint: new Text(widget.defaultOptionText),
onChanged: (value) {
_selected = value;
widget.valueReturned(_selected);
setState(() {
});
}
) : Container();
Upvotes: 0
Reputation: 10175
Your problem is caused indeed by the _selected
value. It has to be in the list of DropdownMenuItem
so in your case the first value is an empty string and there are no items so that's ok, but when you get the values from the API there is no DropdownMenuItem
that has the value==''
so the fix would be to init the _selected
with the first value received from the API. Also you should setState
outside the for
loop. Something like this:
setState(() {
jsonResponse.forEach((key, value) {
if (_selected.isEmpty) {
_selected = value;
}
this._data.add(new DropdownMenuItem(
child: new Text(value.toString()),
value: value.toString(),
));
});
});
Upvotes: 4
Reputation: 11881
You are getting this error because dropdown menu is trying to select item that does not exists.
DropdownButton(
value: _selected, # < here you are trying to select `String _selected = '';`
items: _data,
To solve this simple remove value
or set it somewhere.
Upvotes: 7