bluepnume
bluepnume

Reputation: 17118

Ember.js - multiple components on a page

I'm trying to build an Ember app and I'm running into some difficulty.

I have an index route, which I want to render the following page:

+--------------------------+
|   Welcome, [email protected]   |
+--------------------------+
|                          |
|        New Posts         |
|        ---------         |
|          *foo            |
|          *bar            |
|          *baz            |
|                          |
+--------------------------+

So I have an Account model, and a Post model. (which don't have any related fields)

I'm having conceptual difficulty with the following:

Ember routes have a model method which returns the model for the route. But what if I want multiple models to be associated with my route? In this case I have Account and Post. How do I make them both available to my page?

One thing I've tried is using setupController and manually setting account and posts on the controller so they can be accessed by the template. But if I can do this, what's the point/significance of the model method!?

Why does Ember want to associate a route with only a single model?

Appreciate any advice,

Thanks, Daniel

Upvotes: 3

Views: 1095

Answers (2)

darkbaby123
darkbaby123

Reputation: 2065

Using model callback has some advantages:

  1. It automatically generate model callback when you define router.
  2. In template, when you use link-to "someRoute" model, then when you click that link and transition to another route, the route will use the model you pass in for it's model (without calling model callback to get data).

See http://emberjs.com/api/classes/Ember.Route.html#method_model

But the biggest advantage I think, is promise support.

A route uses model callback to get data it needs, then in setupController, it pass the data to the second argument.

Notice what I mean setupController gets data from model callback. If the model callback returns a promise, the route will wait until this promise is resolved, then get the data from promise. If the promise is processing, the setupController is not called, and the template is not rendered.

App.PostsRoute = Em.Route.extend({
  model: function() {
    // The server response an array of posts like [{name: 'foo'}, {name: 'bar'}, {name: 'baz'}]
    return $.get('/api/posts.json');
  },

  setupController: function(controller, model) {
    console.log(model);  // it's array, not promise object
    controller.set('model', model);
  }
});

When you can use setupController to do the same thing, it's like this:

App.PostsRoute = Em.Route.extend({
  setupController: function(controller, model) {
    $.get('/api/posts.json').then(function(data) {
      controller.set('model', data);
    });
  }
});

BUT, setupController does not support promise, that means if you get data from the server in the setupController, Ember will render template before the data is prepared. In many case it's not what we want.

BUT, the model seems not a good place to get multiple data from server. You can do that using Ember.RSVP.all with multiple promises. but you also need to consider link-to. I'm not sure what is the best practice to get multiple data in a route and wait them all prepared before rendering template. If anyone has a good solution, Please tell me!

For your situation, I think you can use different route to do this. After all I think something like "Welcome, [email protected]" is a top bar for all of the pages, right? Then you can put it in ApplicationRoute, and render account info in application.hbs template.

Upvotes: 1

intuitivepixel
intuitivepixel

Reputation: 23322

One thing I've tried is using setupController and manually setting account and posts on the controller so they can be accessed by the template.

What you are doing is correct, this is what the setupController hook is for.

But if I can do this, what's the point/significance of the model method!? Why does Ember want to associate a route with only a single model?

In RC3, preventing the default behavior was impossible. In RC4, implementing the setupController hook prevents the default behavior from happening. This is a potentially breaking change for dev's migrating to newer versions.

Also note that if your route implements the setupController hook and you want to preserve the default behavior (the model from also being invoked) make sure you call this._super() from within the setupController hook. You can read more here in the announcing blog post.

Hope it helps.

Upvotes: 1

Related Questions