Ryan
Ryan

Reputation: 867

When and where may I load data, from a remote API, in my Ember.js application?

I'm learning Ember.js, and am writing an application that I want to perform the following tasks ...

  1. load some data from local storage
  2. check 3rd party API for new additional data
  3. append any additional and save entire thing back to local storage
  4. display a table of this data

My application is just a single route. I'm using the Ember.Route's model hook to load data from local storage. Where is a good spot to check that 3rd party API for any new data, though? Should I also do this in the model hook? I'd like to be able to display some sort of loading icon during the query to the 3rd party API and I'm not sure if that model hook will allow me to do this?

Right now, my Route only contains the following code ...

App.HistoryRoute = Ember.Route.extend({

    model: function (params) {

        // initialize model
        var model = { summoner: params, history: [] };

        if (typeof(localStorage.history) == 'undefined')
            return model;

        // fetch the data from local storage
        var history = JSON.parse(localStorage.history);

        // check for existing data
        if (!history.hasOwnKey(params.region) || !history[params.region].hasOwnKey(params.name))
            return model;

        // use the data from local storage
        return history[params.region][params.name];

    }

});

The data in local storage is namespaced using a region and name. It looks something like this ...

{
  "NorthAmerica": {
    "ryan": {
      "summoner": { "region": "NorthAmerica", "name": "ryan" },
      "history": [ ... ]
    }
  }
}

So, the Route's model method loads that data so that it can be used as the model. Where should I hit the 3rd party API to get new data, though? I'd like to check it for new data each time the page is refreshed. Thanks!

Upvotes: 6

Views: 1287

Answers (2)

joegoldbeck
joegoldbeck

Reputation: 546

The model hook is indeed the place to do this. Ember will wait until a promise returned in the model hook is resolved before completing the transition. If you want to display something while the page is loading, the HistoryLoadingRoute (or the corresponding history/loading template) will do exactly that. http://emberjs.com/guides/routing/loading-and-error-substates/

To make sure Ember waits for your API call to complete before moving out of the loading state, you'll need to return a promise in the model hook. You can use return $.ajax(... for this, or I prefer return ic_ajax.request(... from https://github.com/instructure/ic-ajax because it works better with Ember testing.

Upvotes: 0

Aaron Storck
Aaron Storck

Reputation: 886

The model hook is certainly the typical place that Ember expects you to place code like that. I wanted to create a lazy loading/infinite scroll mechanism and the best place to put the code to retrieve additional content was on the controller. For organization sake, I ended up moving the call to load my initial data into the controller as well. Using Ember.run.scheduleOnce, I was able to ensure that the load happened after the render queue:

init: function() {
  //make sure the nested views have rendered before fetching initial data
  Ember.run.scheduleOnce('afterRender', this, this.fetchInitialData);
},

//fetch initial data based on pageSize
fetchInitialData: function() {

  //enable loading animation
  this.set('isLoading', true);

  //get the first page of users
  var self = this;
  $.post("/user/search", {limit: 15})
    .then(function(response) {
      self.set('isLoading', false);
      self.set('total', response.total);
      self.set('model', response.users);
    });
}

Hope that helps! :)

Upvotes: 5

Related Questions