6
DropdownButton Value does not update even after selecting different items.

If default value is null then error message is shown and if I pass any default value (not null) then it never changes to other selected values.

currentCategory is set as default value for DropdownButton.

StreamBuilder<QuerySnapshot>(
                    stream: Firestore.instance
                        .collection('categories')
                        .snapshots(),
                    builder: (BuildContext context,
                        AsyncSnapshot<QuerySnapshot> snapshot) {
                      currentCategory = snapshot.data.documents[0];
                      return DropdownButtonHideUnderline(
                        child:
                            new DropdownButtonFormField<DocumentSnapshot>(
                          value: currentCategory,
                          onChanged: (DocumentSnapshot newValue) {
                            setState(() {
                              currentCategory = newValue;
                            });
                            print(currentCategory.data['name']);
                          },
                          onSaved: (DocumentSnapshot newValue) {
                            setState(() {
                              currentCategory = newValue;
                            });
                          },
                          items: snapshot.data.documents
                              .map((DocumentSnapshot document) {
                            return new DropdownMenuItem<DocumentSnapshot>(
                              value: document,
                              child: Text(
                                document.data['name'],
                              ),
                            );
                          }).toList(),
                        ),
                      );
                    }),

help me to resolve this issue. Thanks in advance.

Ketul Rastogi
  • 163
  • 2
  • 9
  • 2
    override `initState()` and create a `stream` variable then set stream value in stream builder. – Ahmed Jan 04 '19 at 22:44

2 Answers2

7

Triggering setState will schedule a new build (the build method is always called after receiving a call to setState).

So I suggest you to move your query outside your widget and initialize the stream in a initState statement so that it is not computed every time the state change (unless you really need it).

Also move your currentCategory outside the widget build method.

Something like this should work :

class YourClass extends StatefulWidget {
  ...
}

class _YourClassState extends State<YourClass> {

  Stream<QuerySnapshot> _categories;
  DocumentSnapshot _currentCategory;

  initState() {
    _categories = Firestore.instance.collection('categories').snapshots();
    return super.initState();
  }

  Widget build(BuildContext context) {
    return Container(
      child: StreamBuilder<QuerySnapshot>(
        stream: _categories,
        builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
          return DropdownButtonHideUnderline(
            child: new DropdownButtonFormField<DocumentSnapshot>(
              value: _currentCategory,
              onChanged: (DocumentSnapshot newValue) {
                setState(() {
                  _currentCategory = newValue;
                });
              }
            )
          )
        }
      )
    );
  }

}

Also note that setState only work for stateful widgets.

Yann39
  • 14,285
  • 11
  • 56
  • 84
0

That's because everytime you do a setState even though the currentCategory changed, it will rebuild your tree and go through currentCategory = snapshot.data.documents[0]; back again giving you the idea that is not being set.

Replace it by if(currentCategory == null) currentCategory = snapshot.data.documents[0]; so it will be set only if this condition is met.

Miguel Ruivo
  • 16,035
  • 7
  • 57
  • 87
  • This error message is displayed now if I set initialvalue if it is equal to null. The following assertion was thrown building DropdownButtonFormField(dirty, state: _DropdownButtonFormFieldState#b9cd7): 'package:flutter/src/material/dropdown.dart': Failed assertion: line 514 pos 15: 'items == null || value == null || items.where((DropdownMenuItem item) => item.value == value).length == 1': is not true. – Ketul Rastogi Jan 04 '19 at 19:36