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

Select all, Clear all #52

Open
Mohdx opened this issue Jun 18, 2024 · 8 comments
Open

Select all, Clear all #52

Mohdx opened this issue Jun 18, 2024 · 8 comments
Assignees

Comments

@Mohdx
Copy link

Mohdx commented Jun 18, 2024

Hello, thank you for this cool package, really appreciate it

Current Behavior

When selecting all items then clear all. the items doesn't return back to builder list

final MultipleSearchController<GroupModel> ctrl =
      MultipleSearchController<GroupModel>();
      ...
      
  void _select() {
    final List<GroupModel> x = ctrl.getPickedItems();
    final List<String> labels = List.generate(x.length, (i) => x[i].name ?? '');
    widget.onSelect(('$labels').replaceAll(RegExp(r'[\[\]]'), ''), x);
  }
  ...
  
return MultipleSearchSelection<GroupModel>(
 controller: ctrl,
 onItemRemoved: (_) => _select(),
 onItemAdded: (_) => _select(),
 onTapClearAll: () => _select(),
 onTapSelectAll: () => _select(),
 itemBuilder: (GroupModel group, int _) {
        return Container(
          margin: const EdgeInsets.all(6.0),
          padding: const EdgeInsets.fromLTRB(12, 14, 12, 14),
          decoration: Decorations.flat(context),
          child: Text(group.name ?? ''),
        );
      },

Expected behavior/code

When selecting clear all. the items returns back to builder list

SVID_20240618_122211_1-ezgif com-video-to-gif-converter

Full code

import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:multiple_search_selection/multiple_search_selection.dart';

import '/app/theme/colors/main_colors.dart';
import '/app/theme/decoration/decorations.dart';
import '/models/ModelProvider.dart';

class CompanyGroupField extends StatefulWidget {
  const CompanyGroupField({
    super.key,
    required this.groups,
    required this.onSelect,
    this.selectedGroups = const <GroupModel>[],
  });
  final List<GroupModel> groups;
  final List<GroupModel> selectedGroups;
  final void Function(String, List<GroupModel>) onSelect;

  @override
  State<CompanyGroupField> createState() => _CompanyGroupFieldState();
}

class _CompanyGroupFieldState extends State<CompanyGroupField> {
  late AppLocalizations arb;

  final MultipleSearchController<GroupModel> ctrl =
      MultipleSearchController<GroupModel>();

  void _select() {
    final List<GroupModel> x = ctrl.getPickedItems();
    final List<String> labels = List.generate(x.length, (i) => x[i].name ?? '');
    widget.onSelect(('$labels').replaceAll(RegExp(r'[\[\]]'), ''), x);
  }

  @override
  void didChangeDependencies() {
    arb = AppLocalizations.of(context)!;
    super.didChangeDependencies();
  }

  @override
  Widget build(BuildContext context) {
    return MultipleSearchSelection<GroupModel>(
      controller: ctrl,
      initialPickedItems: widget.selectedGroups,
      items: widget.groups,
      onItemRemoved: (_) => _select(),
      onItemAdded: (_) => _select(),
      onTapClearAll: () => _select(),
      onTapSelectAll: () => _select(),
      clearSearchFieldOnSelect: true,

      searchField: TextField(
        decoration: InputDecoration(
          hintText: 'Search groups',
          contentPadding: const EdgeInsets.fromLTRB(18, 14, 18, 14),
          focusedBorder: Decorations.formBorderTop(context),
          enabledBorder: Decorations.formBorderTop(context),
          border: Decorations.formBorderTop(context),
        ),
      ),

      pickedItemBuilder: (group) {
        return Container(
          padding: const EdgeInsets.all(8),
          decoration: Decorations.border(context),
          child: Row(
            mainAxisSize: MainAxisSize.min,
            children: [
              Text(group.name ?? ''),
              const SizedBox(width: 4),
              const Icon(Icons.cancel, color: MainColors.red, size: 20),
            ],
          ),
        );
      },

      itemBuilder: (GroupModel group, int _) {
        return Container(
          margin: const EdgeInsets.all(6.0),
          padding: const EdgeInsets.fromLTRB(12, 14, 12, 14),
          decoration: Decorations.flat(context),
          child: Text(group.name ?? ''),
        );
      },

      fieldToCheck: (group) => group.name ?? '',
      noResultsWidget: const SizedBox.shrink(),
      pickedItemsBoxDecoration: Decorations.border(context),
      showedItemsBoxDecoration: Decorations.borderBottom(context),
    );
  }
}
@esentis
Copy link
Owner

esentis commented Jun 19, 2024

Hell hello !!

Thanks for taking the time to fill the issue.
I will investigate it as soon as possible, and will get back to you !
Cheers.

@esentis
Copy link
Owner

esentis commented Jun 22, 2024

@Mohdx is there a reason you use the same method for those callbacks ?

     onTapClearAll: () => _select(),
     onTapSelectAll: () => _select(),

@esentis esentis added waiting response Waiting for user's response and removed under investigation labels Jun 22, 2024
@Mohdx
Copy link
Author

Mohdx commented Jun 23, 2024

@Mohdx is there a reason you use the same method for those callbacks ?

     onTapClearAll: () => _select(),

     onTapSelectAll: () => _select(),

Sorry I couldn't find the best use practice in the documentation.

Just wanted to keep listening to controller on click, what is selected items

@esentis
Copy link
Owner

esentis commented Jun 23, 2024

There is a callback onPickedChange which fires everytime the picked / selected items change. Your example could lead to inconsistencies since you are manipulating the list on clear method. The list manipulation happens internally, there is no need to do it on your own.

onTapClearAll & onTapSelectAll are just callbacks when the events occures.

@Mohdx
Copy link
Author

Mohdx commented Jun 24, 2024

There is a callback onPickedChange which fires everytime the picked / selected items change. Your example could lead to inconsistencies since you are manipulating the list on clear method. The list manipulation happens internally, there is no need to do it on your own.

onTapClearAll & onTapSelectAll are just callbacks when the events occures.

Gotcha, thanks for the explanation.
Meaning for my use, no need for a controller to get selected items on click, so my code now looks like this:

class _MultiSelectFieldState<T> extends State<MultiSelectField<T>> {
  late AppLocalizations arb;

  // final MultipleSearchController<T> ctrl = MultipleSearchController<T>();

  void _select(List<T> list) {
    final List<String> labels =
        List.generate(list.length, (i) => widget.labelExtractor(list[i]));
    widget.onSelect(('$labels').replaceAll(RegExp(r'[\[\]]'), ''), list);
  }

  @override
  void didChangeDependencies() {
    arb = AppLocalizations.of(context)!;
    super.didChangeDependencies();
  }

  @override
  Widget build(BuildContext context) {
    return MultipleSearchSelection<T>(
      // controller: ctrl,
      initialPickedItems: widget.selectedModels,
      items: widget.models,
      onPickedChange: (list) => _select(list),
      clearSearchFieldOnSelect: true,
      ...

However, I'm still facing the issue :(
Also I faced another issue where when you set itemsVisibility: to ShowedItemsVisibility.toggle,
The items is not removed from the pop-up list when selecting
ezgif-5-5b68142990

@esentis
Copy link
Owner

esentis commented Jun 24, 2024

Hmm, try to not manipulate the original list on your onPickedChange method (_select). If you want to manipulate your original list, try creating a new local list for your MultipleSearchSelection widget.

e.g

late final _localList = [...widget.groups]

As I said the adding/removing from lists is done internally and there is no need for you to do this manually. onPickedChange ideally, should just update a variable with your currently picked items, rather than changing the original feeding list.

@Mohdx
Copy link
Author

Mohdx commented Jun 27, 2024

Hmm, try to not manipulate the original list on your onPickedChange method (_select). If you want to manipulate your original list, try creating a new local list for your MultipleSearchSelection widget.

e.g

late final _localList = [...widget.groups]

As I said the adding/removing from lists is done internally and there is no need for you to do this manually. onPickedChange ideally, should just update a variable with your currently picked items, rather than changing the original feeding list.

Sorry I'm confused. I comment out onPickedChange but still has the same issues.

Nevermind about my code. this is the library example:
Why "clear all" doesn't return back items: (to select list)? how I'm going to do it manually?
Also you can select the same item more than once in the pop-up list, unlike the example GIF you cannot.
ezgif-6-49d197c5e5

image

@Mohdx
Copy link
Author

Mohdx commented Jun 27, 2024

Try to search for a country after "clear all" you won't be able to see any

@esentis esentis added under investigation and removed waiting response Waiting for user's response labels Jun 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants