I am working on an open source project called Eleutherios and keep getting this error message:
Another exception was thrown: There should be exactly one item with [DropdownButton]'s value: ad7c17409ab11f249329c5528be5c5f7.
I am populating the dropdownButton from firebase and using initState to prefetch the default registrantId of the selected registrant for the end user and storing it in dropdownValue.
class _ViewForumScreenState extends ConsumerState<ViewForumScreen> {
final messageController = TextEditingController();
Registrant? selectedRegistrant;
String? dropdownValue;
var tapPosition;
getSelectedRegistrant() async {
final user = ref.read(userProvider)!;
selectedRegistrant = await ref
.read(getUserSelectedRegistrantProvider2(
Tuple2(widget.forumId, user.uid)))
.first;
setState(() {
dropdownValue = selectedRegistrant!.registrantId;
});
}
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
getSelectedRegistrant();
}
);
}
Then using dropdownValue as the selected value for the DropdownButton.
Expanded(
flex: 41,
child: ref
.watch(getUserRegistrantsProvider(
Tuple2(widget.forumId, user.uid)))
.when(
data: (registrants) {
return DropdownButtonHideUnderline(
child: ButtonTheme(
alignedDropdown: true,
child: DropdownButton(
isDense: true,
value: dropdownValue,
onChanged: (String? registrantId) {
if (registrantId is String) {
changeSelectedRegistrant(
registrantId);
}
},
// *********************************
// items
// *********************************
items: registrants
.map<DropdownMenuItem<String>>(
(Registrant registrant) {
return ref
.watch(getServiceByIdProvider(
registrant.serviceId))
.when(data: (service) {
return DropdownMenuItem<String>(
value: registrant.registrantId,
child: Row(children: [
service!.image ==
Constants
.avatarDefault
? CircleAvatar(
backgroundImage: Image
.asset(service
.image)
.image,
radius: 11,
)
: CircleAvatar(
backgroundImage:
NetworkImage(
service
.image),
radius: 11,
),
const SizedBox(
width: 8,
),
service.title.length > 12
? Text(
'${service.title.substring(0, 12)}...',
style:
const TextStyle(
fontSize: 14,
),
)
: Text(
service.title,
style:
const TextStyle(
fontSize: 14,
),
),
]),
);
},
// *********************************
// error
// *********************************
error: (error, stackTrace) {
return DropdownMenuItem<String>(
value: error.toString(),
child: Text(error.toString()),
);
},
// *********************************
// loading
// *********************************
loading: () {
return const DropdownMenuItem<
String>(
value: 'Loader',
child: Loader(),
);
});
}).toList(),
),
),
);
},
error: (error, stackTrace) =>
ErrorText(error: error.toString()),
loading: () => const Loader(),
),
),
It works, but not without the flutter page flashing red for a split second with the aforementioned error message.
What is bizarre is the error only occurs when I navigate to the View Forum page from a Drawer (side panel) page.
In the above image you can see me opening the side draw and click on the Physical Examination Forum link.
In the above image you can see I get the error message.
If I navigate to the View Forum page by clicking on the view button from the Forum Details page the error doesn't occur???
In the above image you can see the Forum Details page before I click on the View button.
And here's the result with no error and everything is working fine.
Has anybody encountered this problem before and got a work around or is there something I am missing?
Cheers!
Code for the List Draw page:
https://github.com/aletheon/eleutherios-flutter/blob/main/lib/features/home/drawers/list_drawer.dart
Code for the Forum Details page:
Code for the View Forum page:
Entire source code:




The problem is with this block of code.
I'm using the map function to iterate through the registrants list and then immediately calling another provider within that map function to fetch the associated service belonging to the registrant:
This means the DropdownButton items is not being populated before the comparison is made because getServiceByIdProvider hasn't returned yet and thus the error occurs.
So, the answer became glaringly obvious, force the items to be populated before doing the comparison and the best place to do that was the DropdownMenuItem's child property.
Like so:
Now the DropdownButton items has to wait until all of the getServiceByIdProvider calls have been made before it does the comparison.
And viola, no more error!
A rookie mistake I know, but hey, live and learn right.
:-)