ux icon indicating copy to clipboard operation
ux copied to clipboard

LiveComponent and non managed inputs

Open norkunas opened this issue 3 years ago • 4 comments

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?

norkunas avatar Mar 23 '22 05:03 norkunas

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">

weaverryan avatar May 16 '22 13:05 weaverryan

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.

akyoscommunication avatar Aug 11 '22 17:08 akyoscommunication

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.

weaverryan avatar Aug 11 '22 19:08 weaverryan

Thanks for the insights, will check it :)

norkunas avatar Aug 12 '22 04:08 norkunas