I implemented a two levels of dropdown buttons where button# 2 depends on the choice of button #1. first drop down is a list of countries, depending on the user's selection of the country, a list of cities will be available in the second drop down. The main question is about the link between the two drop-downs, I am using a chain of if-statements to tell the code that if I choose country x, display cities of x etc. In the example code below I am including only 6 countries, so writing if statements is still clean and manageable, but what if the list of countries goes to 150? will I need to write 150 lines of if-statements to link countries to their cities? Is there a smarter way to do this? can I exploit the similarities in the country name and the name of the list containing its cities? e.g. 'USA' and 'cityUSA'
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String? dropdownValue;
String? dropdownCity;
List<String> selectedCities=[];
String? selectedCountry;
@override
Widget build(BuildContext context) {
final List<String> country = ['USA', 'Egypt', 'Spain', 'Mexico', 'Russia', 'China'];
final List<String> cityEgypt =['Cairo', 'Alexandria'];
final List<String> cityUSA = ['Houston', 'Dallas'];
final List<String> citySpain = ['Madrid', 'Barcelona'];
final List<String> cityMexico = ['Cancun', 'Mexico City'];
final List<String> cityRussia=['Moscow', 'Saint Petersburg'];
final List<String> cityChina = ['Gowanzo', 'Beijing'];
return MaterialApp(
title: 'Drop down fun',
home: Scaffold(
backgroundColor: Colors.greenAccent,
body:Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Text('Please choose your location', style:TextStyle(fontWeight: FontWeight.bold, fontSize: 25)),
),
Padding(
padding: const EdgeInsets.all(10.0),
child: DropdownButton<String>(
value: dropdownValue,
icon: Icon(Icons.map),
disabledHint: Text('Choose country first'),
style:TextStyle(color: Colors.black, fontSize: 15) ,
onChanged: (String? newValue) {
setState(() {
dropdownValue = newValue;
selectedCountry = dropdownValue;
dropdownCity = null;
if(selectedCountry=='Egypt'){selectedCities=cityEgypt;}
else if(selectedCountry=='USA'){selectedCities=cityUSA;}
else if(selectedCountry=='Spain'){selectedCities=citySpain;}
else if(selectedCountry=='Mexico'){selectedCities=cityMexico;}
else if(selectedCountry=='Russia'){selectedCities=cityRussia;}
else if(selectedCountry=='China'){selectedCities=cityChina;}
});
},
items: country.map((String item){
return DropdownMenuItem<String>(
value: item,
child: Container(
color: Colors.greenAccent,
child: Text(item),
),
);
}
).toList()
),
),
Padding(
padding: const EdgeInsets.all(10.0),
child: DropdownButton<String>(
value: dropdownCity,
icon: Icon(Icons.map),
style:TextStyle(color: Colors.black, fontSize: 15) ,
onChanged: (String? newValue) {
setState(() {
dropdownCity = newValue;});
},
items: selectedCities.map((String item){
return DropdownMenuItem<String>(
value: item,
child: Container(
color: Colors.greenAccent,
child: Text(item),
),
);
}
).toList()
),
),
],
),
),);
}
}
Usually, in any language not specific of dart or being a flutter dropdown button functionality, in such cases you relay over the data encapsulation which you will prepare a list of countries objects, each of them contains id, name and a list of their own cities
class Country {
int id;
String name;
List<City> cities;
}
class City {
int id;
String name;
}
so In such case you will have a dropdown of Country not a String
DropdownButton<Country>
and instead of long "if-else if-else ... else", you will have a direct mapping of cities
selectedCities = selectedCountry.cities