Flutter: Dropdownbutton does not update to display selected choice - flutter

I am trying to use a dropdown button to have the user select from a list of options, however after making a selection the dropdown button remains displaying the hint. I think something about the setState is not updating the dropdown button.
value: skillChoice,
items: listDrop,
hint: Text("Choose Skill"),
onChanged: (value) {
setState(() {
skillChoice = value;
});
},
),
here are the variables which are declared earlier in the code:
List<DropdownMenuItem<int>> listDrop = [];
int skillChoice = null;
Can anyone let me know why it isn't updating?

I think setting skillChoice null initially disables the dropdown.

It would have been better if you had shown the full code snippet of how you implemented your DropDownButton. But here is how I do implement mine:
// This is the initial value that will be selected on the DropDownMenu by default
String choice = '1';
// This is the List of String (or whatever data type you want) that will make up the
Drop Down Menu Item options. NOTE: That the String value of 'choice' ('1') is also present in the List of choices ('1')
List<String> choices = [
'1',
'2',
'3',
'4',
'5',
];
DropdownButton<String>(
value: choice,
icon: Icon(Icons.add),
onChanged: (String newValue) {
setState(() => choices = newValue);
},
items: choices.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(
value,
)
);
}).toList(),
),
Should work properly for you now.

Related

Change selection of dropdown button according to the choice from the previous one, Flutter

I have 2 DropdownButtonFormFields where I have a selection of cars. I need to change the second selection of buttons according to the car model user has chosen from the first selection in the DropdownButtonFormField (i.e. If a user chooses a Mercedes in the first one, in the DropdownButtonFormField below, I want to display only models of Mercedes and not, let's say, Audi).
How can I achieve this? Here is the code:
String _make, _model;
/// List of cars and models
List<String> carList = [
'Audi',
'BMW',
'Mercedes',
];
List<String> modelAudi = ['A6', 'A8', 'Q7',];
List<String> modelMercedes = ['E-Class', 'S-Class','Maybach'];
List<String> modelBMW = ['3-Series', 'X5', 'X7'];
/*two DropdownButtonFormFields, but the second one needs to match
it's car manufacturer selection from the carList selection
(i.e. if you select Audi, it must only show the modelAudi list (A6,
A8, Q7) in the second DropdownButtonFormField)
*/
DropdownButtonFormField<String>(
value: _make,
items: carList
.map((label) => DropdownMenuItem(
child: Text(label.toString()),
value: label,
))
.toList(),
onChanged: (value) {
setState(() {
_make = value;
print(value);
});
},
),
DropdownButtonFormField<String>(
value: _model,
/* here is where I need to implement logic
that maps out the model names that matches the car maker
*/
items: modelAudi
.map((label) => DropdownMenuItem(
child: Text(label.toString()),
value: label,
))
.toList(),
onChanged: (value) {
setState(() {
_model = value;
print(value);
});
},
),
The DropDown for the first button:
And naturally because I have no logic behind it, I get this as the model selection whatever I chose from the car list, but I want it to map out only models from the car list you chose.
This is a great use case for a switch statement. Define your cases for each car maker according to this example:
String _maker;
List chosenMakerModel;
switch (_maker) {
case 'Audi':
chosenMakerModel = modelAudi;
break;
case 'BMW':
// implement logic:
break;
case 'OTHER MANUFACTURER':
// implement logic;
break;
}
Using the example code above use chosenMakerModel instead of modelAudi
You can create a model selection method to handle this situation, like
List<String> _selectModel(String? modelName) {
return modelName == carList[0]
? modelAudi
: modelName == carList[1]
? modelMercedes
: modelBMW; // initally it will have modelBMW
}
This will decide the second dropdown item. If you click to select the second drop down item 1st, it will through errors. To handle this situation, you need to update the second dropdown value as well. You can set the second dropdown value=null. Therefor we need to use nullable String for selection value.
class MyProfileState extends State<StatefulWidget> {
String? _make, _model;
/// List of cars and models
List<String> carList = ['Audi', 'BMW', 'Mercedes'];
List<String> modelAudi = ['A6', 'A8', 'Q7'];
List<String> modelMercedes = ['E-Class', 'S-Class', 'Maybach'];
List<String> modelBMW = ['3-Series', 'X5', 'X7'];
List<String> _selectModel(String? modelName) {
return modelName == carList[0]
? modelAudi
: modelName == carList[1]
? modelMercedes
: modelBMW;
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
DropdownButtonFormField<String>(
value: _make,
items: carList
.map((label) => DropdownMenuItem(
child: Text(label.toString()),
value: label,
))
.toList(),
onChanged: (value) {
setState(() {
_make = value;
_model = null;
print(value);
});
},
),
DropdownButtonFormField<String>(
value: _model,
items: _selectModel(_make)
.map((label) => DropdownMenuItem(
child: Text(label.toString()),
value: label,
))
.toList(),
onChanged: (value) {
setState(() {
_model = value;
print(value);
});
},
),
],
));
}
}

Is it allowed to create more than 1 drop down menu in Bottom sheet flutter? I am getting an error

This is my String list:
final List<String> cupsize = ['Select', 'Small', 'Medium', 'Large'];
final List<String> flavour = [
'Chocolate',
'Vanilla',
'Strawberry',
'Blueberry',
'Raspberry',
'Kiwi'
'Select'
];
String _currentCupSize;
String _currentFlavour;
And The drop down menu function is as follows:
//This is for cupsize
DropdownButtonFormField(
value: _currentCupSize ?? 'Select',
items: cupsize.map((size) {
return DropdownMenuItem(
value: size,
child: Text('$size Size'),
);
}).toList(),
onChanged: (val) => setState(() {
return _currentCupSize = val;
}),
),
//This is for flavour
DropdownButtonFormField(
value: _currentFlavour ?? 'One',
items: flavour.map((flav) {
return DropdownMenuItem(
value: flav,
child: Text('$flav Flavour'),
);
}).toList(),
onChanged: (val) => setState(() {
return _currentFlavour = val;
}),
),
The cupsize code is working fine but as soon as flavor function is written,
It says:
I referred to some other answers but none solved my problem.
Any help will be much appreciated:)
Two issues I see here.
One is that you have missed a , after 'Kiwi' in the List.
Second, you have 'Select' in the flavour List. But then, your default value for your second DropdownButtonFormField is 'One'.
So either, change the default value to 'Select' or change the last value in the list to 'One';
final List<String> flavour = [
'Chocolate',
'Vanilla',
'Strawberry',
'Blueberry',
'Raspberry',
'Kiwi',
'One'
];
Since, it doesn't see your 'One' default value being in the list, it is throwing the error.

No rebuild after choosing value in Dropdown

I am sending the choosen value of the DropdownMenu via Callback to the parent widget (see code below).
return DropdownButton<String>(
hint: Text(widget.hint),
value: valueChoose,
items: widget.users.map((dynamic valueItem) {
return DropdownMenuItem<String>(
value: valueItem,
child: Text(valueItem),
);
}).toList(),
onChanged: (newValue) {
setState(() {
valueChoose = newValue;
besetzungsList.add(valueChoose);
widget.besetzungsListChanged(valueChoose);
widget.fromDropDown(true);
});
},
);
The problem is with "besetzungsList[i] = value;" no rebuild occurs. But I need the choosen value to be shown in the UI. If I set the value via the insert function then it works. But I need to replace the value inside the list.
DataCell(DropDown(
hint: "Wählen",
users: users,
besetzungsListChanged: (String value) {
besetzungsList[i] = value;
},
fromDropDown: (bool value) => fromDropDown = value,
))
Is the parent widget a stateful widget?
you can try to call setState in benutzungsListChangedto enforce rebuild of the parent widget
DataCell(DropDown(
hint: "Wählen",
users: users,
besetzungsListChanged: (String value) {
setState(() {besetzungsList[i] = value;});
},
fromDropDown: (bool value) => fromDropDown = value,
))

How do I make DropdownButtonFormField show me the output that is the value that I have saved in my database

I am working with a DropdownButtonFormField and so far the list is loading me, but I would like you to load the list and also load the item that is saved in my database and show it to me as output indicating that the user had already selected an item previously.
This is the code that I am using
DropdownButtonFormField(
isDense: true,
//hint: new Text("Seleccione Barrio"),
items: dataBarrio.map((item) {
return new DropdownMenuItem(
child: new Text(item['nom']),
value: item['id'].toString(),
);
}).toList(),
onChanged: (newVal) {
setState(() {
_mySelectionBarrio = newVal;
});
},
value: _mySelectionBarrio,
)

DropdownButtonFormField gives Error when try to display String

I want to make DropdownButtonFormField that shows cities like this:
final List<String> cities = ['London', 'New York', 'Paris', 'Shanghahai', 'Tokyo'];
String _currentCity;
DropdownButtonFormField(
value: _currentCity ?? ' ',
decoration: textInputDecoration,
items: cities.map((city) {
return DropdownMenuItem(
value: city,
child: Text('$city City '),
);
}).toList(),
onChanged: (val) => setState(() => _currentCity = val ),
),
But when I try to show these Strings I get red screen error :
and If I changed the Strings inside the List to numbers it works well:
final List<String> cities = ['0', '1', '2', '3', '4'];
Can someone tell me what is wrong with it although I use List of strings
You can try set _currentCity for default value?
String _currentCity = 'London';