I'm newbie with flutter, can someone help me ? when I choose first dropdown, and choose the second dropdown, and then choose again the first dropdown, i get freeze error, I'm already set the variable list empty, but still not working, i get error :
there should be exactly one item with dropdownbutton 's value either zero or 2 or more [DropdownMenuItem]s were detected with the same value
this my code :
main.dart
import 'package:flutter/material.dart';
import 'package:perhitungan_pkt_kgb/data.dart';
class HitungPkt extends StatefulWidget {
const HitungPkt({super.key});
@override
State<HitungPkt> createState() => _HitungPktState();
}
class _HitungPktState extends State<HitungPkt> {
@override
Widget build(BuildContext context) {
return Form(
child: Column(
children: [
_buildDropdown(
label: 'Gol',
items: Data.gol.cast<Map<String, dynamic>>(),
onChanged: (String? newValue) {
setState(() {
// value dropdown nya kita masukan ke sebuah variabel
Data.golValue = newValue;
Data.vehicle?.clear();
Data.vehicle = Data.cekgol();
});
}),
if (Data.vehicle != null)
_buildDropdown(
label: 'Vechile',
items: Data.vehicle!.cast<Map<String, dynamic>>(),
onChanged: (String? newValue) {
setState(() {
// value dropdown nya kita masukan ke sebuah variabel
Data.vehicleValue = newValue;
});
}),
],
),
);
}
Widget _buildDropdown({
required String label,
required List<Map<String, dynamic>> items,
required void Function(String?) onChanged,
String? value,
}) {
return DropdownButtonFormField<String>(
decoration: InputDecoration(
labelText: label,
hintStyle: const TextStyle(color: Colors.blue),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: const BorderSide(color: Colors.blue),
),
focusedBorder: OutlineInputBorder(
borderSide: const BorderSide(color: Colors.blue),
borderRadius: BorderRadius.circular(10),
),
enabledBorder: OutlineInputBorder(
borderSide: const BorderSide(color: Colors.blue),
borderRadius: BorderRadius.circular(10),
),
errorBorder: OutlineInputBorder(
borderSide: const BorderSide(color: Colors.blue),
borderRadius: BorderRadius.circular(10),
),
),
value: value,
items: items.map((item) {
return DropdownMenuItem<String>(
value: item['value'] as String,
child: Text(item['label'] as String),
);
}).toList(),
onChanged: onChanged);
}
}
data.dart
class Data{
static const List gol = [
{'value': 'Car', 'label': 'Car'},
{'value': 'Bus', 'label': 'Bus'},
{'value': 'Plane', 'label': 'Plane'}
];
static String? golValue;
static String? vehicleValue;
static List? vehicle;
static List cekgol() {
if (golValue == 'Car') {
return [
{'value': 'car1', 'label': 'car1'},
{'value': 'car2', 'label': 'car2'},
{'value': 'car3', 'label': 'car3'},
{'value': 'car4', 'label': 'car4'},
{'value': 'car5', 'label': 'car5'}
];
} else if (golValue == 'Bus') {
return [
{'value': 'Bus1', 'label': 'Bus1'},
{'value': 'Bus2', 'label': 'Bus2'},
{'value': 'Bus3', 'label': 'Bus3'},
{'value': 'Bus4', 'label': 'Bus4'}
];
} else if (golValue == 'Plane') {
return [
{'value': 'Plane1', 'label': 'Plane1'},
{'value': 'Plane2', 'label': 'Plane2'},
{'value': 'Plane3', 'label': 'Plane3'},
{'value': 'Plane4', 'label': 'Plane4'},
{'value': 'Plane5', 'label': 'Plane5'}
];
} else {
return [];
}
}
}
The issue arises because you're likely setting the value of your DropdownButtonFormField to a value that isn't present in the items list you provide. When you change the first dropdown (Gol), you correctly clear the vehicle list, but you're not resetting the vehicleValue. This means the second dropdown tries to render with a vehicleValue that no longer exists in the newly populated vehicle list, causing the error.
class Data {
static const List gol = [
{'value': 'Car', 'label': 'Car'},
{'value': 'Bus', 'label': 'Bus'},
{'value': 'Plane', 'label': 'Plane'}
];
static String? golValue;
static String? vehicleValue;
static List? vehicle;
static List cekgol() {
if (golValue == 'Car') {
return [
{'value': 'car1', 'label': 'car1'},
{'value': 'car2', 'label': 'car2'},
{'value': 'car3', 'label': 'car3'},
{'value': 'car4', 'label': 'car4'},
{'value': 'car5', 'label': 'car5'}
];
} else if (golValue == 'Bus') {
return [
{'value': 'Bus1', 'label': 'Bus1'},
{'value': 'Bus2', 'label': 'Bus2'},
{'value': 'Bus3', 'label': 'Bus3'},
{'value': 'Bus4', 'label': 'Bus4'}
];
} else if (golValue == 'Plane') {
return [
{'value': 'Plane1', 'label': 'Plane1'},
{'value': 'Plane2', 'label': 'Plane2'},
{'value': 'Plane3', 'label': 'Plane3'},
{'value': 'Plane4', 'label': 'Plane4'},
{'value': 'Plane5', 'label': 'Plane5'}
];
} else {
return [];
}
}
}
class HitungPkt extends StatefulWidget {
const HitungPkt({super.key});
@override
State<HitungPkt> createState() => _HitungPktState();
}
class _HitungPktState extends State<HitungPkt> {
@override
Widget build(BuildContext context) {
return Form(
child: Column(
children: [
_buildDropdown(
label: 'Gol',
items: Data.gol.cast<Map<String, dynamic>>(),
onChanged: (String? newValue) {
setState(() {
Data.golValue = newValue;
Data.vehicle?.clear();
Data.vehicle = Data.cekgol();
Data.vehicleValue = null; // Reset vehicleValue here!
});
},
),
if (Data.vehicle != null)
_buildDropdown(
label: 'Vechile',
items: Data.vehicle!.cast<Map<String, dynamic>>(),
onChanged: (String? newValue) {
setState(() {
Data.vehicleValue = newValue;
});
},
),
],
),
);
}
Widget _buildDropdown({
required String label,
required List<Map<String, dynamic>> items,
required void Function(String?) onChanged,
}) {
return DropdownButtonFormField<String>(
decoration: InputDecoration(
labelText: label,
hintStyle: const TextStyle(color: Colors.blue),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: const BorderSide(color: Colors.blue),
),
focusedBorder: OutlineInputBorder(
borderSide: const BorderSide(color: Colors.blue),
borderRadius: BorderRadius.circular(10),
),
enabledBorder: OutlineInputBorder(
borderSide: const BorderSide(color: Colors.blue),
borderRadius: BorderRadius.circular(10),
),
errorBorder: OutlineInputBorder(
borderSide: const BorderSide(color: Colors.blue),
borderRadius: BorderRadius.circular(10),
),
),
value: (label == "Gol")
? Data.golValue
: Data.vehicleValue, // Use ternary for value
items: items.map((item) {
return DropdownMenuItem<String>(
value: item['value'] as String,
child: Text(item['label'] as String),
);
}).toList(),
onChanged: onChanged,
);
}
}