Change selection of dropdown button according to the choice from the previous one, Flutter

Issue

I have 2 DropdownButtonFormFields where I have a selection of cars. I need to change the second selection of buttons according to the car model user has chosen from the first selection in the DropdownButtonFormField (i.e. If a user chooses a Mercedes in the first one, in the DropdownButtonFormField below, I want to display only models of Mercedes and not, let’s say, Audi).

How can I achieve this? Here is the code:

String _make, _model;

/// List of cars and models
List<String> carList = [
    'Audi',
    'BMW',
    'Mercedes',
  ];
List<String> modelAudi = ['A6', 'A8', 'Q7',];
List<String> modelMercedes = ['E-Class', 'S-Class','Maybach'];
List<String> modelBMW = ['3-Series', 'X5', 'X7'];


/*two DropdownButtonFormFields, but the second one needs to match 
 it's car manufacturer selection from the carList selection
 (i.e. if you select Audi, it must only show the modelAudi list (A6,
 A8, Q7) in the second DropdownButtonFormField)
*/

 DropdownButtonFormField<String>(
          value: _make,
          items: carList
              .map((label) => DropdownMenuItem(
                    child: Text(label.toString()),
                    value: label,
                  ))
              .toList(),
          onChanged: (value) {
            setState(() {
              _make = value;
              print(value);
            });
          },
        ),
 
DropdownButtonFormField<String>(
  value: _model,

/* here is where I need to implement logic 
that maps out the model names that matches the car maker
*/
  items: modelAudi
      .map((label) => DropdownMenuItem(
            child: Text(label.toString()),
            value: label,
          ))
      .toList(),
  onChanged: (value) {
    setState(() {
      _model = value;
      print(value);
    });
  },
),                            

The DropDown for the first button:
enter image description here

And naturally because I have no logic behind it, I get this as the model selection whatever I chose from the car list, but I want it to map out only models from the car list you chose.

enter image description here

Solution

You can create a model selection method to handle this situation, like

  List<String> _selectModel(String? modelName) {
    return modelName == carList[0]
        ? modelAudi
        : modelName == carList[1]
            ? modelMercedes
            : modelBMW; // initally it will have modelBMW
  }

This will decide the second dropdown item. If you click to select the second drop down item 1st, it will through errors. To handle this situation, you need to update the second dropdown value as well. You can set the second dropdown value=null. Therefor we need to use nullable String for selection value.


class MyProfileState extends State<StatefulWidget> {
  String? _make, _model;

  /// List of cars and models
  List<String> carList = ['Audi', 'BMW', 'Mercedes'];
  List<String> modelAudi = ['A6', 'A8', 'Q7'];
  List<String> modelMercedes = ['E-Class', 'S-Class', 'Maybach'];
  List<String> modelBMW = ['3-Series', 'X5', 'X7'];

  List<String> _selectModel(String? modelName) {
    return modelName == carList[0]
        ? modelAudi
        : modelName == carList[1]
            ? modelMercedes
            : modelBMW;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Column(
      children: [
        DropdownButtonFormField<String>(
          value: _make,
          items: carList
              .map((label) => DropdownMenuItem(
                    child: Text(label.toString()),
                    value: label,
                  ))
              .toList(),
          onChanged: (value) {
            setState(() {
              _make = value;
              _model = null;
              print(value);
            });
          },
        ),
        DropdownButtonFormField<String>(
          value: _model,
          items: _selectModel(_make)
              .map((label) => DropdownMenuItem(
                    child: Text(label.toString()),
                    value: label,
                  ))
              .toList(),
          onChanged: (value) {
            setState(() {
              _model = value;
              print(value);
            });
          },
        ),
      ],
    ));
  }
}

Answered By – Yeasin Sheikh

Answer Checked By – David Marino (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published.