Choices: How to get a handle for an initialized Choices element

Created on 28 Mar 2018  ·  21Comments  ·  Source: Choices-js/Choices

If I have initialized my Choices element in the following way:

new Choices(document.querySelector(#choices'));

Is there a way to access the initialized Choices element somewhere else in the code if I don't have a reference to the original value? As far as I know, using new Choices always returns a new, uninitialized value.

The use case could be, for example, that I want to programmatically set the value (.setValue())

Most helpful comment

I found that you can set the value of an existing Choices instance that you cannot access but triggering the mousedown event on the item with the value for which you're looking:

handleSelect (obj, value) { let selectFields = obj.closest('.choices').querySelectorAll('.choices__item--selectable') for (let i = 0; i < selectFields.length; i++) { if (selectFields[i].dataset.value === value) { console.warn(selectFields[i].dataset.value) selectFields[i].dispatchEvent(new Event('mousedown')) } } }
(obj here is a select element)

All 21 comments

Hey,

All you need to do is assign it to a variable e.g.

const instance = new Choices(document.querySelector(#choices'));

instance.setValue();

👍

Hi,

The point was exactly that I don't have the option to assign it to a
variable.

On Wed, 28 Mar 2018, 17:31 Josh Johnson, notifications@github.com wrote:

Hey,

All you need to do is assign it to a variable e.g.

const instance = new Choices(document.querySelector(#choices'));instance.setValue(...);


You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
https://github.com/jshjohnson/Choices/issues/376#issuecomment-376907996,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AANfNycNy85QKI_GV30YXvXuVy0-GlBEks5ti569gaJpZM4S-tQH
.

Ahh I see, sorry.

As far as I know you could chain the method you want to call like:

new Choices(document.querySelector(#choices')).setValue();

There is no way of accessing an instance without referencing a variable as far as I know though.

For example, in FullCalendar you can get an instantiated calendar and then run methods, like this:

$('#calendar').fullCalendar().next();

You can try it in the console in the FullCalendar frontpage. A similar feature would be really useful with Choices.js.

See my previous comment. They are behaving the same way. One is just using jQuery's API.

It does not behave the same way AFAIK. I can demonstrate my issue this way:
I go to the Choices frontpage, open devtools console and type:

(new Choices('#choices-multiple-labels')).setValue(['Three'])

What I'd expect to happen is the option Three on the existing dropdown (initialized: true) to be selected. This does not happen.

@aleehedl If for whatever reason you don't have access to the initialization code then you're better off just destroying then reinitializing ChoicesJS. Possible even removing the '.choices' element altogether. But on another note if you have the ability to access the code where you initialized when you wrote 'new Choices(document.querySelector(#choices'));' then you can it to a variable then push that variable to an array attached to window. I do this when I have to add my initializations via a for loop. Otherwise I think we need more context to help you out. A JS fiddle would help us troubleshoot your issue better.

I just add new instance to data with $(element).data('choices', choices); And then I retrieve it by var choices = $(element).data('choices');But this is not good solution. There should be some other way to do it.

@aleehedl i totally agree to your point. i got the same problem, i want to destroy an existing choices element which is not saved in any variable. Every other library like slick, swiper or fullcalender offers the opportunity to call an existing element and run existing commands / methods. How does it work for choices?

@pliebig @aleehedl The develop branch has been updated to return an array of instances 👍

@jshjohnson hiya, what's the name of the method added to get the instances?

@jshjohnson hiya, what's the name of the method added to get the instances?

I would like to know that too ...

@heylookalive @fs86 When you create a new instance of Choices it will now return an array of instances if it has created more than 1.

So:

const [instance1, instance2] = new Choices(document.querySelector(#choices'));

Dosn't work for me. If i call new Choices() then my controls will get reinitialized.

@fs86 Not going to be able to debug your code without seeing it!

I wanted to create a small test project but I can't get it to work.

jsFunctions.js:

window.jsFunctions = {
  initializeChoices: function () {
    const controls = document.querySelectorAll('select');
    new Choices(controls, {
      searchEnabled: false,
      shouldSort: false
    });
  }
}

Error message:

Uncaught TypeError: Cannot read property 'element' of undefined
    at e.value (choices.min.js:2)
    at new e (choices.min.js:2)
    at Object.initializeChoices (jsFunctions.js:5)
    at HTMLDocument.<anonymous> (index.html:32)

@jshjohnson I have created a small repo for you where you can see the issue. Instead of getting an instance of an already initialized select element, the element will get reinitialized and added to the DOM every time you hit the button.

Here is the repo: https://github.com/fs86/ChoicesTest

@fs86 You are assigning the instance to a variable and not doing anything with it. You need to create a closure.

Something like:

let choices;

document.addEventListener('DOMContentLoaded', function () {
  choices = new Choices('select');
});

Thanks for your help, but I get still the same result. The select box is added multiple times to the DOM. See my updated repo.

Edit: Ok I think I understand. Do I have to hold the instances in a global variable or so? Actually I need to retrieve an instance of an already initialized element without holding all instances in an array. Is this possible?

Anybody got it? How to retrieve an instance of an already initialized element?
Or with global variables only?

I found that you can set the value of an existing Choices instance that you cannot access but triggering the mousedown event on the item with the value for which you're looking:

handleSelect (obj, value) { let selectFields = obj.closest('.choices').querySelectorAll('.choices__item--selectable') for (let i = 0; i < selectFields.length; i++) { if (selectFields[i].dataset.value === value) { console.warn(selectFields[i].dataset.value) selectFields[i].dispatchEvent(new Event('mousedown')) } } }
(obj here is a select element)

Was this page helpful?
0 / 5 - 0 ratings