Flutter - There should be exactly one item with [DropdownButton]'s value... error with provider
I have a dropdown-menu. My goal is to let the user choose a value of the dropdown-menu. After this the value should be shown as a list above the dropdown-menu. I'm using Provider for storing the choosen value(s) in a List. But when I let the List listen to the changes in the provider-model I get the error for the Dropdown-menu. I don't know why I get errors during rebuilding...
Provider.of<InspectionFormModel>(context, listen: true).removeAbleObjects!=null?ListView(
shrinkWrap: true,
key: ObjectKey(Provider.of<InspectionFormModel>(context, listen: false).removeAbleObjects),
children: Provider.of<InspectionFormModel>(context, listen: false).removeAbleObjects!=null?Provider.of<InspectionFormModel>(context, listen: false).removeAbleObjects!.map((e) => e).toList():[Container()]
):Visibility(child: Container(),visible: false,),
CustomDropdown(items: [DropDownObject("text",1),DropDownObject("textsoundso",2)], hintText: inspectionObject, provider: "inspection",value:"device",),
My DropDownButton:
import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class CustomDropdown extends StatefulWidget {
final List<DropDownObject> items;
//final List<dynamic>? objects;
final String hintText;
final String? provider;
final String? value;
final bool useId;
const CustomDropdown({Key? key,
this.useId=false,
this.value,
this.provider,
this.hintText="",
required this.items}) : super(key: key);
@override
State<CustomDropdown> createState() => _CustomDropdownState();
}
class _CustomDropdownState extends State<CustomDropdown> {
@override
void initState() {
developer.log("init dropdown");
super.initState();
}
@override
Widget build(BuildContext context) {
DropDownObject? selectedValue=null;
return Padding(
padding: EdgeInsets.only(right: 15),
// child: DropdownButtonHideUnderline(
child: DropdownButtonFormField2<DropDownObject>(
validator: (value) {
if (value == null ) {
return 'Bitte wählen Sie einen Wert aus.';
}
return null;
},
buttonHeight: 50,
decoration: InputDecoration(
// errorBorder: OutlineInputBorder(borderSide: BorderSide(color: Colors.red),borderRadius: BorderRadius.circular(10)),
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.transparent)
)
),//InputDecoration.collapsed(hintText: ""),//
hint: Padding(padding: EdgeInsets.only(left: 10),child: Text(widget.hintText, style: AppTextStyle().formText,)),
isExpanded: true,
dropdownDecoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
border: Border.all(
color: AppColors().grey,
),
),
buttonDecoration: BoxDecoration(
color: AppColors().formFieldColor,
borderRadius: BorderRadius.circular(10),
border: Border.all(
color: AppColors().grey,
),
),
items: widget.items.map((item) =>
DropdownMenuItem<DropDownObject>(
value: item,
child: Row(children:[
Expanded(child: Text(item.text, textAlign: TextAlign.left,))
],)
)).toList(),
// value:selectedValue,
onChanged: (value) {
setState(() {
selectedValue=value;
//selectedValue = value;
//widget.useId?widget.provider??FormProviderSelection().writeValueToProviderObject(context, widget.provider!,widget.value!,selectedValue!):
FormProviderSelection().writeValueToProviderObject(context, widget.provider!,widget.value!,value!);//widget.provider??
});
},
icon: const Icon(Icons.arrow_drop_down_rounded),
iconEnabledColor: AppColors().grey,
iconDisabledColor: Colors.white54,
dropdownMaxHeight: 200,
dropdownElevation: 8,
),
// ),
);
}
}
Update 2022-01-22
class DropDownObject{
String text;
int? dropDownObjectId;
DropDownObject(this.text, [this.dropDownObjectId]);
}
Solution 1:
Maybe you have two or more same DropDownObject
. Or you have null DropDownObject
.
Check this part of your code.
items: widget.items.map((item) =>
DropdownMenuItem<DropDownObject>(
value: item,
child: Row(children:[
Expanded(child: Text(item.text, textAlign: TextAlign.left,))
],)
)).toList(),
try to add filters:
widget.items
.where((e) => e != null) //removes null items
.toSet() // removes duplicate items
.map
also implement == and hashcode in your model class:
class DropDownObject{
String text;
int? dropDownObjectId;
DropDownObject(this.text, [this.dropDownObjectId]);
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is DropDownObject && runtimeType == other.runtimeType && text == other.text;
@override
int get hashCode => text.hashCode;
}