AhmedLSayed9 / dropdown_button2

Flutter's core Dropdown Button widget with steady dropdown menu and many other features.
https://pub.dev/packages/dropdown_button2
MIT License
264 stars 122 forks source link

onChanged doesn't work when using multiValueListenable #275

Closed npateras closed 3 months ago

npateras commented 3 months ago

Following this example from the official documentation:

final List<String> items = [
  'All',
  'Item1',
  'Item2',
  'Item3',
  'Item4',
];
final multiValueListenable = ValueNotifier<List<String>>([]);

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: Center(
      child: DropdownButtonHideUnderline(
        child: DropdownButton2<String>(
          isExpanded: true,
          hint: Text(
            'Select Items',
            style: TextStyle(
              fontSize: 14,
              color: Theme.of(context).hintColor,
            ),
          ),
          items: items.map((item) {
            return DropdownItem(
              value: item,
              height: 40,
              //disable default onTap to avoid closing menu when selecting an item
              enabled: false,
              child: ValueListenableBuilder<List<String>>(
                valueListenable: multiValueListenable,
                builder: (context, multiValue, _) {
                  final isSelected = multiValue.contains(item);
                  return InkWell(
                    onTap: () {
                      if (item == 'All') {
                        isSelected
                            ? multiValueListenable.value = []
                            : multiValueListenable.value = List.from(items);
                      } else {
                        multiValueListenable.value = isSelected
                            ? ([...multiValue]..remove(item))
                            : [...multiValue, item];
                      }
                    },
                    child: Container(
                      height: double.infinity,
                      padding: const EdgeInsets.symmetric(horizontal: 16.0),
                      child: Row(
                        children: [
                          if (isSelected)
                            const Icon(Icons.check_box_outlined)
                          else
                            const Icon(Icons.check_box_outline_blank),
                          const SizedBox(width: 16),
                          Expanded(
                            child: Text(
                              item,
                              style: const TextStyle(
                                fontSize: 14,
                              ),
                            ),
                          ),
                        ],
                      ),
                    ),
                  );
                },
              ),
            );
          }).toList(),
          multiValueListenable: multiValueListenable,
          onChanged: (value) {},
          selectedItemBuilder: (context) {
            return items.map(
              (item) {
                return ValueListenableBuilder<List<String>>(
                    valueListenable: multiValueListenable,
                    builder: (context, multiValue, _) {
                      return Container(
                        alignment: AlignmentDirectional.center,
                        child: Text(
                          multiValue
                              .where((item) => item != 'All')
                              .join(', '),
                          style: const TextStyle(
                            fontSize: 14,
                            overflow: TextOverflow.ellipsis,
                          ),
                          maxLines: 1,
                        ),
                      );
                    });
              },
            ).toList();
          },
          buttonStyleData: const ButtonStyleData(
            padding: EdgeInsets.only(left: 16, right: 8),
            height: 40,
            width: 140,
          ),
          menuItemStyleData: const MenuItemStyleData(
            padding: EdgeInsets.zero,
          ),
        ),
      ),
    ),
  );
}
  1. The onChanged parameter has no effect and removing it disables the dropdown completely.
  2. Is there any way to achieve the example above without ValueListenableBuilder?
AhmedLSayed9 commented 3 months ago
  1. The onChanged parameter has no effect and removing it disables the dropdown completely.

Now onChanged will be called when tapping an enabled item whether the menu will be closed or not. We no longer need to use the InkWell workaround, check the updated example at version ^3.0.0-beta.15.

  1. Is there any way to achieve the example above without ValueListenableBuilder?

It won't update an open menu as expected. Check https://github.com/AhmedLSayed9/dropdown_button2/pull/245 for more info.

npateras commented 3 months ago
  1. The onChanged parameter has no effect and removing it disables the dropdown completely.

Now onChanged will be called when tapping an enabled item whether the menu will be closed or not. We no longer need to use the InkWell workaround, check the updated example at version ^3.0.0-beta.15.

  1. Is there any way to achieve the example above without ValueListenableBuilder?

It won't update an open menu as expected. Check #245 for more info.

Thanks a lot, will check #245 ❤️