Reputation: 17118
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
Reputation: 2065
Using model
callback has some advantages:
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
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