Currently I'm trying to implement dropdown using DropdownButton, but there is one problem.
In DropdownButton(), if value: is empty, error is not occurred but nothing change when choose.
if I assign an arbitrary String variable to value:, the following error will occur.
════════ Exception caught by widgets library ═══════════════════════════════════
The following assertion was thrown building StatefulBuilder(dirty, state: _StatefulBuilderState#65c7c):
Assertion failed:
..\…\material\dropdown.dart:915
items == null || items.isEmpty || value == null ||
items.where((DropdownMenuItem<T> item) {
return item.value == value;
}).length == 1
"There should be exactly one item with [DropdownButton]'s value: . \nEither zero or 2 or more [DropdownMenuItem]s were detected with the same value"
My code;
List<String> strings = <String>["Aa", "Bb", "Cc"];
String selectedString = "";
#override
Widget build(BuildContext c) { ....
showDialog( builder: (context) {
return Dialog(builder: (context, setState) {
return SingleChildScrollView(
child: Column( ....
DropdownButton<String>(
value: selectedString, // IF THIS IS NOT NULL, THE ERROR NOT APPEARD
hint: Text("Choose"),
items: strings.map((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
onChanged: (value) {
setState(() {
selectedString = value!;
});
},
),
........
You have to follow these three steps;
1. List<String> strings = <String>[" ","Aa", "Bb", "Cc"];
2. String selectedString = " ";
3. value: selectedString ,
This was easy to solve.
Flutter: There should be exactly one item with [DropdownButton]'s value
This answer says that selectedString value should be string that exists in strings. Like this
selectedString = "Aa";
You must have at least one value that is contained in the list of items
List strings = [" ","Aa", "Bb", "Cc"];
String selectedString = " "; or "Aa" or "Bb" <******** !!
value: selectedString ,
Related
I tried the solutions provided on the same question, but each question has its own case, so in my case i am trying to create drop down of countries list and before use it in the Scaffold widget i want to save it to an instance of type DropdownButton(), here is the code:
List<String> provinces = [
'عمان',
'إربد',
'الزرقاء',
'المفرق',
'الطفيلة',
'عجلون',
'معان',
'الكرك',
'مادبا',
'العقبة',
'البلقاء',
'جرش'
];
String dropDownValue = "";
final provincesField = DropdownButton<String>(
value: dropDownValue,
icon: Icon(Icons.keyboard_arrow_down),
items: provinces.map((String items) {
return DropdownMenuItem(value: items, child: Text(items));
}).toList(),
onChanged: (String? newValue) {
setState(() {
dropDownValue = newValue!;
});
},
);
Am not sure why its not accessing the list and consider it empty. Here is the full error:
The following assertion was thrown building RegistrationScreen(dirty, state: _RegistrationScreenState#b01ae):
There should be exactly one item with [DropdownButton]'s value: .
Either zero or 2 or more [DropdownMenuItem]s were detected with the same value
'package:flutter/src/material/dropdown.dart':
package:flutter/…/material/dropdown.dart:1
Failed assertion: line 882 pos 15: 'items == null || items.isEmpty || value == null ||
items.where((DropdownMenuItem<T> item) {
return item.value == value;
}).length == 1'
The error:
There should be exactly one item with [DropdownButton]'s value: one.
Either zero or 2 or more [DropdownMenuItem]s were detected with the same value
Indicates that in your list provinces it should contain the same value as your dropDownValue.
Which means, that your file should look like this:
String dropDownValue = "one";
List<String> provinces = [
"one", // <-- Notice we're adding the word "one" to the list since that's the value of `dropDownValue`
'عمان',
'إربد',
'الزرقاء',
'المفرق',
'الطفيلة',
'عجلون',
'معان',
'الكرك',
'مادبا',
'العقبة',
'البلقاء',
'جرش'
];
Here is a complete example:
class Test extends StatefulWidget {
const Test({Key? key}) : super(key: key);
#override
State<Test> createState() => _TestState();
}
class _TestState extends State<Test> {
List<String> provinces = [
"one", // <-- Notice wer're adding the word "one" to the list
'عمان',
'إربد',
'الزرقاء',
'المفرق',
'الطفيلة',
'عجلون',
'معان',
'الكرك',
'مادبا',
'العقبة',
'البلقاء',
'جرش'
];
#override
Widget build(BuildContext context) {
// make sure this is this value is in your list
String dropDownValue = "one";
final provincesField = DropdownButton<String>(
value: dropDownValue,
icon: Icon(Icons.keyboard_arrow_down),
items: provinces.map((String items) {
return DropdownMenuItem(value: items, child: Text(items));
}).toList(),
onChanged: (String? newValue) {
setState(() {
dropDownValue = newValue!;
});
},
);
return Container();
}
}
Try and replace the code instead of String dropDownValue.
var dropDownValue;
And items should have a value other than null.
in constructor (){
dropDownValue = provinces.first;
}
make sure a value is in your list
Exception has occurred.
_AssertionError ('package: flutter/src/material/dropdown.dart': Failed assertion: line 915 pos 15: 'items == null || items.isEmpty || value == null ||
items.where((DropdownMenuItem item) {
return item.value == value;
}).length == 1': There should be exactly one item with [DropdownButton]'s value: 0.
Either zero or 2 or more [DropdownMenuItem]s were detected with the same value)
Your "value" for DropdownButton should be set to 'null' or or be one from the values list.
DropdownButton(
value: null,
isDense: true,
onChanged: (String newValue) {
// somehow set here selected 'value' above whith
// newValue
// via setState or reactive.
},
items: ['yellow', 'brown', 'silver'].map((String value) {
return DropdownMenuItem(
value: value,
child: Text(value),
);
}).toList(),
),
Initialize the value object with some default value. Please note that the value should be one of the values contained by your collection.
String selectedArray = "ABC"; //This is the selection value. It is also present in my array.
final array = [“ABC”, “DEF”, “GHI”, “JKL”]; //This is the array for dropdown
During the process of my web-application I want the user to allow to make changes and save them. For that process I'm using SharedPreferences in order to store the changes. I have a list of titles called konzernDataTitle. In general this list is used to display my titles.
In order to change something I edit this list and "upload" it to my SharedPreferences. However, everything works fine but I cant get the new list prefsKonzernTitle into my DropDownButton. For that I'm using a FutureBuilder. The error is quite simple:
══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
[...]
The following assertion was thrown building FutureBuilder<List<DropdownMenuItem<String>>>(dirty,
state: _FutureBuilderState<List<DropdownMenuItem<String>>>#dcca3):
Assertion failed:
items == null || items.isEmpty || value == null ||
items.where((DropdownMenuItem<T> item) {
return item.value == value;
}).length == 1
"There should be exactly one item with [DropdownButton]'s value: MyTitle. \nEither zero or 2 or more
[DropdownMenuItem]s were detected with the same value"
The relevant error-causing widget was:
FutureBuilder<List<DropdownMenuItem<String>>>
FutureBuilder Function:
Future<List<DropdownMenuItem<String>>> getDropDownItems() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
bool prefsTitleExist;
var newList = List<String>.empty();
if (prefs.containsKey("prefsKonzernTitle")) {
var getPrefList = prefs.getStringList("prefsKonzernTitle");
newList = getPrefList!;
prefsTitleExist = true;
} else {
prefsTitleExist = false;
}
final actualList = prefsTitleExist ? newList : konzernDataTitle;
return actualList.map((data) {
return DropdownMenuItem<String>(
value: data,
child: Text(
data,
),
);
}).toList();
}
FutureBuilder Widget
FutureBuilder<List<DropdownMenuItem<String>>>(
future: getDropDownItems(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return const SizedBox();
}
return DropdownButton<String>(
value: dropdownValue,
items: snapshot.data,
onChanged: (String? newValue) {
setState(() {
dropdownValue = newValue!;
i = konzernDataTitle.indexOf(newValue);
titleController.text = konzernDataTitle[i];
linkController.text = konzernDataLink[i];
imageController.text = konzernDataImage[i];
colorController.text =
konzernDataColor[i].toString();
});
},
);
}),
I searched the problems inside the lists but all lists are exactly how they have to be.
So maybe you can help me out. Thanks for any kind of help. All questions will be answered in a few minutes.
^Tim
There should be exactly one item with [DropdownButton]'s value: MyTitle.
Either zero or 2 or more
[DropdownMenuItem]s were detected with the same value
The above error denotes dropdownValue does not match with any value available in dropdown menu item list or more than one value present in dropMenuItemList.
For the first case set dropdownValue = null on initialization and for the second case check menu item doesn't have duplication.
I implemented a DropDown which contains a list of items you can delete.
The Dropdown can't be displayed correctly after deleting the item and that causes the error but i don't know how to fix this. Help is highly appriciated!
The DropDown:
The items are a collection of documents queried from firebase.
Deleting the item removes it from firebase but i get the following error:
This is my code:
var selectedStand;
void deleteStand() {
DocumentReference ref = Firestore.instance
.collection('Standnamen')
.document(selectedStand);
ref.delete();
}
StreamBuilder<QuerySnapshot>(
stream: Firestore.instance.collection('Standnamen').snapshots(),
// ignore: missing_return
builder: (context, snapshot) {
if (!snapshot.hasData) {
Text("Loading");
} else {
List<DropdownMenuItem> standItems = [];
for (int i = 0; i < snapshot.data.documents.length; i++) {
DocumentSnapshot snap = snapshot.data.documents[i];
standItems.add(
DropdownMenuItem(
child: Text(
snap.documentID,
style: TextStyle(color: Colors.blue),
),
value: "${snap.documentID}",
)
);
}
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
DropdownButton(
items: standItems,
onChanged: (standValue) {
setState(() {
selectedStand = standValue;
});
},
value: selectedStand,
isExpanded: false,
hint: new Text(
"Choose stand to delete",
),
),
)
],
);
}
},
),
],
),
);
}
}
Detailed Error:
════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The following assertion was thrown building StreamBuilder<QuerySnapshot>(dirty, state: _StreamBuilderBaseState<QuerySnapshot, AsyncSnapshot<QuerySnapshot>>#46c06):
There should be exactly one item with [DropdownButton]'s value: example3.
Either zero or 2 or more [DropdownMenuItem]s were detected with the same value
'package:flutter/src/material/dropdown.dart':
Failed assertion: line 827 pos 15: 'items == null || items.isEmpty || value == null ||
items.where((DropdownMenuItem<T> item) {
return item.value == value;
}).length == 1'
The relevant error-causing widget was:
StreamBuilder<QuerySnapshot> file:///Users/darjusch/Developer/flutterProjects/sommerobst_app_beta/lib/screens/admin/admin_create_stand_screen.dart:67:13
When the exception was thrown, this was the stack:
#2 new DropdownButton (package:flutter/src/material/dropdown.dart:827:15)
#3 _AdminCreateStandScreenState.build.<anonymous closure> (package:sommerobst_app_beta/screens/admin/admin_create_stand_screen.dart:92:23)
#4 StreamBuilder.build (package:flutter/src/widgets/async.dart:509:81)
#5 _StreamBuilderBaseState.build (package:flutter/src/widgets/async.dart:127:48)
#6 StatefulElement.build (package:flutter/src/widgets/framework.dart:4619:28)
...
════════════════════════════════════════════════════════════════════════════════════════════════════
W/erobst_app_bet(20965): Reducing the number of considered missed Gc histogram windows from 119 to 100
════════ Exception caught by rendering library ═════════════════════════════════════════════════════
A RenderFlex overflowed by 99569 pixels on the bottom.
EDIT:
I tried your suggestion which sounds very logical but it did not work i still get the same error.
var selectedDoc;
DropdownButton(
items: standItems,
onChanged: (standValue) {
setState(() {
selectedStand = standValue;
selectedDoc = snapshot.data.documents.firstWhere(
(doc) => doc.documentID == selectedStand,
orElse: () => null,
);
});
},
value: selectedDoc?.documentID,
After deletion DropdownButton is given a value(selectedStand) that none of the DropdownMenuItems contain. So, first check if a document exists whose id is selectedStand otherwise set value to null.
// get the document with id as selectedStand. Will be null if it doesn't exist.
var selectedDoc = snapshot.data.documents.firstWhere(
(doc) => doc.documentID == selectedStand,
orElse: () => null,
);
DropdownButton(
// assign selectedDoc's id (same as selectedStand) if exists
// otherwise null
value = selectedDoc?.documentID,
// ...
),
The logic should not be in onChanged but outside of DropdownButton within the StreamBuilder.
selectedDoc = snapshot.data.documents.firstWhere(
(doc) => doc.documentID == selectedStand,
orElse: () => null,
);
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
DropdownButton(
items: standItems,
onChanged: (standValue) {
setState(() {
selectedStand = standValue;
});
},
value: selectedDoc?.documentID,
isExpanded: false,
hint: new Text(
"Choose stand to delete"
),
),
],
),
Alternatively you could set selectedStand = selectedDoc?.documentID right after finding selectedDoc, so that selectedStand will always have a valid value.
I guess the problem is that you are adding to the same variable without clearing it first which cause multiple element of items to be there with the same names. So I would suggest clear out the items in standItems right before you call the add function to add items outside the for loop.
I've seen other similar topics but it didn't help me. I'm not a programmer or have a strong background on this field, just a mechanical engineer trying to develop some apps ;)
So, here's the thing, when I use dropdownmenu, i usually define a list with the items beforehand, like the below:
List<String> varfluid = ["CO2", "O2"];
String _varfluid = "CO2";
void metFluid(String value){
setState((){
_varfluid=value;
});
}
This is defined before, and the below is how I create my DropdownButton
new DropdownButton(
onChanged: (String value){
metFluid(value);
},
value: _varfluid,
items: varfluid.map((String value){
return new DropdownMenuItem(
value: value,
child: new Text(value),
);
}).toList(),
)
It is working fine for me so far, the challenge I'm facing now is to populate another DropDown with items from a sqflite db. I tried to do it in a similar way to the above but I'm getting an error. Here's what I have:
This is the method for returning a list with all the items from the DB
Future<List> pegarTanques() async {
var bdCliente = await db;
var res = await bdCliente.rawQuery("SELECT * FROM $tabelaTanque");
return res.toList();
}
Then I run this piece of code to get only the desired property of the object to my List.
List todosTanques;
List<String> nomestanques = [""];
String _nomestanques = "";
void listartanques() async {
var db = new BD();
todosTanques = await db.pegarTanques();
for (int i = 0; i < todosTanques.length; i++) {
Tanque tanque = Tanque.map(todosTanques[i]);
nomestanques.add(tanque.nome);
}
}
And then I'm getting the list just fine. However when I try to implement it the same way as I did with the dropdown with predefined items, everytime I click on an item from the dropdown list I get this error:
'package:flutter/src/material/dropdown.dart': Failed assertion: line 620 pos 15: 'items == null || items.isEmpty || value == null || items.where((DropdownMenuItem<T> item) => item.value == value).length == 1': is not true.
User-created ancestor of the error-causing widget was:
MaterialApp file:///C:/Users/Victor/AndroidStudioProjects/formv3/lib/main.dart:9:14
Any help on this?