# How to tell if page is loading in theme component / widget?

**URL:** https://meta.discourse.org/t/how-to-tell-if-page-is-loading-in-theme-component-widget/190190
**Category:** Development
**Created:** [May 12, 2021, 1:41pm UTC](https://meta.discourse.org/t/how-to-tell-if-page-is-loading-in-theme-component-widget/190190 "2021-05-12T13:41:26Z")
**Posts on this page:** 11
**Page:** 1

<div class="post-metadata">

### Author: ![Zach\_Swinehart](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/zach_swinehart/32/210979_2.png) [@Zach\_Swinehart](https://meta.discourse.org/u/Zach_Swinehart)
#### Post date: [May 12, 2021, 1:41pm UTC](https://meta.discourse.org/t/how-to-tell-if-page-is-loading-in-theme-component-widget/190190/1 "2021-05-12T13:41:26Z")

</div>

I feel like I’m probably missing something obvious here, but I can’t figure it out. I have a theme component that loads up some widgets, and I’m using the following code to re-render them after the user navigates to a new page (borrowed from category banners)

```
api.decorateWidget("my-widget:after", (helper) => {
    helper.widget.appEvents.on("page:changed", () => {
      helper.widget.scheduleRerender();
    })
});

```

However, this code waits until after the new page has loaded to update the widget. What I’m hoping to do is hide my widget content as soon as someone clicks a link to another page, similar to how the native discourse functionality is to hide things and show a loading spinner immediately on click.

I see in app\assets\javascripts\discourse\app\templates\discovery.hbs that the div container observes a “loading” var, but I can’t figure out where that comes from and how to “tap in” to that or observe the loading state in my widget.

Appreciative of any answers or simply pointing me in the right general direction. 🙂

Thanks,

Zach

---

<div class="post-metadata">

### Author: ![Zach\_Swinehart](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/zach_swinehart/32/210979_2.png) [@Zach\_Swinehart](https://meta.discourse.org/u/Zach_Swinehart)
#### Post date: [May 19, 2021, 8:30am UTC](https://meta.discourse.org/t/how-to-tell-if-page-is-loading-in-theme-component-widget/190190/2 "2021-05-19T08:30:27Z")

</div>

Thought I’d bump this one up – happy to pay for some premium support to get an answer if need be.

---

<div class="post-metadata">

### Author: ![fzngagan](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/fzngagan/32/259349_2.png) [@fzngagan](https://meta.discourse.org/u/fzngagan)
#### Post date: [May 19, 2021, 10:11am UTC](https://meta.discourse.org/t/how-to-tell-if-page-is-loading-in-theme-component-widget/190190/3 "2021-05-19T10:11:10Z")

</div>

Can you briefly describe what behaviour is desired and on which exact pages?

---

<div class="post-metadata">

### Author: ![hawm](https://avatars.discourse-cdn.com/v4/letter/h/f07891/32.png) [@hawm](https://meta.discourse.org/u/hawm)
#### Post date: [May 19, 2021, 11:16am UTC](https://meta.discourse.org/t/how-to-tell-if-page-is-loading-in-theme-component-widget/190190/4 "2021-05-19T11:16:13Z")

</div>

You may try `queueRerender()` instead of `scheduleRerender()`

> [@A tour of how the Widget (Virtual DOM) code in Discourse works](https://meta.discourse.org/t/a-tour-of-how-the-widget-virtual-dom-code-in-discourse-works/40347/1):
>
> ### Bindings and Rerendering Content
> 
> If you’ve been working with Ember for a while, you might be wondering how the widgets know when they need to be rerendered since they aren’t using Ember’s bindings or observers system. In fact, this is one of the big trade offs widgets make: in Ember’s view rendering this is handled transparently for you, but with Widgets we assume the widget only needs to be re-rendered when you interact with them.
> 
> Widgets are rerendered when:
> 
> - A user clicks on them
> - After any actions are triggered
> - If an action returns a promise, after that promise has resolved
> 
> The above cases count for the **vast** majority of the times when Discourse needs to rerender a widget. However, if you have an edge case, a widget can rerender itself by calling `this.queueRerender()` .
> 
> Render calls are coalesced on the [Ember Run Loop](https://guides.emberjs.com/v1.12.0/understanding-ember/run-loop/), so don’t be afraid to call `this.queueRerender()` multiple times in the same event loop – the widget will only render one time for all the changes you’ve queued.

---

<div class="post-metadata">

### Author: ![Zach\_Swinehart](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/zach_swinehart/32/210979_2.png) [@Zach\_Swinehart](https://meta.discourse.org/u/Zach_Swinehart)
#### Post date: [May 19, 2021, 12:17pm UTC](https://meta.discourse.org/t/how-to-tell-if-page-is-loading-in-theme-component-widget/190190/5 "2021-05-19T12:17:23Z")

</div>

Thanks for the responses guys.

I have a number of widgets I’ve built for certain category pages, and I’d ideally like to hide them immediately when someone navigates away from a page. Here’s a 45 second loom video demo of what I’m going for: [Google Chrome - Latest Rental Cities/California topics - Afford Anything Forums - Google Chrome | Loom](https://www.loom.com/share/b75394bd00674d6e9ea74c21c1c01f1c)

@hawm I’m not sure that the queue re-render is what I need here, as this isn’t really about re-rendering my widgets, but rather about giving my widgets awareness of whether or not the global Discourse app is loading a new page.

---

<div class="post-metadata">

### Author: ![fzngagan](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/fzngagan/32/259349_2.png) [@fzngagan](https://meta.discourse.org/u/fzngagan)
#### Post date: [May 19, 2021, 1:14pm UTC](https://meta.discourse.org/t/how-to-tell-if-page-is-loading-in-theme-component-widget/190190/6 "2021-05-19T13:14:20Z")

</div>

The short it is, the condition should be in the template. i.e.

```plaintext
{{#if xyz}}
your code
{{/If}}

```

The ember templates dynamic. If the value changes, the widget will be hidden.

---

<div class="post-metadata">

### Author: ![Zach\_Swinehart](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/zach_swinehart/32/210979_2.png) [@Zach\_Swinehart](https://meta.discourse.org/u/Zach_Swinehart)
#### Post date: [May 19, 2021, 2:00pm UTC](https://meta.discourse.org/t/how-to-tell-if-page-is-loading-in-theme-component-widget/190190/7 "2021-05-19T14:00:58Z")

</div>

Yes, of course. 🙂 I am not struggling with the if/then syntax; what I’m asking is if there’s a way that I can check if Discourse is currently loading a new page.

---

<div class="post-metadata">

### Author: ![hawm](https://avatars.discourse-cdn.com/v4/letter/h/f07891/32.png) [@hawm](https://meta.discourse.org/u/hawm)
#### Post date: [May 19, 2021, 4:11pm UTC](https://meta.discourse.org/t/how-to-tell-if-page-is-loading-in-theme-component-widget/190190/8 "2021-05-19T16:11:04Z")

</div>

> [@Zach\_Swinehart](#):
>
> awareness of whether or not the global Discourse app is loading a new page.

I think to hack into the [discovery](https://github.com/discourse/discourse/blob/master/app/assets/javascripts/discourse/app/routes/discovery.js) route by using the `modifyClass` API then trigger some custom event would work.

[https://api.emberjs.com/ember/3.12/classes/Route](https://api.emberjs.com/ember/3.12/classes/Route)

> [@Zach\_Swinehart](#):
>
> I see in app\assets\javascripts\discourse\app\templates\discovery.hbs that the div container observes a “loading” var, but I can’t figure out where that comes from and how to “tap in” to that or observe the loading state in my widget.

The `loading` variable comes from the `discovery` route that I mentioned above, the widget attached to plugin-outlet may not able to access it since it doesn’t pass as an argument, it depends on the definition of plugin-outlet.

---

<div class="post-metadata">

### Author: ![Zach\_Swinehart](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/zach_swinehart/32/210979_2.png) [@Zach\_Swinehart](https://meta.discourse.org/u/Zach_Swinehart)
#### Post date: [May 20, 2021, 7:38am UTC](https://meta.discourse.org/t/how-to-tell-if-page-is-loading-in-theme-component-widget/190190/9 "2021-05-20T07:38:22Z")

</div>

Okay, thanks a bunch. I’ll do some digging and see what I find, and update this with a solution for posterity if I find one 🙂

---

<div class="post-metadata">

### Author: ![Zach\_Swinehart](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/zach_swinehart/32/210979_2.png) [@Zach\_Swinehart](https://meta.discourse.org/u/Zach_Swinehart)
#### Post date: [June 2, 2021, 10:48am UTC](https://meta.discourse.org/t/how-to-tell-if-page-is-loading-in-theme-component-widget/190190/10 "2021-06-02T10:48:56Z")

</div>

I managed to finally find a solution. Spent sooooooooooo long on this and IMO it’s worth merging into core because honestly it feels like it should already exist anyway in core.

I added the code below to my theme component; what it does is adds a “loading” class to the body as soon as routing starts, and then removes it as soon as routing is complete. Maybe this would be simple/obvious for folks who know ember, but it took me an obscenely long time (and trying a million things + reading through all threads on here I could find) to figure out.

With this core code in place, I can add loading spinners and such to my different widgets that will have their css and visibility be driven by whether or not the body tag has the `loading` css class.

```plaintext
initialize() {
    withPluginApi("0.8.8", (api) => {
      const router = api._lookupContainer('router:main');
      router.reopen({
        addLoadingCSSClassToBody: function() {
          document.body.classList.add("loading");
        }.on('willTransition')
      });

      router.reopen({
        removeLoadingCSSClassFromBody: function() {
          document.body.classList.remove("loading");
        }.on('didTransition')
      });
    });
  },
};

```

---

<div class="post-metadata">

### Author: ![jordan.vidrine](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/jordan.vidrine/32/515563_2.png) [@jordan.vidrine](https://meta.discourse.org/u/jordan.vidrine)
#### Post date: [June 4, 2021, 9:24pm UTC](https://meta.discourse.org/t/how-to-tell-if-page-is-loading-in-theme-component-widget/190190/11 "2021-06-04T21:24:43Z")

</div>

The code I am sharing isn’t from a widget, but it is from a component that we did release for download [here on meta](https://meta.discourse.org/t/showcased-categories-theme-component/173524).

In it we use the router, along with `@discourseComputed` to check if the route has changed, and render based on that.

You can look deeper into the code if you are interested in how it works.

> <https://github.com/discourse/discourse-showcased-categories/blob/2a340c0675a4ee5683449229eeb052f25a546999/javascripts/discourse/components/two-topic-list.js#L9-L10>
