Updating Dropdown Data In Flutter Gives Error

5,820

Solution 1

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.

Solution 2

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(),
            ));
      });
    });
Share:
5,820
tomerpacific
Author by

tomerpacific

Updated on December 11, 2022

Comments

  • tomerpacific
    tomerpacific over 1 year

    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 the 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, that 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?