Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter: There should be exactly one item with [DropdownButton]'s value

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.

like image 770
Abdelbaki Boukerche Avatar asked Mar 03 '20 15:03

Abdelbaki Boukerche


2 Answers

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:

crash_message

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 
like image 176
sud007 Avatar answered Sep 22 '22 10:09

sud007


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]; } 
like image 24
Nuts Avatar answered Sep 22 '22 10:09

Nuts