Drop down button in flutter: value isn't compiling - flutter

I have this drop down button in flutter:
DropdownButton(
value: _value,
items: [
DropdownMenuItem(
child: Text("First Item"),
value: 1,
),
DropdownMenuItem(
child: Text("Second Item"),
value: 2,
),
DropdownMenuItem(
child: Text("Third Item"),
value: 3
),
DropdownMenuItem(
child: Text("Fourth Item"),
value: 4
)
],
onChanged: (value) {
setState(() {
_value = value; //here I get the error
});
})
I get the following error: A value of type 'Object?' can't be assigned to a variable of type 'int'.
On the following line: _value = value;
Any help is appreciated.

You need to specify the type of value with the generic on the DropdownButton constructor:
DropdownButton<int>(
...
The way you currently have it, the DropdownButton does not know what type value is supposed to be, so the onChanged callback provides the most generic type, an Object?. Adding the generic parameter tells the button that it should expect and emit int values.

Related

DropdownButtonFormField reset value to initial

How do I reset or select the first value from DropdownButtonFormField?
The answer from here How to reset value in Flutter DropdownButtonFormField is outdated and not suitable for the newer flutter version.
DropdownButtonFormField:
final etSkillScore1Key = GlobalKey<FormState>();
...
DropdownButtonFormField(
key: etSkillScore1Key,
decoration: const InputDecoration(labelText: 'Select value'),
onChanged: (val) async {
setState(() {
etSkillScore1 = val as int;
});
FocusScope.of(context).requestFocus(FocusNode());
},
value: etSkillScore1,
items: priorities2.map((db.Priority priorities) {
return DropdownMenuItem(
child: Text(priorities.name),
value: priorities.value,
);
}).toList(),
),
Button for resetting the value:
IconButton(
onPressed: () {
//ERORR: Null check operator used on a null value
etSkillScore1Key.currentState!.reset();
},
icon: Icon(
Icons.close,
))
Error:
======== Exception caught by gesture
The following _CastError was thrown while handling a gesture:
Null check operator used on a null value
If I use
etSkillScore1Key.currentState?.reset();
then nothing happens
First of all you are not using the correct key it should be a GlobalKey<FormFieldState>(), but even then the reset() would not work.
The reason for this is because of the implementation of DropdownButtonFormField:
DropdownButtonFormField({
// ...
T? value,
// ...
}) : super(
// ...
initialValue: value,
// ...
);
(source: Flutter Documentation)
As you can see the value property of DropdownButtonFormField is what defines the initialValue of the FormField so when you are rebuilding your form field and changing the value of etSkillScore1 it is also changing the value of your DropdownButtonFormField.initialValue.
Solution 1
If you want your reset() to work then you can remove the property value of DropdownButtonFormField so the initialValue won't change with etSkillScore1.
DropdownButtonFormField<int>(
key: etSkillScore1Key,
decoration: const InputDecoration(labelText: 'Select value'),
onChanged: (val) {
etSkillScore1 = val;
FocusScope.of(context).requestFocus(FocusNode());
},
// value: etSkillScore1,
items: priorities2.map((db.Priority priorities) {
return DropdownMenuItem<int>(
child: Text(priorities.name),
value: priorities.value,
);
}).toList(),
)
Try the full example on DartPad
Solution 2
Do not set the value property with etSkillScore1, if you want to initialize your widget with an initial value then do it like this:
DropdownButtonFormField<int>(
key: etSkillScore1Key,
decoration: const InputDecoration(labelText: 'Select value'),
onChanged: (val) {
etSkillScore1 = val;
FocusScope.of(context).requestFocus(FocusNode());
},
value: 1, // Use a fixed value that won't change
items: priorities2.map((db.Priority priorities) {
return DropdownMenuItem<int>(
child: Text(priorities.name),
value: priorities.value,
);
}).toList(),
)
As your value will be fixed then when DropdownButtonFormField is rebuild it will keep 1 as its initial value.

Can I get multiple return from dropdownbutton?

I tried to make json to dropdownbutton today.
But I want to get 2 values(ID and Name both) from it.
this is my json
[{"StudentID":"3","StudentName":"Amy"},{"StudentID":"4","StudentName":"Derek"}]
and this is my code of dropdown button.
Row(
children: <Widget>[Container(
padding: EdgeInsets.only(left:5),
child: new DropdownButton(
value: _StudentSelection,
items: StudentData.map((product) {
return new DropdownMenuItem(
value: product["StudentID"].toString(),
child: new Text(product["StudentName"]!)
)
}).toList(),
onChanged: (String? newValue) {
setState(() {
_StudentSelection = newValue!;
});
},
hint: Text('StudentID'),
)
),
],
),
in this case variety _StudentSelection is already initialized by Amy and StudentData is result of decoding json.
Thank you for seeing this question :)
Make your _StudentSelection variable's type the same type as your product variable and then use product as a value:, not just the ID.
Row(
children: <Widget>[Container(
padding: EdgeInsets.only(left:5),
child: new DropdownButton(
value: _StudentSelection, // change this variables type to the type of your product variable
items: StudentData.map((product) {
return new DropdownMenuItem(
value: product, // use the whole product as value
child: new Text(product["StudentName"]!)
)
}).toList(),
onChanged: (TYPE_OF_PRODUCT_HERE? newValue) {
setState(() {
_StudentSelection = newValue!;
});
},
hint: Text('StudentID'),
)
),
],
),

Create a Dropdown Button from a list of maps

I'm trying to create a dropdown button using a list of maps.
This is my list which is in _location['category']:
[{id: 12345, title: My category}]
And the DropdownButton:
DropdownButton(
items: _location['category'].map((item) {
return DropdownMenuItem(
child: Text(item['title']),
value: item.id,
);
}),
onChanged: (newVal) => print(newVal),
value: null,
),
Error: The following _TypeError was thrown building LocationDialog(dirty, state: _LocationDialogState#6947a):
type 'MappedListIterable<dynamic, dynamic>' is not a subtype of type 'List<DropdownMenuItem<Null>>'
Add .toList() to make your .map a List.
The code below should help
Create a List called category somewhere then use it with the DropdownButton
List category = _location['category'];
DropdownButton(
items: category.map((item) {
return DropdownMenuItem(
child: Text(item['title']),
value: item.id,
);
}).toList(),
onChanged: (newVal) => print(newVal),
value: null,
),

How to use custom data types dropdownlist buttons in flutter?

I want to make drop-downlistbutton but its list should be elements of enum now I tried to change the type but it showed an error now I know I could do with strings and later on use if-else to do but obviously would make the code long so is there any way like to change the string to datatype of an enum.
Yes, you can easily do that. Just specify the data type you want to use, here we use DropdownButton<CustomType>
enum CustomType { TYPE1, TYPE2, TYPE3 }
DropdownButton<CustomType>(
onChanged: (value) => print(value),
items: [
DropdownMenuItem(
child: Text("TYPE 1"),
value: CustomType.TYPE1,
),
DropdownMenuItem(
child: Text("TYPE 2"),
value: CustomType.TYPE2,
),
DropdownMenuItem(
child: Text("TYPE 3"),
value: CustomType.TYPE3,
),
],
)
Iterating over enum values
DropdownButton<CustomType>(
onChanged: (value) => print(value),
items: CustomType.values
.map((type) => DropdownMenuItem(
child: Text(type.toString().split('.')[1]),
value: type,
))
.toList(),
)
I hope this is what you are looking for.

DropDownButton items in a variable

I'm trying to store the possible values for a DropDownButton in a variable.
Goal:
On the press of a button, I want a new list of Strings to be created and assigned as possible choices for the DropdownButton. To do so, I need to store the possible choices (list of DropdownMenuItem) in a variable.
This sample of code works:
static String defaultDropDownValue = 'Select your Network';
String dropdownValue = defaultDropDownValue;
[...]
new Flexible(
child: DropdownButton(
isExpanded: true,
value: dropdownValue,
onChanged: (String newValue) {
setState(() {
dropdownValue = newValue;
});
_checkSsid();
},
items: <String>[defaultDropDownValue, 'One', 'Two', 'Three', 'Four']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
),
),
[...]
Now, this sample of code does not work:
static String defaultDropDownValue = 'Select your Network';
String dropdownValue = defaultDropDownValue;
List<DropdownMenuItem> dropdownList = [defaultDropDownValue, 'one', 'two'].map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList();
[...]
new Flexible(
child: DropdownButton(
isExpanded: true,
value: dropdownValue,
onChanged: (String newValue) {
setState(() {
dropdownValue = newValue;
});
_checkSsid();
},
items: dropdownList,
),
),
[...]
The compiler returns the following error message:
Error: The argument type 'Null Function(String)' can't be assigned to
the parameter type 'void Function(dynamic)'. Try changing the type of
the parameter, or casting the argument to 'void Function(dynamic)'.
onChanged: (String newValue) {
I don't really understand the meaning of the message, nor its cause.
Becasue you don't explicitly define the Type for array in the second example,
You could try DropdownMenuItem<String> and DropdownButton<String> to explicit them.
static String defaultDropDownValue = 'Select your Network';
String dropdownValue = defaultDropDownValue;
List<DropdownMenuItem<String>> dropdownList = [defaultDropDownValue, 'one', 'two'].map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList();
[...]
new Flexible(
child: DropdownButton<String>(
isExpanded: true,
value: dropdownValue,
onChanged: (String newValue) {
setState(() {
dropdownValue = newValue;
});
_checkSsid();
},
items: dropdownList,
),
),
[...]
Referenced from DropdownButton's Documentation below:
The type T is the type of the value that each dropdown item represents. All the entries in a given menu must represent values with consistent types. Typically, an enum is used. Each DropdownMenuItem in items must be specialized with that same type argument.