Closed aleehedl closed 6 years ago
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)
Really a shame not to be able to retrieve the instance from the HTML element... :'(
If you don't want to store the TomSelects in a global, you can keep the reference with the HTML element itself, like so: document.getElementById( '#list' )._TomSelect = new TomSelect( ....
and then later use e.g. document.getElementById( '#list' )._TomSelect.setValue( 'some value' )
Pretty stupid they don't give you the instance. It should be attached to the DOM object like every other lib.
Pretty stupid they don't give you the instance. It should be attached to the DOM object like every other lib.
Fucking hell, I had to dig the whole internet to find out that this plugin developed by 1000 developers...doesn't give the instance. Seriously, how ridiculous this is...
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)
Thanks. You saved time! I made the code readable.
const selectInput = document.querySelector("#selectInput");
if (selectInput.tagName == 'SELECT') {
const choiceItems = selectInput.closest(".choices").querySelectorAll(".choices__item--selectable");
for (let i = 0; i < choiceItems.length; i++) {
if (choiceItems[i].dataset.value === "{VALUE_TO_BE_SET}") {
choiceItems[i].dispatchEvent(new Event('mousedown'));
}
}
}
@HermanSchoenfeld I agree. The workaround I have found for this was pretty simple. may not work for @aleehedl but for anyone with source code access should work fine. Just simply append the returned choices object to the element at initialization.
let element = document.querySelector("#ChoicesDiv"); element.choices = new Choices(element, {});
from there you can run methods in other functions pretty easily.
https://codepen.io/dphaas2004/pen/xxMJYaV
hope it helps someone as I too spent most of my day searching the API and code for a way to to do this.
@HermanSchoenfeld I agree. The workaround I have found for this was pretty simple. may not work for @aleehedl but for anyone with source code access should work fine. Just simply append the returned choices object to the element at initialization.
let element = document.querySelector("#ChoicesDiv"); element.choices = new Choices(element, {});
from there you can run methods in other functions pretty easily.
https://codepen.io/dphaas2004/pen/xxMJYaV
hope it helps someone as I too spent most of my day searching the API and code for a way to to do this.
That's actually not bad solution, I think! Thanks!
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')) } } }
Dude, you saved my life. It took me days for this solution. Thanks bro!
If I have initialized my Choices element in the following way:
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()
)