ux
ux copied to clipboard
LiveComponent and non managed inputs
I am trying to use https://github.com/Choices-js/Choices in a LiveComponent. I have a controller to initialize an instance of Choices.js. Without LiveComponent it works nicely, but the problem is that Choices.js modifies structure of the input and also adds an additional choice search input, so it is not managed by LiveComponent and I don't see any point to map it in the component.
Question: is it possible somehow to ignore the input changes and let the LiveComponent to rerender after bluring this non mapped input?
So basically, you want a normal <input> that is NOT mapped to a model... but on "change", you DO want to trigger a re-render, is that correct? What about this?
<input data-action="live#$render">
It's a bit old but still open so..
If you can't change the hidden input, or if Choice.js force new value without dispatching "change" event, what about a custom stimulus controller that dispatch change event when Choices.js is blured ?
Maybe just have to listen on Choice.js "change" event (https://github.com/Choices-js/Choices#events), then dispatch change on hidden input ?
hiddenInput.dispatchEvent(new window.Event('change', { bubbles: true }));
I made custom datepicker and select2.js work with that.
That's a nice solution... and it makes me think that an even better thing would be something like:
const element = document.getElementById('example');
const example = new Choices(element);
element.addEventListener(
'addItem',
function(event) {
liveController.$render();
}
);
Basically, call the $render() method on the live controller directly, instead of needing to add a hidden input and then trigger a change event on it. The only question is: what's a good way/pattern to get access to the live controller instance? I'm thinking about a controller like this:
export default class extends Controller {
connect() {
this.element.addEventListener('live:connect', (event) => {
this.liveController = event.detail.controller;
});
// or, we would use targets - but you get the idea
const element = document.getElementById('example');
const example = new Choices(element);
element.addEventListener(
'addItem',
function(event) {
this.liveController.$render();
}
);
}
}
This is probably an approach that should be documented. Right now, the live:connect event isn't documented at all.
Thanks for the insights, will check it :)