control & disable a dropdown button in flutter? - flutter

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

Related

Flutter: disable DropdownButtonFormField option

I have this widget:
DropdownButtonFormField<String>(
hint: Text(translate('payments.select_frequency')),
value: frequency,
items: frequencies.map((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(
translate("expense.$value"),
style: TextStyle(
color: disabledFrequencies.contains(value) ? Colors.grey : null,
),
),
);
}).toList(),
onChanged: (value) async {
if (!disabledFrequencies.contains(value)) {
setState(() {
frequency = value;
});
}
},
validator: (value) {
if (value == null) {
return translate('fill_field');
}
return null;
},
);
This generates something like this:
Here I should be able to just click the first option but I can select any of them. I opened this issue a while ago in Flutter repo and they mentioned it's not an issue.
What's the option then?
There is enable property on DropdownMenuItem control the tap accessibility.
return DropdownMenuItem<String>(
value: value,
enabled: !disabledFrequencies.contains(value), //this
onTap: () {
Whether or not a user can select this menu item.
Defaults to true.

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

In multiple dropdown menu, how to disable an option if already selected in Flutter?

I have 4 different dropdown fields with 5 options and I want to disable/remove an option from other fields if the option is already selected.
Screenshot:
Screenshot 1
Screenshot 2
DropDown Menu Code:
String opemo1, opemo2, opemo3, opemo4;
List<String> emoji = [
"❤️",
"🤩",
"✌️",
"😂",
"😡",
];
DropdownButtonFormField(
validator: (value) =>
value == null ? 'required' : null,
hint: Text('❤️'),
value: opemo1,
icon: Icon(Icons.arrow_drop_down),
iconSize: 36,
isExpanded: true,
style: TextType.regularDarkText,
onChanged: (newValue) {
setState(() {
opemo1 = newValue;
pollDataController.setop1Emoji(newValue);
});
},
items: emoji.map((opemo1) {
return DropdownMenuItem(
value: opemo1,
child: Text(opemo1),
);
}).toList(),
),
To manage it you need to remove the selected emoji from List<String> emoji.
onChanged: (newValue) {
setState(() {
emoji.removeWhere((element) => element == newValue); /// This removed selected emoji.
opemo1 = newValue;
pollDataController.setop1Emoji(newValue);
});
},
You can replace your onChanged with this snippet.

Is it possible to create 50 dropdowns with less code and best practice?

I had to create 50 drop down. I used 50 variables. and 50 drop down. Is it possible to do it less code with best practice?
50 drop down button I created
DropdownButton<String>(
underline: SizedBox(),
value: selectSun,
iconEnabledColor: Palette.darkSilver,
onChanged: selectSun == 'Close'?null:
((value) {
setState(() {
selectSun = value;
});
}),
items: status.map((String value) {
return DropdownMenuItem<String>(
value: value,
child: CustomText(
text: value,
textColor: Palette.redButton,
),
);
}).toList(),
),
and also 50 variables
String selectSunFromHour = '09';
and also I set these data to firebase. I set one by one
You can try this:
Column(
children: languages.map<DropdownButton<String>>((String value) {
return DropdownButton<String>(
// Dropdown button init here, value is from languages
);
}).toList(),
),