Home > Software engineering >  How can I make a multi level dependable dropdown List in Flutter?
How can I make a multi level dependable dropdown List in Flutter?

Time:08-24

I have been working on having two dropdown buttons that are meant for the user to easily pick the car model and its respective make. Below is the code snippet of the static lists that I have. Any feedback is highly appreciated.

final List<String> carModel = [
    'Audi',
    'BMW',
    'Chevrolet',
    'Chrysler',
    'Daihatsu',
    'Ford',
    'Hino',
    'Honda',
    'Isuzu',
    'Jaguar',
    'Jeep',
    'Landrover',
    'Lexus',
    'Mazda',
    'Mercedes',
    'Mitsubishi',
    'Nissan',
    'Peugeot',
    'Porsche',
    'Subaru',
    'Suzuki',
    'Toyota',
    'UD',
    'Volkswagen',
    'Volvo'
  ];
  final List<String> audiMake = [
    'A3',
    'A4',
    'A5',
    'A6',
    'A7',
    'A8',
    'Q3',
    'Q5',
    'Q7',
    'Q8',
    'R8',
    'TT',
  ];
  final List<String> bmwMake = [
    '1 Series',
    '2 Series',
    '3 Series',
    '4 Series',
    '5 Series',
    '6 Series',
    '7 Series',
    '8 Series',
    'M2',
    'M3',
    'M4',
    'M5',
    'M6',
    'X1',
    'X2',
    'X3',
    'X4',
    'X5',
    'X6',
    'X7',
    'Z4',
    'i3',
    'i8',
  ];

Here is the code that I have been working in bringing the functionality of the dropdown buttons to work:

 DropdownButton<String>(
                value: selectedCarModel,
                items: carModel.map((e) {
                  return DropdownMenuItem<String>(
                    value: e,
                    child: Text('$e'),
                  );
                }).toList(),
                onChanged: (val) {
                  setState(() {
                    selectedCarModel = val!;
                  });
                }),
            const SizedBox(
              height: 10,
            ),
            DropdownButton<String>(
                value: selectedCarMake,
                items: carMake.map((e) {
                  return DropdownMenuItem<String>(
                    value: e,
                    child: Text('$e'),
                  );
                }).toList(),
                onChanged: (val) {

                  carMake = val == 'Audi' ? audiMake : bmwMake;
                  setState(() {
                    selectedCarMake = val!;
                  });
                }),

CodePudding user response:

The concept using multi dropdown button will be second dropdown always depend on 1st dropdown value. It is necessary to make dropdown button nullable. So if the 1st dropdown button change, Second dropdown button must have null, else it will provide error based if 1st dropdown button selected something and second dropdown button doesn't contain that value. OK code works better than my explanations.

Let's simplify the process using Map.

class MultiLevelDropDownExample extends StatefulWidget {
  const MultiLevelDropDownExample({Key? key}) : super(key: key);

  @override
  State<MultiLevelDropDownExample> createState() =>
      _MultiLevelDropDownExampleState();
}

class _MultiLevelDropDownExampleState extends State<MultiLevelDropDownExample> {
  final List<String> audiMake = [
    'A3',
    'A4',
  ];
  final List<String> bmwMake = [
    '1 Series',
    '2 Series',
  ];

  String? selectedCardModel;
  String? selectedMake;

  late Map<String, List<String>> dataset = {
    'Audi': audiMake,
    'BMW': bmwMake,
  };

  onCarModelChanged(String? value) {
    //dont change second dropdown if 1st item didnt change
    if (value != selectedCardModel) selectedMake = null;
    setState(() {
      selectedCardModel = value;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          DropdownButton<String?>(
              value: selectedCardModel,
              items: dataset.keys.map((e) {
                return DropdownMenuItem<String?>(
                  value: e,
                  child: Text('$e'),
                );
              }).toList(),
              onChanged: onCarModelChanged),
          const SizedBox(
            height: 10,
          ),
          DropdownButton<String?>(
              value: selectedMake,
              items: (dataset[selectedCardModel] ?? []).map((e) {
                return DropdownMenuItem<String?>(
                  value: e,
                  child: Text('$e'),
                );
              }).toList(),
              onChanged: (val) {
                setState(() {
                  selectedMake = val!;
                });
              }),
          //
        ],
      ),
    );
  }
}
  • Related