Due dropdown collegati: regione e provincia
Un classico dei form reali: il secondo menu dipende dalla scelta fatta nel primo.
Il pattern è semplice ma ha una trappola molto comune: quando cambi la regione devi azzerare la provincia, altrimenti il value del secondo dropdown non esisterà più nella nuova lista di items e l'app andrà in errore con un'asserzione.
Nota anche che il secondo dropdown passa onChanged: null finché non è stata scelta una regione: è il modo idiomatico per disabilitarlo.
class RegioneProvincia extends StatefulWidget {
const RegioneProvincia({super.key});
@override
State<RegioneProvincia> createState() => _RegioneProvinciaState();
}
class _RegioneProvinciaState extends State<RegioneProvincia> {
static const Map<String, List<String>> dati = {
'Lombardia': ['Milano', 'Bergamo', 'Brescia'],
'Lazio': ['Roma', 'Latina', 'Viterbo'],
'Sicilia': ['Palermo', 'Catania', 'Messina'],
};
String? _regione;
String? _provincia;
@override
Widget build(BuildContext context) {
final province = _regione == null ? <String>[] : dati[_regione]!;
return Column(
children: [
DropdownButtonFormField<String>(
initialValue: _regione,
isExpanded: true,
decoration: const InputDecoration(
labelText: 'Regione',
border: OutlineInputBorder(),
),
items: dati.keys
.map((r) => DropdownMenuItem(value: r, child: Text(r)))
.toList(),
onChanged: (valore) {
setState(() {
_regione = valore;
_provincia = null; // fondamentale: azzera la scelta precedente
});
},
),
const SizedBox(height: 16),
DropdownButtonFormField<String>(
initialValue: _provincia,
isExpanded: true,
decoration: const InputDecoration(
labelText: 'Provincia',
border: OutlineInputBorder(),
),
items: province
.map((p) => DropdownMenuItem(value: p, child: Text(p)))
.toList(),
onChanged: _regione == null
? null // disabilitato finché non scegli la regione
: (valore) => setState(() => _provincia = valore),
),
],
);
}
}
Risultato atteso
Il dropdown delle province è grigio e non cliccabile finché non si sceglie una regione; cambiando regione la provincia si svuota e mostra le nuove voci.