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

initialValue not working as expected #5

Closed
jjoschyy opened this issue Oct 1, 2020 · 12 comments
Closed

initialValue not working as expected #5

jjoschyy opened this issue Oct 1, 2020 · 12 comments

Comments

@jjoschyy
Copy link

jjoschyy commented Oct 1, 2020

Hello CHB61

Thanks for this great flutter lib.

Seems the initialValue property is not working correctly. Based on your example I added all animals as an initial value:

MultiSelectBottomSheetField( initialValue: _animals, ..... ),

As a result the selected animals are not shown inside the form. But all animals are pre-selected on the bottom selection area (see screenshot).

Screenshot_1601568203

@CHB61
Copy link
Owner

CHB61 commented Oct 3, 2020

Hi @jjoschyy,

Thank you for submitting this issue. I can see that the chips do not get displayed on the default chipDisplay when an initialValue is set on the MultiSelectBottomSheetField. This will be fixed.

I want to point out that the selected values in the bottomsheet will be set to initialValue every time you open it, even if you changed the selection!
By setting initialValue: _animals, it will have all options selected every time you open it and this is probably not the behavior you want. ex:

To provide background on this param:

The initialValue param is required on MultiSelectBottomSheet and MultiSelectDialog and should be set to the list of selected values so that they are highlighted when the bottomsheet or dialog is re-opened.

In the case of MultiSelectBottomSheetField/MultiSelectDialogField, the initialValue param is not required as there is an internal list of selected items that is being passed from MultiSelectBottomSheetField to MultiSelectBottomSheet every time it is
opened.

However, this param becomes useful when your MultiSelect widget is being re-inserted into the widget tree. For example if you have a MultiSelectDialogField inside of your own custom BottomSheet, you might:

  • open the bottomsheet
  • select values in the MultiSelectDialogField
  • close the bottom sheet
  • open the bottomsheet again and expect the MultiSelectDialogField to have the same values selected

Setting MultiSelectDialogField.initialValue to the list of selected items would achieve this.

Basically the initialValue should always be set to _selectedValues.

But what if you just want some pre-selected items the first time it is opened?

I recommend following these steps to pre-select values before initial interaction:

  • Set initialValue as the list of _selectedValues
  • In initState, set _selectedValues to the pre-selected values that you want
  • Add onConfirm param with setState that updates the _selectedValues

Hope this helps :)

@CHB61
Copy link
Owner

CHB61 commented Oct 4, 2020

Hi @jjoschyy,
This issue is fixed in version 3.1.0.

Please take a look at the changelog and let me know if this solves your issue.

@CHB61 CHB61 closed this as completed Oct 4, 2020
@jjoschyy
Copy link
Author

jjoschyy commented Oct 6, 2020

Hello CHB61

Thanks a lot for your detailed answer. This helped me a lot. Also thanks for the fix. I can confirm the inital values are now shown correctly.

Nevertheless, one issue seems still existing. After adding inital values, the remove action is not working anymore. Example:

image

On this action, the selected value is removed from the _selected list. This works, the value will be removed from the _selected list. But there is no refresh on the MultiSelectChipDisplay.

But if I manually select any other item from the list, the remove action works.

I follwed your recommondation:

  • Set initialValue as the list of _selectedValues
  • In initState, set _selectedValues to the pre-selected values that you want
  • Add onConfirm param with setState that updates the _selectedValues

Thanks again for your help!

@CHB61
Copy link
Owner

CHB61 commented Oct 17, 2020

@jjoschyy Hi! Sorry for the delay! Been so busy last couple weeks but I'll take a look into this problem ASAP.

@CHB61
Copy link
Owner

CHB61 commented Dec 1, 2020

Hi @jjoschyy ,

Sorry for the delay on this one. I was able to reproduce the issue.

The reason you can only delete from the chip display after doing a confirm is because in the onConfirm function,
I am passing a reference of the internal list of selected values.

This means that only when you obtain a reference to the list that is provided in the onConfirm, can you manipulate it from onTap and then the changes will be updated.

onConfirm: (values) {
    _selectedAnimals = values; // gets reference to internal list of selected items
}

So it also means that if you were to change the code in the onConfirm to something like:

onConfirm: (values) {
    _selectedAnimals = [];
    _selectedAnimals.addAll(values);
}

Deleting from the chip display won't work at all now because there is no reference to the list that MultiSelectDialogField uses
to determine the selected items.

With onTap(V) all we know is which item was tapped, and there's no guarantee that the list is going to change.

So in order to delete without getting a reference to the internal list, the fix I've applied is to have MultiSelectDialogField check if
the onTap() function returned anything, and if it returned a List, update the state.

All you would need to do to is simply return the updated list in the onTap function. Example:

onTap: (item) {
    _selectedAnimals.remove(item);
    return _selectedAnimals;
}

You don't even need to set state anymore.

I was considering not passing by reference at all in the onConfirm since it wasn't intentional but I decided to leave that for now.
This leaves both options available to delete from chipDisplay:

  1. Get a reference to internal list of selected items in onConfirm, and setState when doing the remove operation in onTap.
    (Only works if you don't need to delete before confirm)
  2. Return the updated list in onTap.
    (No need to set state here and works any time)

This change is available in version 3.1.4.

Hope this helps :)

@ariefwijaya
Copy link

@CHB61 Please open this issue again The issue is still exist for me, initialValue can't be shown

@vjrj
Copy link

vjrj commented Apr 29, 2021

This was not working for me neither because I followed the example of pub.dev that is using the class without the Generics, like:

MultiSelectBottomSheetField(

instead of:

MultiSelectBottomSheetField<Animal>(

following the repo example generics use, my initialValue code started to work. I hope this helps.

@Darksoulsong
Copy link

Darksoulsong commented Jun 3, 2021

@CHB61 I've got issues having initial values because I'm setting them asynchronously, but these values are being set on MultiSelectDialogField's initState callback only. That means it won't rerender as soon as the initial values are ready or they get updated. For now, I'm working around this by using a loading flag and rendering the widget when the data is ready... but this is far from ideal. Any plans to get this sorted?
BTW, thanks for the awesome lib!

@ronytesler
Copy link

I have the same problem.

@saddemYassin
Copy link

saddemYassin commented Jan 12, 2022

@MuhammadSufyanMalik
Copy link

Hi @jjoschyy ,

Sorry for the delay on this one. I was able to reproduce the issue.

The reason you can only delete from the chip display after doing a confirm is because in the onConfirm function, I am passing a reference of the internal list of selected values.

This means that only when you obtain a reference to the list that is provided in the onConfirm, can you manipulate it from onTap and then the changes will be updated.

onConfirm: (values) {
    _selectedAnimals = values; // gets reference to internal list of selected items
}

So it also means that if you were to change the code in the onConfirm to something like:

onConfirm: (values) {
    _selectedAnimals = [];
    _selectedAnimals.addAll(values);
}

Deleting from the chip display won't work at all now because there is no reference to the list that MultiSelectDialogField uses to determine the selected items.

With onTap(V) all we know is which item was tapped, and there's no guarantee that the list is going to change.

So in order to delete without getting a reference to the internal list, the fix I've applied is to have MultiSelectDialogField check if the onTap() function returned anything, and if it returned a List, update the state.

All you would need to do to is simply return the updated list in the onTap function. Example:

onTap: (item) {
    _selectedAnimals.remove(item);
    return _selectedAnimals;
}

You don't even need to set state anymore.

I was considering not passing by reference at all in the onConfirm since it wasn't intentional but I decided to leave that for now. This leaves both options available to delete from chipDisplay:

  1. Get a reference to internal list of selected items in onConfirm, and setState when doing the remove operation in onTap.
    (Only works if you don't need to delete before confirm)
  2. Return the updated list in onTap.
    (No need to set state here and works any time)

This change is available in version 3.1.4.

Hope this helps :)

Hi,it helps for me , but now I am unable to get values from list, it shows instances.

@MalikSamiAwan
Copy link

@MuhammadSufyanMalik could you help me in this one
onTap does not update initial values

onTap: (value) {

              selected.removeWhere((element) => element.getId==value.getId);
              pprint(selected);
              ///my code

              return selected;
          },

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

9 participants