How to get around DOMContentLoaded for navigation?

We have a js function that runs on DOMContentLoaded, document.addEventListener(“DOMContentLoaded”, OURFUNCTION).

It works fine when you refresh the browser, but never shows when you navigate the site. I presume that’s because Discourse only loads the dom once and then the rest of handled with client side navigation, like an SPA. Some I’m wondering, how can we run the function on a navigation change in Discourse itself? There used to be easy ways to do that via the plugin API, but those APIs are deprecated and I don’t see them used anymore in any components. Is there an easy way to still do this? Or do we need to make a whole component to just execute some JavaScript upon a navigation change? THanks.

Hey,

If you’re looking for an event called when page loads, there is api.onPageChange.

api.onPageChange((url, title) => {
   console.log('the page changed to: ' + url + ' and title ' + title);
});

If you’re looking for something else, can you elaborate on what you want to achieve? We could give you a more precise answer.

On a side note, you have a ton of documentation that you might find helpful: Developer Guides - Discourse Meta.

3 Likes

Hmmm … I’m not sure it guarantees the DOM content has loaded, I believe it fires on the Route change, which is much earlier.

You’d need to consider attaching a Component to a Plugin Outlet and firing on didInsert modifier if the DOM loading is important.

If just the Route change is important, then yes, onPageChange should do it :+1:

1 Like

You may be right! :thinking:

onPageChange is called the next runloop, so I think it will still be called after DOMContentLoaded in most situations, but I can’t say it’s guaranteed.

I can see usage relying on onPageChange and doing DOM element stuff directly. From where is fired the routeDidChange event btw (EDIT: it’s from ember: RouterService - 6.1 - Ember API Documentation)?

I agree with the didInsert modifier, really neat!

1 Like

Thanks. I’ve read thru the documentation extensively and per my comments and a discourse member follow up there, the plugin API is legacy and will be deprecated soon. So while your code might work now, it will break soon, I believe in future updates. That’s why I’m looking for a better solution. Seems overkill to create a glimmer component for this so I was hoping there was another event that maybe we could use.

I don’t believe that is correct.

was updated last week.

What is deprecated are:

  • widget API
  • Raw templates
  • Overriding templates in general
3 Likes

Thanks for clarifying! So it’s just the widget api . Ok will try the api suggestions above first

3 Likes

This is kind of a blessing :sweat_smile:, Glimmer is a helluva lot more developer friendly

2 Likes

BTW, we tested it with api.OnPageChange and it works fine. We haven’t run into an instance yet here the DOM content wasn’t available upon calling OnPageChange, so it seems like it is fired after DomContentLoaded. But, I can’t be 100% sure. Thanks for your help on this.

3 Likes

Good. Just be aware that timing is not guaranteed. But glad it works for your use case!

1 Like

Can you please better explain what this means? What is the didInsert modifier? I’m firing on the decorateCookedElement. Thanks.

1 Like

(post deleted by author)

1 Like
1 Like

The doc is the way to go as pointed Robert; you can also see a ton of examples on the repo: Code search results · GitHub

1 Like

Oh, ok, so this is an ember feature and not related to discourse? Only part in the code that is really “discourse” related would be the pluginoutlet?

1 Like

Yep, it’s part of the Glimmer standard

pluginOutlets are just special Components that are designed to mount other Components:

2 Likes