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!;
},
);
},
);
}),
],
);
}
}