Closed norkunas closed 1 year ago
I'm thinking the solution is to use browser events - like #794.
Here's the thinking: if you are "managing" the state of something (a check box, modal opened/closed, etc), you should choose to manage that either entirely client-side with custom JS or server-side with LiveComponents. In your situation, since you have Stimulus code to handle things, in your LiveAction
, I would dispatch a browser event - e.g. uncheck
and maybe even pass the id or color of the one you want unchecked if necessary (my event naming may be poor for your actual situation). Then, update your existing Stimulus controller to listen to this event and do the "uncheck" work needed.
I've done the same thing recently for a modal: I use Bootstrap's native JavaScript on a link to open a modal - no LiveComponents code needed for that part. Then, via a child component that lives in the modal, when I submit to a LiveAction
on that child component, it dispatches a browser event which tells a modal
Stimulus controller to close that modal. Hence: the modal state is entirely handled client-side.
Thoughts?
I would dispatch a browser event - e.g. uncheck
Hmm :) that's optimistic. I want stimulus controllers to be agnostic from live components, so in this case checkbox controller listens only for change
event and determines based on event.target.checked
, so somehow I need to set target.checked = bool
, but looking at dispatchBrowserEvent
I can pass only event.detail
:)
With modals I currently chose an <turbo-stream action="remove">
approach to avoid leaving modal in the DOM, but good to know that this opens possibility for another approach :)
Hmm :) that's optimistic. I want stimulus controllers to be agnostic from live components, so in this case checkbox controller listens only for change event and determines based on event.target.checked, so somehow I need to set target.checked = bool, but looking at dispatchBrowserEvent I can pass only event.detail
You're not really binding your Stimulus controllers to live components - you're giving them an extra hook point (e.g. if someone dispatches an uncheck
event, you listen to that to do something). However, I realize there may be a hiccup in my logic. If you dispatchBrowserEvent
, that'll dispatch on the root component element. So, your custom checkbox Stimulus controller would need to be registered on that same root component element (or a parent), else the DOM event would never bubble to them.
Assuming your Stimulus controller IS on the same element (or a parent) of the live component root element, you could do something like this to pull this off:
// in connect()
this.element.addEventListener('check:uncheck', (event) => {
// pretend you pass a "value" to dispatchBrowserEvent with the value of the item that should be unchecked
const targetedValue = event.detail.value;
const checkbox = this.element.querySelector(`input[type="checkbox"][value="${targetedValue}"]`);
checkbox.checked = false;
});
Still not the MOST elegant thing - but let me know what you think.
Thanks, but I will need more time to check this as I'll be off for a week, so will get back to you later.
Yes, in backend I use
html_classes
to apply them based on states. The component was made to work without live components - so for UI to know what color class to apply on checkbox If it's checked I need to expose it to stimulus. So now with in a different part of app it was integrated into a live component and then the problem arose. And yes - it is to make experience feel faster :)