Chris
Chris

Reputation: 3174

Populating Ember JS handlebars template with Ajax data from model?

the scenario.

I'm gathering some ajax data and want to populate a list with it. The data source is from LastFM's API - I know I'm receiving the data - see the image:

image showing data in ember view

Here's the code I'm using - any advice on best practice would be appreciated also - I'm enjoying Ember, but to be honest am still feeing my way around the way it works:

ember model

App.IndexRoute = Ember.Route.extend({
  model: function () {

      var albumArtwork = [];

      function convertString (data) {
          return encodeURIComponent(data).replace(/%20/g, "+");
      }

      $.each(topAlbums, function (i, el) {
          var request = 'http://ws.audioscrobbler.com/2.0/?method=album.getinfo&api_key=[REMOVED API KEY!]&artist=' + convertString(topAlbums[i].artist) + '&album=' + convertString(topAlbums[i].album) + '&format=json';

          $.ajax({
              'url': request
          }).done(function (d) {
              albumArtwork.push(d.album.image[1]['#text']);
          });
      });

      albumArtwork = _.toArray(albumArtwork)

      return albumArtwork;
  }
  });

ember handlebars template

<script type="text/x-handlebars" id="index">
    <div class="album-artwork-list-wrapper">
        <ul class="album-artwork-list">
            {{#each item in model}}
                <li class="album-artwork-item">
                    <img src="{{item}}">
                </li>
            {{/each}}
        </ul>
    </dv>
</script>

final thoughts

Here's what I think is happening: The handlebars template is being rendered before the data comes back from the API call. How to overcome this with Ember JS, I'm not certain - I have seen examples of a solution here on stackoverflow and attempted to use them but to no avail!

Many thanks for your help in advance!

Upvotes: 2

Views: 1443

Answers (1)

thecodejack
thecodejack

Reputation: 13379

you have to create promises so that async calls can become synchronised. Ember provides RSVP.js to do the same. RSVP.all fits your purpose. So..your code can be changed like this.

    App.IndexRoute = Ember.Route.extend({
      model: function () {

          var albumArtwork = [], promises =[];

          function convertString (data) {
              return encodeURIComponent(data).replace(/%20/g, "+");
          }

          $.each(topAlbums, function (i, el) {
              var request = 'http://ws.audioscrobbler.com/2.0/?method=album.getinfo&api_key=[REMOVED API KEY!]&artist=' + convertString(topAlbums[i].artist) + '&album=' + convertString(topAlbums[i].album) + '&format=json';

              promises.push(ajaxPromise(url));

      }
      return RSVP.all(promises).then(function(images) {
             // images contains an array of results for the given promises
             albumArtwork = images.filterBy('album');
             return albumArtwork;
          });
      });

var ajaxPromise = function(url, options){
  return Ember.RSVP.Promise(function(resolve, reject) {

    options.success = function(data){
      resolve(data);
    };

    options.error = function(jqXHR, status, error){
      reject(arguments);
    };

    Ember.$.ajax(url, options);
  });
};

Upvotes: 5

Related Questions