# Creating a Dynamic Dropdown Form Field in flutter

## Overview

In this post, we will discuss how to create a dynamic dropdown form field in Flutter. We will be using two `DropdownFormField()` widget. A region dropdown field and a district dropdown field.

A region is the USA equivalent of a state and a district is a sub-location within a region. These two fields along with other fields comprise our Farmer Register Form as shown in the screenshot below

![Updated Add Farmer Screen](https://drive.google.com/uc?id=1iErcTZmW5965gvPiyEmXQh-Qoglwgi9q align="left")

My goal is to filter the options in the district depending on the region selected by the user. The purpose of this methodology is to reduce the number of options in the district dropdown field.

## Region Dropdown Form Field

```Dart
class RegionDropdownFormField extends StatelessWidget {
  const RegionDropdownFormField({
    Key? key,
    required this.state,
  }) : super(key: key);

  final _AddFarmerScreenController state;

  @override
  Widget build(BuildContext context) {
    return Expanded(
      flex: 5,
      child: DropdownButtonFormField(
        focusNode: state.regionFocusNode,
        decoration: FormStyles.textFieldDecoration(labelText: 'Region'),
        onChanged: (String? value) {
          state.setState(() {
            state.dropdownMenuItems = state._districtItem(value!);
            state.value = state.dropdownMenuItems!.first.value;
          });
        },
        validator: state.farmer.validateRequiredField,
        onSaved: state.farmer.saveFarmerCategory,
        items: Region.all
            .map((e) => DropdownMenuItem(
                  child: Text(e),
                  value: e,
                ))
            .toList(),
      ),
    );
  }
}
```

When the user selects an option from the `RegionDropdownFormField()` the `onChanged:` function will be triggered.

```Dart
(String? value) {
          state.setState(() {
            state.districtDropdownMenuItems = state._getDistrictItems(value!);
            state.districtValue = state.districtDropdownMenuItems!.first.value;
          });
        }
```

This function calls `setState()` since we want the UI to update. Within `setstate()`, `state.districtDropdownMenuItems = state._getDistrictItems(value!);` creates a list of `dropdownMenuItem()` based on the value selected by the user. `state.districtDropdownMenuItems` will be assigned to the `items:` property of the `DistrictDropdownFormField()`.

`state.districtValue = state.districtDropdownMenuItems!.first.value;` selects the first value of the newly created `state.districtDropdownMenuItems`. This variable will be assigned to the `value:` property of the `DistrictDropdownFormField()`. Failure to do this will create the below error.

```Dart
════════ Exception caught by widgets library ═══════════════════════════════════
The following assertion was thrown building Builder(dirty, dependencies: [_FocusMarker]):
There should be exactly one item with [DropdownButton]'s value: District 6. 
Either zero or 2 or more [DropdownMenuItem]s were detected with the same value
'package:flutter/src/material/dropdown.dart':
Failed assertion: line 850 pos 15: 'items == null || items.isEmpty || value == null ||
              items.where((DropdownMenuItem<T> item) {
                return item.value == value;
              }).length == 1'
```

## District Dropdown FormField

```Dart
class DistrictDropdownFormField extends StatelessWidget {
  const DistrictDropdownFormField({
    Key? key,
    required this.state,
  }) : super(key: key);

  final _AddFarmerScreenController state;

  @override
  Widget build(BuildContext context) {
    return Expanded(
      flex: 5,
      child: DropdownButtonFormField(
        focusNode: state.districtFocusNode,
        decoration: FormStyles.textFieldDecoration(labelText: 'District'),
        onChanged: (value) =>
            state._handleDropdownOnChanged(state.districtFocusNode),
        validator: state.farmer.validateRequiredField,
        onSaved: state.farmer.saveDistrict,
        value: state.districtValue,
        items: state.districtDropdownMenuItems,
      ),
    );
  }
}
```

This widget is a typical `DropdownFormField()` but note, `value: state.districtValue`, and `items: state.districtDropdownMenuItems,` are dependent on the region selected in the `DistrictDropdownFormField()`.

## Wrap Up

In this post, we discussed how to create a dynamic dropdown form field.

## Connect with me

Thank you for reading my post. Feel free to follow me for more flutter tips and tricks or connect with me on [LinkedIn](https://www.linkedin.com/in/curtlycritchlow/) and [Twitter](https://twitter.com/CritchlowCurtly). You can also [buy me a book](https://www.buymeacoffee.com/curtlycritchlow) to show your support.
