I have created the DropdownBotton inside the ListView and i have a list of values which needs to be displayed in the DropdownMenuItem.
I have 2 questions with respect to DropdownBotton,
There should be exactly one item with [DropdownButton]'s value: $ 5.50 Pineapple Jack (S).
Either zero or 2 or more [DropdownMenuItem]s were detected with the same value
'package:flutter/src/material/dropdown.dart':
Failed assertion: line 915 pos 15: 'items == null || items.isEmpty || value == null ||
items.where((DropdownMenuItem<T> item) {
return item.value == value;
}).length == 1'
Below is my code:
ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
physics: const ScrollPhysics(),
itemCount: snapshot.data!.length,
itemBuilder: (_, index) {
List<String> selectedItemValue = <String>[
("\$${snapshot.data![index].price} ${snapshot.data![index].productType.type1}"),
("\$${snapshot.data![index].price} ${snapshot.data![index].productType.type2}"),
("\$${snapshot.data![index].price} ${snapshot.data![index].productType.type3}")];
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
margin: const EdgeInsets.symmetric(
horizontal: 10, vertical: 5),
padding: const EdgeInsets.all(5.0),
child: DropdownButtonHideUnderline(
child: DropdownButton<String>(
value: dropdownValue,
items: selectedItemValue.map((dropValue) {
return DropdownMenuItem<String>(
value: dropValue,
child: Text(dropValue),
);
}).toList(),
onChanged:
(newDropdownValue) {
setState(() {
dropdownValue =
newDropdownValue!;
print(
'dropdown: $dropdownValue');
});
},
),
),
),
],
);
}
),
Please someone help me on this issue, Thanks in advance.
DropdownButton
's value should be unique among DropdownMenuItem
' values and There must be one DropDownMenuItem
in items which exactly matches the current value of the DropDownButton
.
in your case you are not setting DropdownButton
s value from selectedItemValue
. Therefore answers for your questions are,
set initial value of the DropdownButton
which you want's to be your default value from selectedItemValue
.
to avoid the error, move your DropdownButton
to separate StatefullWidget
(CustomDropdownButton
in this case.). change your code as follows.
ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
physics: const ScrollPhysics(),
itemCount: snapshot.data!.length,
itemBuilder: (_, index) {
List<String> selectedItemValue = <String>[
("\$${snapshot.data![index].price} ${snapshot.data![index].productType.type1}"),
("\$${snapshot.data![index].price} ${snapshot.data![index].productType.type2}"),
("\$${snapshot.data![index].price} ${snapshot.data![index].productType.type3}")];
final defaultValue = selectedItemValue[1];
return CustomDropdownButton(defaultValue:defaultValue, values: selectedItemValue, onItemSelected: (value) {print("Selected Item : $value");});
}
),
CustomDropdownButton
class
class CustomDropdownMenu extends StatefulWidget {
const CustomDropdownMenu(
{Key? key,
required this.defaultValue,
required this.values,
required this.onItemSelected})
: super(key: key);
final dynamic Function(String? selectedValue) onItemSelected;
final String defaultValue;
final List<String> values;
@override
_CustomDropdownMenuState createState() => _CustomDropdownMenuState();
}
class _CustomDropdownMenuState extends State<CustomDropdownMenu> {
late String dropdownValue;
@override
void initState() {
super.initState();
dropdownValue = widget.defaultValue;
}
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
margin: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
padding: const EdgeInsets.all(5.0),
child: DropdownButtonHideUnderline(
child: DropdownButton<String>(
value: dropdownValue,
items: widget.values.map((dropValue) {
return DropdownMenuItem<String>(
value: dropValue,
child: Text(dropValue),
);
}).toList(),
onChanged: (newDropdownValue) {
setState(() {
dropdownValue = newDropdownValue!;
});
widget.onItemSelected(newDropdownValue);
},
),
),
),
],
);
}
}