twiz
twiz

Reputation: 10558

Loading external data into Ember template using ember-data/DataStore

Here is what I'm tyrnig to do:

  1. Make ajax request to retrieve JSON data from a PHP script
  2. Insert that information into DataStore Models
  3. Store those models within a controller
  4. Display the information using {{#each}} with a handlebars template


Any examples that implement all of the 4 steps would also be very helpful, since I can't seem to find any.

Upvotes: 0

Views: 2067

Answers (2)

MilkyWayJoe
MilkyWayJoe

Reputation: 9092

<edit>

Like I said in the comments, this questions asks a lot at once, so to follow up, here's a work in progress fiddle: http://jsfiddle.net/schawaska/dWcUp/

This is not 100%, but covers some of your questions. It uses the FixtureAdapter. I'll be updating it as I find time.

</edit>

1 Make ajax request to retrieve JSON data from a PHP script

Ember-Data will take care of that for you. Consider the following:

window.App = Em.Application.create();

App.Store = DS.Store.extend({
    revision: 12,
    adapter: 'DS.RESTAdapter'
});

App.Product = DS.Model.extend({
    name: DS.attr('string'),
    imageUrl: DS.attr('string')
})

The code above defines a data store (almost like an ORM) within your client app. Ember uses convention over configuration (heavily), so as per configuration this code expects your backend to have a resource in the same domain as /products which talks to GET, POST, PUT and DELETE.

2 Insert that information into DataStore Models

Considering what I said above, by calling one of the following:

App.store.find(App.Product) or App.Product.find()

EmberData will fire a GET request through AJAX targeting your resource /products, and if you say App.Product.find(1), it will target /products/1. Your app store will use its adapter and the adapter's serializer to translate the JSON result and materialize its data into your App.Product model.

3 Store those models within a controller

This is done when defining your application router. Regardless of what you do, Ember will run its own workflow, but it provides you several hooks, giving you the control of that specific action. Consider the following:

App.Router.map(function() {
  this.resource('products');
});

App.ProductsRoute = Ember.Route.extend({
  model: function() {
    return App.Product.find();
  }
});

The code above populates the model used in the products route (which you would access at http://yourdomain.com/#/products). Internally it will generate the code for your ProductsController, or you can define your own, which should extend ArrayController. Controllers will have a content property which is an alias to the model or model collection. Again, convention over configuration.

4 Display the information using {{#each}} with a handlebars template

Providing you're following the conventions, in your handlebars template, you should iterate through your collection like this:

{{#each product in controller}}
    {{#linkTo 'product' product}}
        {{product.name}}
    {{/linkTo}}
{{/each}}

  • Does ember-data have a built in way of retrieving data? If not, where should the AJAX request be implemented?

Yes, simply call App.Product.find() for a product model and it return you a blank ModelArray while firing the AJAX request to the products resource in your backend, then materialize/populate your data into each model once it receives the data back from the server.

  • What is the best way to insert the JSON data into the DS model?

You shouldn't be concerned about this if you're using ember-data. The framework does that for you in most cases. That's why we love it. You might, however, have to configure mapping, namespace and plurals depending on your backend.

  • What is the best way to then sync the models up with a Controller?

Something similar to this:

var product = App.Product.createRecord({
    name: 'laptop',
    imageUrl: 'path/to/image.png'
});
product.save();

This should fire a POST or PUT request to your backend API.


You should definitely check:

http://emberjs.com/guides/

https://peepcode.com/products/emberjs

http://toranbillups.com/blog/archive/2013/01/03/Intro-to-ember-js-and-the-new-router-api/

Upvotes: 2

Wildhoney
Wildhoney

Reputation: 4969

Making the AJAX request

// Find all pets.
var pets = App.Pet.find();

// Find pet with ID of 1.
var pet = App.Pet.find(1);

Into DataStore Models

pets above will be a DS.RecordArray containing many App.Pet models, whereas pet is just one App.Pet.

Store in Controller

App.IndexRoute = Ember.Route.extend({
   model: function() {
       return App.Pet.find(4);
   } 
});

The router is used to setup the controller, and so we specify here that the IndexController should hold one App.Pet with the ID of 4. This can of course be dynamic. Since your controller represents only one model, it should be of the type ObjectController, but if it was used to store many pets, then it should be of the type ArrayController.

By specify the model, you will have access to it in your IndexController and index view (data-template-name="index"). This is because when you move into your index route, the IndexController is located/instantiated, IndexView is instantiated and placed into the DOM, all after consulting the IndexRoute for setting up the controller.

You can now do something like this in your template (although model. is not necessary): {{model.name}}, which will get you your pet's name.

Display using #each

Find all your pets using a modified version of the above code, but returning all of the pets. Remember, this is done by specifying no arguments to your find method:

App.IndexRoute = Ember.Route.extend({
   model: function() {
       return App.Pet.find();
   }
});

Now we can do loop through all of the pets in the index template. Whilst there are many ways to loop, such as including content./model., excluding .content/model, using this, controller, et cetera..., it's not necessary, but that's for another day. What matters at the moment is that this will work for you, and will be the most self-intuitive:

{{#each pet in controller}}
    {{pet.name}}
{{/each}}

I'll put together a jsFiddle for this if you would like. Please let me know.

Questions

Does ember-data have a built in way of retrieving data? If not, where should the AJAX request be implemented?

Yes, that's Ember Data module which has some good guides on EmberJS.com.

What is the best way to insert the JSON data into the DS model?

Using Ember Data as per the examples up above.

What is the best way to then sync the models up with a Controller?

Using the model hook in the appropriate route to specify which model(s) your controller represents.

Upvotes: 2

Related Questions