Skip to content

[Live] Adding a custom Stimulus controller to a live component #527

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
weaverryan opened this issue Nov 4, 2022 · 6 comments · Fixed by #589
Closed

[Live] Adding a custom Stimulus controller to a live component #527

weaverryan opened this issue Nov 4, 2022 · 6 comments · Fixed by #589
Labels
Bug Bug Fix

Comments

@weaverryan
Copy link
Member

Sometimes you'll want to attach a stimulus controller to the root element of your live controller. Currently, you might try this:

<div
    {{ attributes.defaults({ 'data-controller: 'foo'})
>

But, I don't think that works, as I think we're always setting data-controller to live:

Also, that's a pretty ugly syntax, especially if you need to pass in some values 😱 .

What about one of the following:

<div
    {{ attributes.stimulusController('foo', {}) }]

    {{ stimulus_controller('foo', {})|attributes }}

    Is this one even possible? Would `|merge` instead of "+" work?
    {{ stimulus_controller('foo', {}) + attributes }}
>

stimulus_controller returns a StimulusControllersDto which has a toArray() method.

@rdavaillaud
Copy link
Contributor

Hi Ryan,

I stumbled upon the subject today.
What about instead of using attributes, use a live_controller() function returning a StimulusControllersDto.
As stimulus_controller is also a filter, we can have something like:

<div {{ live_controller() | stimulus_controller('foo', {}) >

This will unfortunately tie the ux code to webpack-encore-bundle, this may be not wanted.

Maybe we can add to this webpack bundle a filter toStimulusControllersDto to extract a Dto from the attributes and use something like :

<div {{ attributes|toStimulusControllersDto|stimulus_controller('foo', {}) }} >

just throwing some ideas.

@jbelien
Copy link

jbelien commented Dec 2, 2022

Hello,

I'm trying to link a custom controller to my Live Component.
From the documentation, it seems to be possible but I can't seem to figure out how to do it.
Same for the following code (from the documentation), component is always undefined.

const component = document.getElementById('id-on-your-element').__component;

While researching, I've found this current issue.
Does that mean it's currently not possible ?

And if it's possible, could you guide me to how to do it ?
Thanks a lot!

@weaverryan weaverryan added the Bug Bug Fix label Dec 2, 2022
@weaverryan
Copy link
Member Author

Hey @jbelien!

Ok, 2 separate things here:

  1. Yes, currently, it's not possible (at least not in a reasonable way) to attach a Stimulus controller directly to your root element. But you could certainly put a controller around your root element, though totally not ideal. I've added the Bug label to this issue, and this is really a bug.

  2. About the undefined __component. Your code should absolutely work. One guess is that this code may be running just before the live controller is initializing. If that's true, then yes, the documentation is a bit wrong - or at least misleading, as it may not always work. Try this instead:

const element = document.getElementById('id-on-your-element');
element.addEventListener('live:connect', (event) => {
    const component = event.detail.component;
});

That should be more reliable. You could also put this code into a Stimulus controller - https://symfony.com/bundles/ux-live-component/current/index.html#working-with-the-component-in-javascript - that goes around your live controller element.

Let me know if this fixes it. We may need a warning in the docs about the other code that, if called too early, the component won't be there yet.

@jbelien
Copy link

jbelien commented Dec 2, 2022

Thanks A LOT @weaverryan for these clear(er) explanation. 😄

  1. I indeed missed the (really important) "around" word in the documentation! It works "as expected". 👍

  2. For the other issue, the documentation got me confused because it says the following:

    const component = document.getElementById('id-on-your-element').__component;
    component.mode = 'editing';

    That document.getElementById('id-on-your-element').__component syntax doesn't seem to work but your suggested syntax works indeed like a charm. 👍

    const element = document.getElementById('id-on-your-element');
    element.addEventListener('live:connect', (event) => {
        const component = event.detail.component;
    });

@weaverryan
Copy link
Member Author

Awesome! Thank you for the update. In addition to fixing this bug, we should add a note/warning around the document.getElementById('id-on-your-element').__component example.

@weaverryan
Copy link
Member Author

See #589

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Bug Fix
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants