I am trying to create a dropdown button in Flutter. I am getting a List from my database then I pass the list to my dropdownButton
everything works the data is shown as intended but when I choose an element from it I get this error:
There should be exactly one item with [DropdownButton]'s value: Instance of 'Tag'. Either zero or 2 or more [DropdownMenuItem]s were detected with the same value 'package:flutter/src/material/dropdown.dart': Failed assertion: line 805 pos 15: 'items == null || items.isEmpty || value == null || items.where((DropdownMenuItem<T> item) { return item.value == value; }).length == 1'
I tried setting DropdownButton value to null it works but then I can't see the chosen element.
Here is my code:
FutureBuilder<List<Tag>>( future: _tagDatabaseHelper.getTagList(), builder: (BuildContext context, AsyncSnapshot<List<Tag>> snapshot) { if (!snapshot.hasData) { return Center( child: CircularProgressIndicator(), ); } return ListView( children: <Widget>[ SizedBox( height: MediaQuery.of(context).size.height * 0.2, ), Container( margin: EdgeInsets.symmetric( horizontal: MediaQuery.of(context).size.width * 0.07), child: Theme( data: ThemeData(canvasColor: Color(0xFF525A71)), child: DropdownButton<Tag>( value: _selectedTag, isExpanded: true, icon: Icon( Icons.arrow_drop_down, size: 24, ), hint: Text( "Select tags", style: TextStyle(color: Color(0xFF9F9F9F)), ), onChanged: (value) { setState(() { _selectedTag = value; }); }, items: snapshot.data.map((Tag tag) { return DropdownMenuItem<Tag>( value: tag, child: Text( tag.tagTitle, style: TextStyle(color: Colors.white), ), ); }).toList(), value: _selectedTag, ), ), ),
I used futureBuilder to get my List from database.
Well, since no problem has an exact same solution. I was facing the same issue with my code. Here is How I fixed this.
CODE of my DropdownButton:
DropdownButton( items: _salutations .map((String item) => DropdownMenuItem<String>(child: Text(item), value: item)) .toList(), onChanged: (String value) { setState(() { print("previous ${this._salutation}"); print("selected $value"); this._salutation = value; }); }, value: _salutation, ),
The Error
In the code snippet below, I am setting the state for a selection value, which is of type String. Now problem with my code was the default initialization of this selection value. Initially, I was initializing the variable _salutation
as:
String _salutation = ""; //Notice the empty String.
This was a mistake!
Initial selection should not be null or empty as the error message correctly mentioned.
'items == null || items.isEmpty || value == null ||
And hence the crash:
Solution
Initialize the value object with some default value. Please note that the value should be the one of the values contained by your collection. If it is not, then expect a crash.
String _salutation = "Mr."; //This is the selection value. It is also present in my array. final _salutations = ["Mr.", "Mrs.", "Master", "Mistress"];//This is the array for dropdown
Might also get this error if trying to set value of dropdown with a class instance;
var tag1 = Tag(); var tag2 = Tag(); print(tag1 == tag2); // prints false, dropwdown computes that value is not present among dropdown options
To solve this override operator ==:
class Tag{ String name = "tag"; @override bool operator ==(Object other) => other is Tag && other.name == name; @override int get hashCode => name.hashCode; }
or use https://pub.dev/packages/equatable lib
class Tag extends Equatable{ String name = "tag"; @override List<Object> get props => [name]; }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With