Flutter Dropdownbutton selected value is not changing I am using dropdownbutton and mapping data using Product model but onchange my value is not changing
DropdownButtonHideUnderline(
child: DropdownButton<Product>(
hint: Text("Select Product"),
dropdownColor: Colors.white,
isExpanded: true,
items: _productController.products
.map((Product value) {
return new DropdownMenuItem<Product>(
value: value,
child: new Text(value.productName),
);
}).toList(),
onChanged: (Product val) {
_stockController.price.text = val.price;
_stockController.productName.text = val.productName;
selectedProduct = val.productName;
TextStyle(color: Colors.black);
setState(() {});
},
),
),
You didn't specify the value property of this widget. I think it should be set to value of selectedProduct.
And what the separate TextStyle? It is used as value for style property of widgets and cannot be used as standalone.
Related
I'm new to flutter, I have dropdown list it works fine and I able to get data from Api, but instead of put hint text, I want the first value of the list that fetch from api to be selected, here the value of dropdown is a String but if I put any string I get error
so I want to check if _level is null then read from enquiryController.levelsList.first.name but I'm getting this error
child: DropdownButton<String>(
autofocus: true,
isDense: false,
value: _level,
items: enquiryController.levelsList.map((item) {
return new DropdownMenuItem(
child: new Text(item.name),
value: item.id,
);
}).toList(),
onChanged: (value) {
_level = value;
enquiryController.setLevelIndex(value, true);
},
isExpanded: true,
underline: SizedBox(),
),
),
For the first time you have to provide an initial value to _level which match to your list item enquiryController.levelsList. If _level value did not match with any list item of enquiryController.levelsList then it throw the above error.
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.
DropdownButton value is not updating after selecting values from DropdownItems. How to update default value with _selectedLocation?
The variables i use:
String? stateToCountry;
List? stateID;
List? cityJson;
Position? _position;
String? currentAddress;
Placemark? place;
DropdownButton(
hint:_selectedLocation==null ? Text('Dropdown') : Text(
_selectedLocation.toString(),
style: TextStyle(color: Colors.black),
),
isExpanded: true,
iconSize: 30,
elevation: 16,
underline: Container(
height: 2,
color: Colors.deepPurpleAccent,
),
style: TextStyle(color: Colors.deepPurple, fontSize: 20.0),
itemHeight: 50,
items: countrylist!.map((location){
return DropdownMenuItem(
value: location,
child: new Text(location["name"].toString()),
);
}).toList(),
onChanged: (newValue){
setState(() {
_selectedLocation=newValue as String?;
});
},
),
Dropdownbutton works as follows:
T represent a generic type, so you can pass a bool, String, double, YourCustomModel etc.
The Dropdownbutton needs 3 things:
The value T
A List<T> with the options,
The onChanged Function, which pass you the T value you select.
The widget, know which value is selected according as his instance,
each object has an hashCode property which identify it from other objects,
When you select an option, you must keep that instance.
That instance should be in your list, for example
final list=<String>[
'Hello', /// hashCode 1
'good bye', /// hashCode 2
'bye bye' /// hashCode 3
];
When you select one, this is pass through the onChanged, let's say you select the first option:
onChanged:(value){
print(value.hashCode); /// output value: 1
// you must keep that instance with the same type `T`
_selectedValue=value;
}
So now, your _selectedValue will be:
print(_selectedValue.hashCode);/// /// output value: 1
print(_selectedValue); /// output value: 'Hello'
You need to set the value property,
DropdownButton(
value: _selectedLocation,
onChanged:(newValue){
setState(() {
_selectedLocation=newValue;
});
}
I am new to Flutter, I want to create a dropdown list of icons and text in TextformField in Flutter. Like bank icon with its name. Please see the screenshot and suggest me any code. Thank you in advance. Please help.
Probably use DropdownButton class, https://api.flutter.dev/flutter/material/DropdownButton-class.html
On the documentation page you can see there is an example code that does not include an Icon.
You can add an icon to the dropdown items by changing the items parameter to have a Row wrapping an Icon and Text widget.
See: https://dartpad.dev/b742bde3465a616f8787c434415c9e3e?null_safety=true
items: <String>['One', 'Two', 'Free', 'Four']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Row(
children: [
Icon(Icons.close),
Text(value),
],
),
);
}).toList(),
...
//custom object
class Item{
String name; //set the item name
Icon icon; //set corresponding icon
}
Item selectedItem;
List<Item> itemList = []; //create a list of the items, you need to add items into it first
DropdownButton<Item>(
isExpanded: true,
hint: new Text("Select Item"),
value: selectedItem ,
icon: Icon(Icons.arrow_drop_down_circle),
iconSize: 24,
elevation: 16,
style: TextStyle(color: Colors.blueAccent),
underline: Container(
height: 2,
color: Colors.blue,
),
onChanged: (Item newValue) {
setState(() {
selectedItem = newValue;
});
},
items: itemList.map<DropdownMenuItem<Item>>((Item value) {
return DropdownMenuItem<Item>(
value: value,
child: Row(
//set alignment here
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Icon(value.icon), //in here you can display the icon
Text(value.name), //name of the item
],
);
}).toList(),
)
I wanted to control a drop-down button and make it unclickable using a button.
Is there any way to make it disable. Basically not allowing it able to change.
new DropdownButton(
value: animalName,
items: animals.map(
(String value) {
return new DropdownMenuItem<String>(
value: value,
child: new Text('$value'),
);
},
).toList(),
onChanged: (value) {
setState(() {
animalName = value;
});
},
),
So this is the code I currently use on the drop-down button, but i cant disabled it.
Found this in the DropdownButton docs:
If items or onChanged is null, the button will be disabled, the down arrow will be grayed out, and the disabledHint will be shown (if provided)
DropdownButton(
onChanged: null,
items: [...],
)
This isn't what you want to hear, but I don't think there's currently an easy way. I experimented with simply removing all the items and that causes a nice little crash. Maybe worth raising an issue with the flutter people on github...
There is an alternative that may be good enough for you for now. If you wrap your DropdownButton in an IgnorePointer, when you want it to be disabled you can change IgnorePointer's ignoring property to true.
That way if the user taps on it, it won't do anything.
But you'll probably want to indicate to the user somehow that it's disabled as well, something like setting the hint text (as it's grey).
child: new IgnorePointer(
ignoring: true,
child: new DropdownButton(
hint: new Text("disabled"),
items: ["asdf", "wehee", "asdf2", "qwer"].map(
(String value) {
return new DropdownMenuItem<String>(
value: value,
child: new Text('$value'),
);
},
).toList(),
onChanged: (value) {},
),
You can make DropdownButtonFormField or DropdownButton disabled if set onChanged to null, and if you want that dropdown still shows selected value you must set disabledHint. For example:
DropdownButtonFormField<String>(
disabledHint: Text(_selectedItem),
value: _selectedItem,
onChanged: enabled ? (value) => setState(() => _selectedItem = value) : null,
items: items.map<DropdownMenuItem<String>>((item) {
return DropdownMenuItem(
value: item,
child: Text(item),
);
}).toList(),
)
Just wrap it with IgnorePointer widget to make DropdownButton disable
IgnorePointer(
ignoring: enabled,
child: new DropdownButton(
value: animalName,
items: animals.map(
(String value) {
return new DropdownMenuItem<String>(
value: value,
child: new Text('$value'),
);
},
).toList(),
onChanged: (value) {
setState(() {
animalName = value;
});
},
),
);
If items or onChanged is null, the button will be disabled, the down
arrow will be grayed out, and the disabledHint will be shown (if
provided)
So something like this should work:
DropdownButton<String>(
...
onChanged: this.enabled ? (id) => setState(() => this.id = id) : null,
)
okay, i found a trick that satisfied me
i wanted it hide/show the DropdownButton depending on CheckboxListTile
in StatefulWidget Class
first create a function ex:
_buildDropDown(bool enable) {
if (enable) {
return DropdownButton<String>(
hint: Text("Hint"),
items: <String>[
'item 1',
'item 2',
'item 3',
].map((String value) {
return new DropdownMenuItem<String>(
value: value,
child: new Text(value),
);
}).toList(),
onChanged: (value) {},
);
} else { // Just Divider with zero Height xD
return Divider(color: Colors.white, height: 0.0);
}
}
and now in build
bool enable = true;
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
CheckboxListTile(
title: const Text('Switcher'),
selected: true,
value: enable,
onChanged: (bool value) {
setState(() {
enable = value;
});
},
),
_buildDropDown(enable),
],
);
}
now every time you change enable it will display and hide the DropdownButton
DropdownButtonFormField(
onChange: isDisable ? null : (str){
},
disabledHint: isDisable ? null : Text('Your hint text'),
...
)
For disable
onChange: null
For disable Caption
disabledHint: Text('Your hint text')
//add widget'AbsorbPointer' true-disable,false-enable
// isEditable = ture
AbsorbPointer(
absorbing: isEditable
DropdownButton(
onChanged: null,
items: [...],
)
)
Simple:
decoration:InputDecoration(enabled: false),