Added enabled property and made onChanged optional for DropdownButton
DropdownButton and DropdownButtonFormField now support an explicit enabled property, and their onChanged callbacks are no longer required.
Summary
#
DropdownButton and DropdownButtonFormField now include
an enabled property to explicitly manage their interactive state,
and the onChanged callback is no longer marked as required.
Background
#
Previously, DropdownButton and DropdownButtonFormField didn't
have an enabled parameter.
The only way to disable the dropdown
(graying it out and making it non-interactive) was to
pass null to the required onChanged callback.
This led to unintuitive code when trying to
dynamically enable or disable the button,
forcing developers to write conditional expressions for the callback itself,
such as onChanged: condition ? (value) { ... } : null.
To improve this API, a dedicated enabled property was introduced,
and onChanged was made optional.
The enabled property is optional.
Making it mandatory introduces a massive breaking change that
breaks nearly every existing DropdownButton implementation in
the Flutter ecosystem.
Instead, to preserve backward compatibility,
if the enabled argument isn't explicitly provided,
the button determines its state by falling back to whether
onChanged is provided (that is, it's enabled if onChanged != null,
and disabled if onChanged == null).
The minor breaking change here is structural:
while the old conditional onChanged pattern technically
still works due to the fallback logic,
developers are encouraged to migrate to the clearer API by
explicitly using the enabled property.
Migration guide
#
If you previously disabled your DropdownButton by
conditionally passing null to onChanged,
migrate to the new enabled property.
This cleanly separates the state of the widget (enabled/disabled) from
its behavior (the callback).
To automatically migrate your code for simple cases
(such as statically passing null), run the following command:
dart fix --apply
Case 1: Statically disabled dropdown
#
For simple cases where a dropdown is permanently disabled,
you can now simply omit onChanged and use enabled: false.
Code before migration:
final disabledDropdown = DropdownButton<String>(
value: 'Option 1',
items: const [
DropdownMenuItem(value: 'Option 1', child: Text('Option 1')),
],
onChanged: null, // This was the only way to disable it
);
Code after migration:
final disabledDropdown = DropdownButton<String>(
value: 'Option 1',
items: const [
DropdownMenuItem(value: 'Option 1', child: Text('Option 1')),
],
onChanged: null, // This was the only way to disable it
enabled: false,
);
Case 2: Conditionally disabled dropdown
#
The recommended best practice is to separate the callback from
the interactive state by using the enabled property directly.
Code before migration:
final conditionalDropdown = DropdownButton<String>(
value: 'Option 1',
items: const [
DropdownMenuItem(value: 'Option 1', child: Text('Option 1')),
],
onChanged: condition ? (value) { ... } : null,
);
Code after migration:
final conditionalDropdown = DropdownButton<String>(
value: 'Option 1',
items: const [
DropdownMenuItem(value: 'Option 1', child: Text('Option 1')),
],
onChanged: condition ? (value) { ... } : null,
onChanged: (value) { ... },
enabled: condition,
);
Timeline
#
Landed in version: 3.44.0-1.0.pre-629
In stable release: Not yet
References
#API documentation:
Relevant issues:
Relevant PRs:
Unless stated otherwise, the documentation on this site reflects Flutter 3.44.0. Page last updated on 2026-06-02. View source or report an issue.