Reputation: 255
I am trying to use the dropdown menu in my flutter app but getting an error.
Here is the code:
List<String> items = ["Item1", "Item2", "Item3", "Item4"];
String selectedItem = "Item1";
DropdownButton<String>(
items: items.map(
(txt) {
return DropdownMenuItem<String>(
child: Text(
"$txt"
),
);
}
).toList(),
value: selectedItem,
)
In some questions, I saw that we have to initially set a variable to the value present inside our list. I have exactly done that but still getting an error.
Error Message:
There should be exactly one item with [DropdownButton]'s value: Item1.
Either zero or 2 or more [DropdownMenuItem]s were detected with the same value
'package:flutter/src/material/dropdown.dart':
Failed assertion: line 850 pos 15: 'items == null || items.isEmpty || value == null ||
items.where((DropdownMenuItem<T> item) {
return item.value == value;
}).length == 1'
What is the error here?
Kindly comment if more information is needed.
Upvotes: 4
Views: 4964
Reputation: 3
Visibility(
visible: isVisibleDitrict,
child: Column(
children: [
Center(
child: FutureBuilder<List<DataDsiricst>>(
future: _getDistrictData(stateCodeDPM),
builder: (context, snapshot) {
if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
}
if (snapshot.data == null) {
return const CircularProgressIndicator();
}
developer.log(
'@@snapshot' + snapshot.data.toString());
List list = snapshot.data
.map<DataDsiricst>((district) {
return district;
}).toList();
if (_selectedUserDistrict == null ||
list.contains(_selectedUserDistrict) ==
false) {
_selectedUserDistrict = list.first;
}
return Padding(
padding: const EdgeInsets.fromLTRB(
20, 10, 20.0, 0),
child: Column(
mainAxisAlignment:
MainAxisAlignment.start,
children: <Widget>[
const Text(
'Select District:',
),
DropdownButtonFormField<DataDsiricst>(
onChanged: (districtUser) =>
setState(() {
_selectedUserDistrict =
districtUser;
distCodeDPM = int.parse(
(districtUser.districtCode
.toString()));
print('@@@Districtuser' +
districtUser.districtName
.toString());
setState(() {});
}),
value: _selectedUserDistrict,
items: snapshot.data.map<
DropdownMenuItem<
DataDsiricst>>(
(DataDsiricst district) {
return DropdownMenuItem<
DataDsiricst>(
value: district,
child:
Text(district.districtName),
);
}).toList(),
/* items: [
...snapshot.data
.map(
(userDistricts) =>
DropdownMenuItem(
value: userDistricts,
child: Text(userDistricts
.districtName),
),
)
.toList()
],*/
),
],
),
);
}),
),
],
),
),
Model class : enter image description here
Upvotes: 0
Reputation: 1126
Here an example, the explanation in the code:
class _MyHomePageState extends State<MyHomePage> {
List<String> items = ["Item1", "Item2", "Item3", "Item4"];
String selectedItem = "Item1";
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Column(
children: [
Flex(direction: Axis.vertical, children:[
DropdownButton<String>(
value: selectedItem,
onChanged: (itemValue) { // update the selectedItem value
setState(() {
selectedItem = itemValue!;
});
},
items: items
.map<DropdownMenuItem<String>>((String value) => DropdownMenuItem<String>(
value: value, // add this property an pass the value to it
child: Text(value,)
)).toList(),
),
])
],
),
);
}
}
Upvotes: 5
Reputation: 35
List<String> items = ["Item1", "Item2", "Item3", "Item4"];
String selectedItem = "";
DropdownButton<String>(
items: items.map(
(txt) {
return DropdownMenuItem<String>(
child: Text("$txt"),
);
}
).toList(),
value: selectedItem==""null?"":selectedItem,
)
Upvotes: 1
Reputation: 2329
If you are loading the list from an api that returns list, look at what i did to debug the error.
Created a reusable widget that handle future response
Widget rangeLists(selectedValue) {
return FutureBuilder(
future: YourFuture,//this should return Future<List>
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Text('Loading...');
} else {
List<DropdownMenuItem<String>> categoriesItems = [
DropdownMenuItem(
child: Text(selectedValue),
value: selectedValue,
),
];
print('categoriesItems.last.value');
print(categoriesItems.last.value);
var snapshotAsMap = snapshot.data as List;
for (int i = 0; i < snapshotAsMap.length; i++) {
if (snapshotAsMap[i]['category'] != selectedValue) {
categoriesItems.add(
DropdownMenuItem(
child: Text(snapshotAsMap[i]['category']),
value: snapshotAsMap[i]['category'],
),
);
}
}
return Padding(
padding: const EdgeInsets.only(left: 18.0, right: 18, top: 10),
child: Container(
padding: EdgeInsets.only(left: 25, right: 25),
decoration: BoxDecoration(
border: Border.all(color: Colors.grey, width: 1),
borderRadius: BorderRadius.circular(25)),
child: DropdownButton<String>(
items: categoriesItems,
icon: const Icon(
Icons.expand_more,
color: Colors.grey,
),
iconSize: 24,
elevation: 16,
isExpanded: true,
style: const TextStyle(color: Colors.grey),
underline: SizedBox(),
onChanged: (value) {
setState(() {
widget.selectedValue = value;
});
},
value: selectedValue,
hint: Text('My courses'),
),
),
);
}
})};
2.Usage you can called it like this
String selectedValue="Select Here"
rangeLists(selectedValue)//call this as a widget in ur ui
It will handle all list from the backend u don't need to worry about the error any more
Upvotes: 0