Can't access element defined in plugin outlet with DOM interface

AI-generated summary

The discussion revolves around accessing an element defined in a plugin outlet using the DOM interface. MrDavis97 created a plugin outlet with a button below the site header and attempted to access it with JavaScript, but received a null output.

Merefield suggested that the issue is due to the selector running before the template is rendered. They recommended turning the code into an Ember Component and using a hook like didInsertElement() to capture the point at which the element is available to modify.

MrDavis97 attempted to implement this solution but still received a null output. However, they eventually found a solution using api.decoratePluginOutlet to access the element after it has been rendered.

The correct code is:

api.decoratePluginOutlet(
       "below-site-header",
       (elem, args) => {
           const button = document.getElementById('vic-button');
           console.log(button);
       }
    );

This solution allows MrDavis97 to successfully access and manipulate the element.

I used the following plug-in outlet to make a button below the header.

<script type="text/x-handlebars" data-template-name="/connectors/below-site-header/vic-button">
    <a id="vic-button" href="http://mathbymiles.com/new-topic?title=&body=&category=uncategorized&tags=" class="btn btn-default">
        <span class="d-button-label">
            ask a question
        </span>
    </a>
</script>

It works just fine. However, now I want to access it with JavaScript to manipulate it, but when I try to get the element based on the id vic-button, the console just returns null.

So when I do

<script type="text/discourse-plugin" version="0.8">
    const button = document.getElementById('vic-button');
    console.log(button);
</script>

I get null as the output. Any ideas?

It’s probably running your selector before it’s rendered the template.

You need to do this ‘in framework’.

The best approach would be to turn this into an Ember Component, then use a hook like didInsertElement() to capture the point at which it’s available to modify.

Remember this is a web app not a web page. Elements are dynamic not static. The plugin outlet is itself a Component so is not rendered immediately.

Would I do something like this?

<script type="text/discourse-plugin" version="0.8">
    api.modifyClass('component:plugin-outlet', {
      didInsertElement() {
        this._super(...arguments);

        const button = document.getElementById('vic-button');
        console.log(button);
      },
    });
</script>

When I do this, there is a repeated null output to the console. I’m a complete newbie so I just tried to search around on meta for people doing similar things, so this is probably not the right track.

Figured it out:

api.decoratePluginOutlet(
       "below-site-header",
       (elem, args) => {
           const button = document.getElementById('vic-button');
           console.log(button);
       }
    );

The output shows what I want. And now I can manipulate the element!