Search code examples
ember.jsdelayhandlebars.jspageload

Template loading delay with Ember.js


I am working on an application that uses Ember.js and Handlebars.js. I have noticed that there can be a bit of a delay displaying templates when the page first loads. It makes sense that this happens since javascript has to create the HTML. When the page first loads it looks like a blank page has loaded, then suddenly everything appears.

Honestly, this is a problem that I can live with, but still it seems a bit awkward to me. I may just be over-analyzing things, but has anyone else noticed this and does anyone have a recommendation for how to make page loads appear more "natural"?


Solution

  • As I commented above, you can show a spinner while the page is rendering, loading data etc. As an example, below is a Mixin which shows a spinner until a View has rendered:

    App.ShowSpinnerWhileRendering = Ember.Mixin.create({
      layout: Ember.Handlebars.compile('<div class="loading">{{ yield }}</div>'),
    
      classNameBindings: ['isLoaded'],
    
      didInsertElement: function() {
        this.set('isLoaded', true);
        this._super();
      }
    });
    

    In the case where you want to wait for data to load (assuming that you use the router for showing views):

    App.ShowSpinnerWhileRendering = Ember.Mixin.create({
      layout: Ember.Handlebars.compile('<div class="loading">{{ yield }}</div>'),
    
      classNameBindings: ['isLoaded'],
    
      isLoaded: function() {
        return this.get('isInserted') && this.get('controller.isLoaded');
      }.property('isInserted', 'controller.isLoaded'),
    
      didInsertElement: function() {
        this.set('inserted', true);
        this._super();
      }
    });
    

    And mix it into your views:

    App.ApplicationView = Ember.View.extend(App.ShowSpinnerWhileRendering, {
     // ...
    });
    

    Then define some CSS rules to show a loading spinner (or something) on an element having a showSpinner class, and hiding it when it also has a isLoaded class:

    .loading{
      background-image: url("spinner.png") 
      background-color: #DFDFDF
    }
    
    .is-loaded .loading {
      /* back to default styling, e.g. */
      background-image: none
      background-color: white
    }