Choices icon indicating copy to clipboard operation
Choices copied to clipboard

Restore select to initial value

Open pieecia opened this issue 2 years ago • 11 comments

hey,

I checked the live preview in the documentation, the button to reset the form (button type="reset") causes select not to keep the default value, select is empty

this feature works fine in version 9.0.1, the bug has appeared since version 9.1.0

how to reproduce the issue:

  • visit https://choices-js.github.io/Choices/
  • change select to a random value
  • click the "reset" button

Zrzut ekranu 2022-03-21 o 11 26 45

pieecia avatar Mar 21 '22 09:03 pieecia

Is there a solution for this issue?

marcelaerts avatar Apr 08 '22 07:04 marcelaerts

We experienced the same problem. We call form.reset() between each page load. Seems like form.reset() call Choices._onFormReset -> resetTo with _initialState. _initialState doesn't contains the preset values from constructor. And the rootReducer will clone the action state in "RESET_TO".

My guess is that _initialState should contains the data of _preset* at line 297 (before the bind calls)

yanmorinokamca avatar May 16 '22 14:05 yanmorinokamca

I am experiencing the same issue. Did anybody find a solution?

masiorama avatar Jul 28 '22 12:07 masiorama

No feedback on this? There is at least another one issue about this problem, with no answer #1053

masiorama avatar Sep 09 '22 09:09 masiorama

@yanmorinokamca I followed you analysis looking at the code and I guess you got it right... did you find any solution?

masiorama avatar Sep 09 '22 10:09 masiorama

As a temporary workaround in my application I managed to intercept reset event on the form and then repopulate all the options by hand:

document.getElementById('formId').select.addEventListener('reset', (ev) => {
    choices.setChoices(async () => {
        return this.options.map(({ value, label }) => ({
            value,
            label,
            selected: false,
        }));
    });
})

This should be unnecessary but at least my app does work. I hope this will be fixed at some point.

masiorama avatar Sep 09 '22 12:09 masiorama

@yanmorinokamca I followed you analysis looking at the code and I guess you got it right... did you find any solution?

Hi, we didn't have time to debug the library, so we replaced the form.reset() with a custom reset of each field.

yanmorinokamca avatar Sep 09 '22 15:09 yanmorinokamca

@yanmorinokamca I followed you analysis looking at the code and I guess you got it right... did you find any solution?

Hi, we didn't have time to debug the library, so we replaced the form.reset() with a custom reset of each field.

I see. Unfortunately I cannot explicitly reset each field because it is a component that has to handle different forms, with many different fields. Thanks for your reply.

masiorama avatar Sep 09 '22 15:09 masiorama

@masiorama I tried your code and saw that the event is not triggered:


const choicesTagsObj = new Choices('#choices-tags', {
            maxItemCount: 4,
            removeItemButton: true,
            allowHTML: false,
            position: 'bottom',
            itemSelectText: 'Push',
            maxItemText: (maxItemCount) => {
                return `Only ${maxItemCount} can be selected`;
            },
        });

document.getElementById('choices-tags').addEventListener('reset', (ev) => {
     console.log('reset');
})

what's the problem?

After some minutes

Some points:

  1. Reset event works only for a form, not for a select element.
  2. Choices deletes options structure from a select, so you need to copy it into var before create new Choices element.

Working code:

let choicesTags = document.getElementById("choices-tags");
//copy full select node with values
let choicesTagsBefore = choicesTags.cloneNode(true);
//convert to array
choicesTagsBefore = Array.from(choicesTagsBefore.options); 

const choicesTagsObj = new Choices(choicesTags, {
    maxItemCount: 4,
    removeItemButton: true,
    allowHTML: false,
    position: 'bottom',
    itemSelectText: 'Push',
    maxItemText: (maxItemCount) => {
        return `Only ${maxItemCount} can be selected`;
    },
});

//fill again after form reset (Choices.js bug workaround)
document.getElementById('therapy-form').addEventListener('reset', (ev) => {
    // console.log('reset');
    choicesTagsObj.setChoices(async () => {
        return choicesTagsBefore.map(({ value, label }) => ({
            value,
            label,
            selected: false,
        }));
    });
})

Sogl avatar Dec 18 '22 12:12 Sogl

this feature works fine in version 9.0.1, the bug has appeared since version 9.1.0

Bisected to: 68313da4122ec7f76274b22926e762914c96723d

(which is the conversion to TypeScript 🥲)


Tracked down to

-    // Set initial state (We need to clone the state because some reducers
-    // modify the inner objects properties in the state) 🤢
-    this._initialState = cloneObject(this._store.state);

after

https://github.com/Choices-js/Choices/blob/5dbea2825a5887d88d6947443f4874bb7b84cc3a/src/scripts/choices.ts#L343

tagliala avatar Dec 19 '22 21:12 tagliala

I've encountered this issue now and hoping to see this fixed soon. I tried the above temporary solution, but I lose my option groups.

Mopster avatar Mar 16 '23 04:03 Mopster