DropdownMenuItem with Map in Flutter - flutter

I wanna populate two DropDownMenuItems from this Map:
var jobs = {
"departments": ["dep1", "dep2", "dep3"],
"dep1": ["job1", "job2"],
"dep2": ["job3", "job4"],
"dep3": ["job5", "job6"]
};
DropdownButton 1 (departments)
DropdownButton(
hint: Text(hint1),
value: chosenDep,
items: jobs['departments']
.map((e) => DropdownMenuItem(child: Text(e), value: e,))
.toList(),
onChanged: (value){
setState({
isDepChosen= true;
chosenDep = value;
});
)
DropdownButton 2 (jobs)
if(isDepChosen)
DropdownButton(
hint: Text(hint2),
value: chosenJob,
items: jobs[chosenDep] // here i select key of map with chosen department
.map((e) => DropdownMenuItem(child: Text(e), value: e,))
.toList(),
onChanged: (value){
setState({
chosenJob = value;
});
)
But I'm getting this error, when i choose anything from second menu and change value of first menu:
Assertion failed: file:///home/koha/flutter/packages/flutter/lib/src/material
/dropdown.dart:1473:15
items == null || items.isEmpty || value == null ||
items.where((DropdownMenuItem<T> item) {
return item.value == value;
}).length == 1
"There should be exactly one item with [DropdownButton]'s value: job1. \nEither zero or 2 or
more [DropdownMenuItem]s were detected with the same value"

You change the first, you have to change the second to the default value.
For example.
DropdownButton(
hint: Text(hint1),
value: chosenDep,
items: jobs['departments']
.map((e) => DropdownMenuItem(child: Text(e), value: e,))
.toList(),
onChanged: (value){
setState({
isDepChosen= true;
chosenDep = value;
chosenJob = jobs[chosenDep].first;
});
)

You are changing the items from the second dropdown, but your variable 'chosenJob' has a value from the old item list. Clean the 'chosenJob' content when you change your 'chosenDep' variable.

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

Errror occured in flutter DropdownButton

Exception has occurred.
_AssertionError ('package: flutter/src/material/dropdown.dart': Failed assertion: line 915 pos 15: 'items == null || items.isEmpty || value == null ||
items.where((DropdownMenuItem item) {
return item.value == value;
}).length == 1': There should be exactly one item with [DropdownButton]'s value: 0.
Either zero or 2 or more [DropdownMenuItem]s were detected with the same value)
Your "value" for DropdownButton should be set to 'null' or or be one from the values list.
DropdownButton(
value: null,
isDense: true,
onChanged: (String newValue) {
// somehow set here selected 'value' above whith
// newValue
// via setState or reactive.
},
items: ['yellow', 'brown', 'silver'].map((String value) {
return DropdownMenuItem(
value: value,
child: Text(value),
);
}).toList(),
),
Initialize the value object with some default value. Please note that the value should be one of the values contained by your collection.
String selectedArray = "ABC"; //This is the selection value. It is also present in my array.
final array = [“ABC”, “DEF”, “GHI”, “JKL”]; //This is the array for dropdown

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,
))

Flutter: Dropdownbutton does not update to display selected choice

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.