0

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

Md. Yeasin Sheikh
  • 54,221
  • 7
  • 29
  • 56
GrandMagus
  • 600
  • 3
  • 12
  • 37

2 Answers2

1

This is a great use case for a switch statement. Define your cases for each car maker according to this example:

String _maker;
List chosenMakerModel;

switch (_maker) {
  case 'Audi':
   chosenMakerModel = modelAudi; 
    break;
  case 'BMW':
   // implement logic:
    break;
  case 'OTHER MANUFACTURER':
    // implement logic;
    break;
 }

Using the example code above use chosenMakerModel instead of modelAudi

Jahn E.
  • 1,228
  • 3
  • 6
  • 21
  • 1
    Yeah I actually used a switch case but I forgot to return something for UI to render it, like case 'Audi': `return` chosenMakerModel = modelAudi;, am I correct or not? Thanks for making me realize my mistake! – GrandMagus Nov 23 '21 at 15:24
  • 1
    @GrandMagus A return statment should not be required. In Dart, a return statement immediately ends the function's execution, and therefore should break out of the switch statement. Please let me know if it works for you by accepting my answer :) – Jahn E. Nov 23 '21 at 15:32
  • I went with the switch case, it's more clear for me to use, thanks. Now I have another issue tho. :) – GrandMagus Nov 23 '21 at 16:28
  • @GrandMagus Of course you have to handle the case that the user is selecting the 2nd first - which is another topic in my opinion, which I therefore did not answered to make it more concise ;) – Jahn E. Nov 23 '21 at 17:16
0

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);
            });
          },
        ),
      ],
    ));
  }
}
Md. Yeasin Sheikh
  • 54,221
  • 7
  • 29
  • 56
  • 1
    I would prefer creating another list with models, and instead of carList i will use index and use `newList[index]`. But I think better will be using `Map>` modelName with carNames – Md. Yeasin Sheikh Nov 23 '21 at 15:25
  • @GrandMagus Depends on your preferences. Nested or longer ternary expressions can be very messy and thus should be replaced by if-else statements. If you use the latter or switch statements to control your code execution is up to you! Personally, I prefer switch statements :) – Jahn E. Nov 23 '21 at 15:38
  • 1
    Switch case require `const` value to check and for some cases we don't have it. And a second issue can occur that I've described on my answer, still this is accepted as answer and yes you can use if else the logic you want but for simple cases like this I prefer ternary . – Md. Yeasin Sheikh Nov 23 '21 at 16:49
  • Going through some testing and fully reading both answers again, I have to agree with @YeasinSheikh, I can still use the switch case but I have to have a default value and make the second selection `null` when switching the first selection again. Switched the accepted answer also. – GrandMagus Nov 23 '21 at 17:08