Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Either zero or 2 or more [DropdownMenuItem]s were detected with the same value this happen when i have three drop downs get from api and two of them depend of what i will choose from the first one when schoose from the three drop downs and select from the first one again got this error #216

Closed
ziad500 opened this issue Nov 8, 2023 · 12 comments

Comments

@ziad500
Copy link

ziad500 commented Nov 8, 2023

import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';

import '../../utils/app_colors.dart';

class CustomDropDown extends StatelessWidget {
CustomDropDown(
{super.key,
required this.list,
this.items,
this.height,
this.iconSize = 24,
required this.hint,
this.isEmpty = false,
required this.onOptionSelected,
this.iconColor,
this.onTap,
this.width,
this.title,
this.validator});

final List list;
final List<DropdownMenuItem>? items;
final String hint;
static String? selectedValue;
final void Function(OptionItem?) onOptionSelected;
final double iconSize;
final Color? iconColor;
final bool isEmpty;
final void Function()? onTap;
final double? height;
final double? width;
final String? title;
final String? Function(OptionItem?)? validator;

final TextEditingController textEditingController = TextEditingController();
static OptionItem? selected;

@OverRide
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (title != null) ...[
Text(
title!,
style: Theme.of(context).textTheme.titleSmall,
),
const SizedBox(
height: 5,
)
],
SizedBox(
width: width,
child: Stack(
children: [
DropdownButtonFormField2(
value: selected,
isExpanded: true,
decoration: InputDecoration(
isDense: true,
contentPadding: const EdgeInsets.symmetric(vertical: 10),
fillColor: AppColors.fillColor,
filled: true,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(6).w,
),
enabledBorder: const OutlineInputBorder(
borderSide: BorderSide(color: AppColors.borderColor))
// Add more decoration..
),
hint: Text(
hint,
style: Theme.of(context)
.textTheme
.bodySmall
?.copyWith(color: AppColors.textColor, fontSize: 16),
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
items: items ??
list
.map((item) => DropdownMenuItem(
value: OptionItem(
id: item.id,
title: item.title,
subtitle: item.subtitle,
description: item.description,
image: item.image),
child: FittedBox(
fit: BoxFit.scaleDown,
child: Text(
item.title,
style: Theme.of(context)
.textTheme
.bodySmall
?.copyWith(color: AppColors.textColor, fontSize: 16),
),
),
))
.toList(),
validator: validator ??
(value) {
if (value == null) {
return "please enter $title";
}
return null;
},
onChanged: (value) {
print("sssssssssssss ${selected?.id}");
onOptionSelected(value);
},
onSaved: (value) {
selectedValue = value.toString();
},
dropdownSearchData: DropdownSearchData(
searchController: textEditingController,
searchInnerWidgetHeight: 50,
searchInnerWidget: Container(
height: 50,
padding: const EdgeInsets.only(
top: 8,
bottom: 4,
right: 8,
left: 8,
),
child: TextFormField(
style: Theme.of(context)
.textTheme
.bodySmall
?.copyWith(color: AppColors.textColor, fontSize: 16),
controller: textEditingController,
decoration: InputDecoration(
isDense: true,
contentPadding: const EdgeInsets.symmetric(
horizontal: 10,
vertical: 8,
),
hintText: "Search",
hintStyle: Theme.of(context)
.textTheme
.bodySmall
?.copyWith(color: AppColors.textColor, fontSize: 16),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
),
),
),
),
searchMatchFn: (DropdownMenuItem<OptionItem?> item, searchValue) {
return item.value!.title
.toString()
.toLowerCase()
.contains(searchValue.toLowerCase());
},
),
buttonStyleData: const ButtonStyleData(
padding: EdgeInsets.only(right: 8),
),
iconStyleData: IconStyleData(
icon: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: Icon(
Icons.keyboard_arrow_down_outlined,
color: iconColor ?? AppColors.iconColor,
),
),
iconSize: iconSize,
),
dropdownStyleData: DropdownStyleData(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
),
),
menuItemStyleData: const MenuItemStyleData(
padding: EdgeInsets.symmetric(horizontal: 16),
),
),
isEmpty == true
? InkWell(
onTap: onTap,
child: SizedBox(
width: width,
height: height ?? 37.h,
),
)
: const SizedBox()
],
),
),
],
);
}
}

class OptionItem extends Equatable {
final String id;
final String title;
final String? subtitle;
final String description;
final String image;

const OptionItem(
{required this.id,
required this.title,
this.description = "",
this.subtitle,
this.image = ""});

@OverRide
List<Object?> get props => [id, title, description, image, subtitle];
}

@AhmedLSayed9
Copy link
Owner

Duplicate of #138

@AhmedLSayed9 AhmedLSayed9 marked this as a duplicate of #138 Nov 8, 2023
@ziad500
Copy link
Author

ziad500 commented Nov 8, 2023

I tried the solution you provided but the same error appears @AhmedLSayed9

@AhmedLSayed9
Copy link
Owner

Your code is hard to read, can you format it?

You should use:
```dart
yourCode
```

@ziad500
Copy link
Author

ziad500 commented Nov 8, 2023

import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';

import '../../utils/app_colors.dart';

class CustomDropDown extends StatelessWidget {
CustomDropDown(
{super.key,
required this.list,
this.items,
this.height,
this.iconSize = 24,
required this.hint,
this.isEmpty = false,
required this.onOptionSelected,
this.iconColor,
this.onTap,
this.width,
this.title,
this.validator});

final List list;
final List<DropdownMenuItem>? items;
final String hint;
static String? selectedValue;
final void Function(OptionItem?) onOptionSelected;
final double iconSize;
final Color? iconColor;
final bool isEmpty;
final void Function()? onTap;
final double? height;
final double? width;
final String? title;
final String? Function(OptionItem?)? validator;

final TextEditingController textEditingController = TextEditingController();

@OverRide
Widget build(BuildContext context) {
return DropdownButtonFormField2(
isExpanded: true,
hint: Text(
hint,
style: Theme.of(context)
.textTheme
.bodySmall
?.copyWith(color: AppColors.textColor, fontSize: 16),
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
items: items ??
list
.map((item) => DropdownMenuItem(
value: OptionItem(
id: item.id,
title: item.title,
subtitle: item.subtitle,
description: item.description,
image: item.image),
child: FittedBox(
fit: BoxFit.scaleDown,
child: Text(
item.title,
style: Theme.of(context)
.textTheme
.bodySmall
?.copyWith(color: AppColors.textColor, fontSize: 16),
),
),
))
.toList(),
validator: validator ??
(value) {
if (value == null) {
return "please enter $title";
}
return null;
},
onChanged: (value) {
onOptionSelected(value);
},
onSaved: (value) {
selectedValue = value.toString();
},
buttonStyleData: const ButtonStyleData(
padding: EdgeInsets.only(right: 8),
),
dropdownStyleData: DropdownStyleData(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
),
),
menuItemStyleData: const MenuItemStyleData(
padding: EdgeInsets.symmetric(horizontal: 16),
),
);
}
}

class OptionItem extends Equatable {
final String id;
final String title;
final String? subtitle;
final String description;
final String image;

const OptionItem(
{required this.id,
required this.title,
this.description = "",
this.subtitle,
this.image = ""});

@OverRide
List<Object?> get props => [id, title, description, image, subtitle];
}

@AhmedLSayed9
Copy link
Owner

It still unformatted 😃

@ziad500
Copy link
Author

ziad500 commented Nov 8, 2023

What should i do 😂

@AhmedLSayed9
Copy link
Owner

Add ```dart at the beginning your code and ``` at the end of your code

@ziad500
Copy link
Author

ziad500 commented Nov 8, 2023

This file contains dropdown widget only

@AhmedLSayed9
Copy link
Owner

AhmedLSayed9 commented Nov 8, 2023

I meant formatting the code here at github

@ziad500
Copy link
Author

ziad500 commented Nov 8, 2023

class CustomDropDown extends StatelessWidget {
CustomDropDown(
{super.key,
required this.list,
this.items,
this.height,
this.iconSize = 24,
required this.hint,
this.isEmpty = false,
required this.onOptionSelected,
this.iconColor,
this.onTap,
this.width,
this.title,
this.validator});

final List list;
final List? items;
final String hint;
static String? selectedValue;
final void Function(OptionItem?) onOptionSelected;
final double iconSize;
final Color? iconColor;
final bool isEmpty;
final void Function()? onTap;
final double? height;
final double? width;
final String? title;
final String? Function(OptionItem?)? validator;

final TextEditingController textEditingController = TextEditingController();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@OverRide
Widget build(BuildContext context) {
return DropdownButtonFormField2(
isExpanded: true,
hint: Text(
hint,
style: Theme.of(context)
.textTheme
.bodySmall
?.copyWith(color: AppColors.textColor, fontSize: 16),
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
items: items ??
list
.map((item) => DropdownMenuItem(
value: OptionItem(
id: item.id,
title: item.title,
subtitle: item.subtitle,
description: item.description,
image: item.image),
child: FittedBox(
fit: BoxFit.scaleDown,
child: Text(
item.title,
style: Theme.of(context)
.textTheme
.bodySmall
?.copyWith(color: AppColors.textColor, fontSize: 16),
),
),
))
.toList(),
validator: validator ??
(value) {
if (value == null) {
return "please enter $title";
}
return null;
},
onChanged: (value) {
onOptionSelected(value);
},
onSaved: (value) {
selectedValue = value.toString();
},
buttonStyleData: const ButtonStyleData(
padding: EdgeInsets.only(right: 8),
),
dropdownStyleData: DropdownStyleData(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
),
),
menuItemStyleData: const MenuItemStyleData(
padding: EdgeInsets.symmetric(horizontal: 16),
),
);
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

class OptionItem extends Equatable {
final String id;
final String title;
final String? subtitle;
final String description;
final String image;

const OptionItem(
{required this.id,
required this.title,
this.description = "",
this.subtitle,
this.image = ""});

@OverRide
List<Object?> get props => [id, title, description, image, subtitle];
} #

@ziad500
Copy link
Author

ziad500 commented Nov 8, 2023

Like this 😅

@AhmedLSayed9
Copy link
Owner

No. Your code should be formatted like this one:

code

Anyway, You can't use String for selectedValue while using OptionItem as the value of your items.

To be compile-safe, you can annotate your DropdownButtonFormField2 with the type you want. i.e:

return  DropdownButtonFormField2< OptionItem>(
....
);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants