Home > OS >  How to set the state of DropdownMenuItem when I got a snapshot from the item property of DropdownBut
How to set the state of DropdownMenuItem when I got a snapshot from the item property of DropdownBut

Time:04-10

I am trying to get the document id of each firebase document in a DropdownMenuItem and I succesfully manage to do that by moving the query outside my widget and initialize the stream in a initState but I struggle in how to setState when the user select a different choice, when I got the id from the DropdownButton item property.

class BoxDestination extends StatefulWidget {
      const BoxDestination({Key? key}) : super(key: key);
    
      @override
      State<BoxDestination> createState() => _BoxDestinationState();
    }
    
    class _BoxDestinationState extends State<BoxDestination> {
    
      Stream<QuerySnapshot>? _governorates;
      @override
      void initState() {
        _governorates= FirebaseFirestore.instance.collection("Gouvernorat").snapshots();
        return super.initState();
      }
      @override
      Widget build(BuildContext context) {
        return   Row(
          children: <Widget>[
            StreamBuilder<QuerySnapshot>(
                stream: _governorates,
                builder: (BuildContext context, AsyncSnapshot<QuerySnapshot>snapshot) {
                  return DropdownButton(
                    // Down Arrow Icon
                    icon: const Icon(Icons.keyboard_arrow_down),
                    hint: const Text("Governorate"),
                    // Array list of items
                    items: snapshot.data?.docs.map((govData) {
                      return DropdownMenuItem(
                        value: govData.id,//variable
                        child: Text(govData.id),
                      );
                    }).toList(),
                    // After selecting the desired option,it will
                    // change button value to selected value
                    onChanged: (value) {
                      setState(() {
                        //I cannot do this because govData is Undefined.
                        govData.id=value;
                      },
                      );
                    },
                  );
                }),
          ],
        );
      }
    }

CodePudding user response:

You need to use one different variable in order to store the selected value. Because on every setstate stream builder will rebuild and it will loose it's old state.

Maybe you could do like this.

class _BoxDestinationState extends State<BoxDestination> {
  Stream<QuerySnapshot>? _governorates;
  dynamic selectedValue;

   @override
   void initState() {
     _governorates =
       FirebaseFirestore.instance.collection("Gouvernorat").snapshots();
       return super.initState();
    }

 @override
 Widget build(BuildContext context) {
return Row(
  children: <Widget>[
    StreamBuilder<QuerySnapshot>(
        stream: _governorates,
        builder:
            (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
          return DropdownButton(
 // Down Arrow Icon
            icon: const Icon(Icons.keyboard_arrow_down),
            hint: const Text("Governorate"),
  // Array list of items
            items: snapshot.data?.docs.map((govData) {
              return DropdownMenuItem(
                value: govData.id, //variable
                child: Text(govData.id),
              );
            }).toList(),
 // After selecting the desired option,it will
 // change button value to selected value
            onChanged: (value) {
              setState(
                () {
  //remove govData.
                  selectedValue = value;
                },
              );
            },

            // use value to select a different choice
            value: selectedValue.id,
          );
        }),
  ],
);

} }

CodePudding user response:

After following this and with the guide of @kishan busa it turns out that we should have a null value first then assign a new value to it in the setState()

class BoxDestination extends StatefulWidget {
      const BoxDestination({Key? key}) : super(key: key);
    
      @override
      State<BoxDestination> createState() => _BoxDestinationState();
    }
    
    class _BoxDestinationState extends State<BoxDestination> {
      String? Governorate;
      Stream<QuerySnapshot>? _governorates;
      @override
      void initState() {
        _governorates= FirebaseFirestore.instance.collection("Gouvernorat").snapshots();
        return super.initState();
      }
      @override
      Widget build(BuildContext context) {
        return   Row(
          children: <Widget>[
            StreamBuilder<QuerySnapshot>(
                stream: _governorates,
                builder: (BuildContext context, AsyncSnapshot<QuerySnapshot>snapshot) {
                  return DropdownButton(
            value: Governorate,
                    // Down Arrow Icon
                    icon: const Icon(Icons.keyboard_arrow_down),
                    hint: const Text("Governorate"),
                    // Array list of items
                    items: snapshot.data?.docs.map((govData) {
                      return DropdownMenuItem(
                        value: govData.id,
                        child: Text(govData.id),
                      );
                    }).toList(),
                    onChanged: (String? value) {
                      setState(() {
                        Governorate=value!;
                      },
                      );
                    },
                  );
                }),
          ],
        );
      }
    }
  • Related