I\' m gettings items from JSON and displaying them in a dropdown. When the person select an item from the dropdown list, I get the selection but the selected item doesn\'t c
Because you need to update the "value: " parameter with "setState(() {});" method and the new value must be of the same type of the one passed to "onChanged:". I suggest tho do this because your are able to change dynamically your icon.
1) declare a new class in the top of the file;
class city {
final String name;
final IconData icon;
const city({
this.name,
this.icon,
});
}
2) the add this in the state of your widget:
class yourState extend<myWidget>{
List<city> cities = [
new city(name: "tokio", icon: Icons.location_city),
new city(name: "paris", icon: Icons.location_city),
new city(name: "new york", icon: Icons.location_city),
];
int index = 0;
Widget drop() {
return DropdownButton(
value: cities[index],
hint: new Text("Ville"),
items: cities.map((city value) {
return new DropdownMenuItem(
value: value,
child: new Row(
children: <Widget>[
new Icon(
value.icon,
color: Colors.deepOrange,
),
new Text(value.name)
],
),
);
}).toList(),
onChanged: (city value) {
setState(() {
index = cities.indexOf(value);
print(index);
});
//getTravelCity(value.name);
});
}
}
now call "drop()" where you want your DropDown. Bye!!
You hard-coded the first city as value for the dropdown.
new DropdownButton(
value: cities.elementAt(0), //this one
...
You need to have some state
variable to hold the selected city.
class YourStatefulWidgetState extends State<YourStatefulWidget> {
@override
initState() {
super.initState();
selectedCity = cities.elementAt(0)
}
@override
Widget build(BuildContext context) {
...
new DropdownButton(
value: selectedCity,
hint: new Text("Ville"),
items: cities.map((String value) {
return new DropdownMenuItem(value: value,
child: new Row(
children: <Widget>[
new Icon(
Icons.location_city, color: Colors.deepOrange,),
new Text(value)
],
),);
}).toList(),
onChanged: (String value) {
setState(() {
selectedCity = getTravelCity(value);
});
},),
...
For those who are facing this problem in future. Use variable to set the value to DropdownButton and when the onChanged called update the variable using setState
Expanded(child: DropdownButton<String>(
items: cities.map((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
value: city,
onChanged: (String val) {
_onDropDownChanged(val);
},
),)
update the city variable by using state
void _onDropDownChanged(String val) {
setState(() {
this.city = val;
});
}
For further information check the link below
https://github.com/FazalHussain/Flutter-Demo/blob/trip_cost_app/lib/main.dart
This is the solution: "StatefulBuilder()"
Future<void> AgregarContacto() async {
String dropdownValue = 'Exento';
return showDialog<void>(
context: context,
barrierDismissible: true, // user must tap button!
builder: (BuildContext context) {
return StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return AlertDialog(
title: Text('Agregar cliente', textAlign: TextAlign.center,),
content:
SingleChildScrollView(
child: ListBody(
children: <Widget>[
Center(
child: Material(
type: MaterialType.transparency,
child: DropdownButton<String>(
items: <String>[
'Responsable inscripto',
'Monotributista',
'Exento',
'Consumidor final',
'No responsable'
]
.map<DropdownMenuItem<String>>((
String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
); //DropMenuItem
}).toList(),
value: dropdownValue,
onChanged: (String newValue) {
setState(() {
dropdownValue = newValue;
print("new${newValue}");
}); //setState
},
//OnChange
isExpanded: false,
hint: Text('Responsable inscripto',
style: TextStyle(color: Colors.black),),
),
), //Material
), //Center
],
),
),
actions: <Widget>[
FlatButton(
child: Text('Regret'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
}
);
},
);
}
make sure you are not declaring the selectedValue inside the Widget the below example works for me perfectly.
here is the working code on dartpad to test it out
var currentSelectedValue;
const deviceTypes = ["Mac", "Windows", "Mobile"];
Widget typeFieldWidget() {
return Container(
padding: EdgeInsets.symmetric(horizontal: 20),
child: FormField<String>(
builder: (FormFieldState<String> state) {
return InputDecorator(
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0))),
child: DropdownButtonHideUnderline(
child: DropdownButton<String>(
hint: Text("Select Device"),
value: currentSelectedValue,
isDense: true,
onChanged: (newValue) {
setState(() {
currentSelectedValue = newValue;
});
print(currentSelectedValue);
},
items: deviceTypes.map((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
),
),
);
},
),
);
}
Is used this code in my most recent app and it works. Maybe you could compare it to your code.
return DropdownButton<String>(
style: Theme.of(context).textTheme.title,
items: _persons.map((String val) {
return new DropdownMenuItem<String>(
value: val,
child: new Container(
child: new Card(
child: new Row(children: <Widget>[
new Icon(Icons.person),
new Text(val),
]),
),
),
);
}).toList(),
hint: new Card(
child: new Row(children: <Widget>[
new Icon(Icons.person),
new Text("check"),
])),
value: _selectedPerson,
onChanged: (newVal) {
_selectedPerson = newVal;
setState(() {});
});