Flutter DropdownButton: Build a Select Menu With Code

Coding Liquids blog cover featuring Sagnik Bhattacharya for the Flutter DropdownButton guide, with an open select menu, DropdownMenuItem options, and the selected value tracked in state.
Coding Liquids blog cover featuring Sagnik Bhattacharya for the Flutter DropdownButton guide.

A select menu is one of the most common form inputs — pick a country, a category, a size — and Flutter's DropdownButton handles it with a value-and-callback pattern that's easy to get almost right. The catch is the assertion that bites every newcomer: the current value must match one of the items exactly. This guide covers building the dropdown, tracking the value, generating items from a list, the form-aware DropdownButtonFormField, the new Material 3 DropdownMenu, and that value error, with paste-ready code.

The Complete Flutter Guide course thumbnail

The Complete Flutter Guide: Build Android, iOS and Web apps

Go from scratch to building industry-standard apps with Riverpod, Firebase, animations, REST APIs, and more.

Enrol now

Every snippet below is paste-ready against current stable Flutter. A dropdown is a selection input like the TextField, and it slots into the same forms.

Follow me on Instagram@sagnikteaches

We'll build a dropdown, track the value, generate items from data, validate it inside a form, and meet the Material 3 DropdownMenu.

Connect on LinkedInSagnik Bhattacharya

If you'd rather watch a form with dropdowns and validation built live, the channel covers real input flows step by step.

Subscribe on YouTube@codingliquids

Build a dropdown

DropdownButton takes a value bound to state, a list of DropdownMenuItem options, and an onChanged callback that updates the value. Make the state variable nullable so the field can start with nothing selected.

String? _size;

DropdownButton<String>(
  value: _size,
  hint: const Text('Choose a size'),
  items: const [
    DropdownMenuItem(value: 'S', child: Text('Small')),
    DropdownMenuItem(value: 'M', child: Text('Medium')),
    DropdownMenuItem(value: 'L', child: Text('Large')),
  ],
  onChanged: (value) => setState(() => _size = value),
)

The hint shows while nothing is chosen, and each item's value is what flows into onChanged. Because the menu is driven by the state variable, the selected label updates the moment you call setState.

Generate items from a list

Hard-coding items gets tedious. Map a data list to DropdownMenuItems so adding an option is a single edit to the source list.

final _countries = ['India', 'United Kingdom', 'United States'];

DropdownButton<String>(
  value: _country,
  items: _countries
      .map((c) => DropdownMenuItem(value: c, child: Text(c)))
      .toList(),
  onChanged: (value) => setState(() => _country = value),
)

This is the form you'll use most. Just make sure the list has no duplicate values — duplicates trip the same assertion as a mismatched value, since the dropdown can't tell two identical values apart.

The Complete Flutter Guide course thumbnail

Build complete, validated forms

The Complete Flutter Guide covers every input, validation, and full forms inside real apps.

Enrol now

The value assertion error

The most common dropdown error reads roughly "value != null: is not true" or complains that the value isn't among the items. DropdownButton requires its value to equal exactly zero or one of the item values.

It happens when you set a default that isn't in the list, when the items rebuild without the current value, or when two items share a value. The fix: keep the value null until the user picks, ensure the value matches one item by equality, and guarantee unique item values. If you load items asynchronously, leave the value null until the list arrives.

Validate inside a form

When the dropdown is part of a Form, swap DropdownButton for DropdownButtonFormField. It adds a validator and an InputDecoration, so it shows error text and participates in Form.validate just like a TextFormField.

DropdownButtonFormField<String>(
  value: _country,
  decoration: const InputDecoration(labelText: 'Country'),
  items: _countries
      .map((c) => DropdownMenuItem(value: c, child: Text(c)))
      .toList(),
  validator: (v) => v == null ? 'Please choose a country' : null,
  onChanged: (value) => setState(() => _country = value),
)

This is the right choice for any required selection in a form, giving consistent error styling with your text fields.

The Material 3 DropdownMenu

Material 3 adds DropdownMenu, which marries a text field with a dropdown and lets users type to filter. It uses DropdownMenuEntry items and an onSelected callback. Prefer it on new Material 3 apps that want a searchable selector; keep DropdownButton for the classic compact control.

Common mistakes

  • A value not in the items. The value must equal one item value exactly, or it asserts.
  • Duplicate item values. The dropdown can't distinguish them; keep values unique.
  • Non-nullable value with no default. Make it nullable so the field can start empty with a hint.
  • Not calling setState in onChanged. The selection won't update without it.
  • DropdownButton in a form. Use DropdownButtonFormField for validation and error text.

Frequently asked questions

How do I create a dropdown in Flutter?

Use DropdownButton with DropdownMenuItem options, a value bound to state, and an onChanged that updates it with setState.

Why does my Flutter DropdownButton throw a value assertion error?

The current value isn't among the items, or two items share a value. Make the value nullable, match one item exactly, and keep values unique.

How do I validate a dropdown in a Flutter form?

Use DropdownButtonFormField with a validator and InputDecoration; it joins Form.validate like a text field.

What is the difference between DropdownButton and DropdownMenu in Flutter?

DropdownButton is the classic control; DropdownMenu is the Material 3 text-field-style selector with type-to-filter and DropdownMenuEntry items.

Further reads

Keep going with the tutorials that pair with this guide:

Sources: Flutter documentation — DropdownButton, DropdownMenuItem, DropdownButtonFormField, and DropdownMenu / DropdownMenuEntry API references (docs.flutter.dev). Verified against current stable Flutter.