1

Is there a way with EmberJS to show a loading template somewhere when something in my page is loading something?

For example, I have a page with many many songs artists, and each of them have many many songs. I load the page of the artists, and good, but in background I'm loading info about songs of everyone. I simply need a loading spinner somewhere that says to me the site is loading something (for example, there is in "Network" tab of Chrome Developer Tools something pending...)

how to do that in such an elegant Emberjs way?

2 Answers2

1

You can observe the isPending property of Ember.PROMISEPROXYMIXIN like so:

{{#if artist.songs.isPending}}
  loading...
{{/if}}
Ahmed Onawale
  • 3,992
  • 1
  • 17
  • 21
  • I do not understand, can you please explain more? –  Sep 18 '16 at 15:54
  • If I need a loading at the application state? Something that appear every time something in the entire app is loading? –  Sep 18 '16 at 16:06
  • You can create a loading template at the same root level with the application template. https://guides.emberjs.com/v2.8.0/routing/loading-and-error-substates/ – Ahmed Onawale Sep 18 '16 at 16:09
  • But the `isPending` change, no? isPending of what in the root level of the application route if I'm loading artists.songs? –  Sep 18 '16 at 16:10
  • It depends on what you are trying to achieve. If you want a loading template whenever the router is transitioning to another route, you can create an application loading template, but if what you want is to show a loading template whenever a model is loading, you can observe `isPending` or any of the mixin property that communicates the state of the model. http://emberjs.com/api/classes/Ember.PromiseProxyMixin.html – Ahmed Onawale Sep 18 '16 at 16:18
  • Ok, but can I create a component which appear when "some" model is loading somewhere? Let's say a "general" loader? This is a different loader than loading.hbs (Emberjs default) which does another thing than mine. Do you understand? –  Sep 18 '16 at 16:22
  • @JohnSam if that's specifically what you're looking for, you should update your question to make it more explicit. – Max Wallace Sep 19 '16 at 14:11
0

As far as I know (and based on a quick perusal of the API docs) Ember doesn't provide a built-in way to achieve this. Unless I'm wrong, this means you'll need to implement request state tracking yourself.

You could do this in Ember's adapter layer (e.g. add code in app/adapters/application.js), but the simplest solution might be to just work with jQuery directly. There are a few APIs you can use:

I'd recommend creating an Ember.Service to track this state-- then you can inject it in any Controller or Component that needs to render a template based on this info. Your Service could look like:

import Ember from 'ember';

export default Ember.Service.extend({

  init() {
    this._super(...arguments);
    const invalidateRequestInProgress = () => {
      this.notifyPropertyChange('dummyProperty');
    }

    $(document).ajaxStart(invalidateRequestInProgress);
    $(document).ajaxStop(invalidateRequestInProgress);
  },

  requestInProgress: Ember.computed('dummyProperty', function() {
    return Ember.$.active !== 0;
  }),

});

I haven't tested this code, so I'm not sure if it'll work in practice :)

Community
  • 1
  • 1
Max Wallace
  • 3,609
  • 31
  • 42
  • I'm trying the method that you suggest and it works well. But can you explain better what does that code? Specifically, I would understand, `notifyPropertyChange` is necessary? Use `Ember.computed` is performance proof? `return Ember.$.active !== 0;` what is exactly? We have good performance? What exactly loads the default loading of Ember (https://guides.emberjs.com/v2.8.0/routing/loading-and-error-substates/) since there is no loading during ajax calls to the server and then we have to resort to these manual methods? –  Sep 21 '16 at 20:10
  • 1
    (1) `notifyPropertyChange` tells Ember that any computed properties that rely on `'dummyProperty'` need to be recomputed. It's cache invalidation. (2) Using Ember.computed lets you check `requestInProgress` in your template. (3) `Ember.$.active !== 0;` is the same as `$.active !== 0;`, except using Ember's namespaced copy of jQuery-- in case there are multiple $s defined on the page. For what `$.active` means, check the link in my answer. – Max Wallace Sep 22 '16 at 11:48
  • 1
    (4) The "loading substate" in the article you linked to is only active when waiting for a Promise returned from the [model hook](https://guides.emberjs.com/v2.8.0/routing/specifying-a-routes-model/) of a route. Ember has no way of knowing about arbitrary AJAX calls you make. – Max Wallace Sep 22 '16 at 11:49
  • 1
    Last-- I realized the use of `notifyPropertyChange` with a computed property may be confusing for newcomers. I believe this is the best style, since it's lazy and more functional, but you could also write it differently by defining `invalidateRequestInProgress` as `() => { this.set('requestInProgress', Ember.$.active !== 0); }` (which is eager). – Max Wallace Sep 22 '16 at 11:52