From reading the docs, it looks like you have to (or should) assign a model to a route like so:
App.PostRoute = Ember.Route.extend({
model: function() {
return App.Post.find();
}
});
What if I need to use several objects in a certain route? i.e. Posts, Comments and Users? How do I tell the route to load those?
This might not be best practice and a naïve approach, but it shows conceptually how you would go about having on multiple models available on one central route:
hope it helps
You could use the
beforeModel
orafterModel
hooks as these are always called, even ifmodel
is not called because you're using dynamic segments.As per the asynchronous routing docs:
So say you have a
themes
property on yourSiteController
, you could have something like this:For a while I was using
Em.RSVP.hash
, however the problem I ran into was that I didn't want my view to wait until all models were loaded before rendering. However, I found a great (but relatively unknown) solution thanks to the folks at Novelys that involves making use of the Ember.PromiseProxyMixin:Let's say you have a view that has three distinct visual sections. Each of these sections should be backed by its own model. The model backing the "splash" content at the top of the view is small and will load quickly, so you can load that one normally:
Create a route
main-page.js
:Then you can create a corresponding Handlebars template
main-page.hbs
:So let's say in your template you want to have separate sections about your love/hate relationship with cheese, each (for some reason) backed by its own model. You have many records in each model with extensive details relating to each reason, however you'd like the content on top to render quickly. This is where the
{{render}}
helper comes in. You can update your template as so:Now you'll need to create controllers and templates for each. Since they're effectively identical for this example, I'll just use one.
Create a controller called
love-cheese.js
:You'll notice that we are using the
PromiseProxyMixin
here, which makes the controller promise-aware. When the controller is initialized, we indicate that the promise should be loading thelove-cheese
model via Ember Data. You'll need to set this property on the controller'spromise
property.Now, create a template called
love-cheese.hbs
:In your template, you'll be able to render different content depending on the state of promise. When your page initially loads, your "Reasons I Love Cheese" section will display
Loading...
. When the promise is loaded, it will render all the reasons associated for each record of your model.Each section will load independently and not block the main content from rendering immediately.
This is a simplistic example, but I hope everyone else finds it as useful as I did.
If you're looking to do something similar for many rows of content, you may find the Novelys example above even more relevant. If not, the above should work fine for you.
Adding to MilkyWayJoe's answer, thanks btw:
returns
author would be
comments
... I believe the link backs are important so that the full relationship is established. Hope that helps someone.
Last update forever: I can't keep updating this. So this is deprecated and will likely be this way. here's a better, and more up-to-date thread EmberJS: How to load multiple models on the same route?
Update: In my original answer I said to use
embedded: true
in the model definition. That's incorrect. In revision 12, Ember-Data expects foreign keys to be defined with a suffix (link)_id
for single record or_ids
for collection. Something similar to the following:I have updated the fiddle and will do so again if anything changes or if I find more issues with the code provided in this answer.
Answer with related models:
For the scenario you are describing, I would rely on associations between models
(settingand only load theembedded: true
)Post
model in that route, considering I can define aDS.hasMany
association for theComment
model andDS.belongsTo
association for theUser
in both theComment
andPost
models. Something like this:This definition would produce something like the following:
With this definition, whenever I
find
a Post, I will have access to a collection of comments associated with that post, and the comment's author as well, and the user which is the author of the post,since they are all embedded. The route stays simple:So in the
PostRoute
(orPostsPostRoute
if you're usingresource
), my templates will have access to the controller'scontent
, which is thePost
model, so I can refer to the author, simply asauthor
(see fiddle)
Answer with non-related models:
However, if your scenario is a little more complex than what you described, and/or have to use (or query) different models for a particular route, I would recommend to do it in
Route#setupController
. For example:And now when I'm in the Post route, my templates will have access to the
user
property in the controller as it was set up insetupController
hook:(see fiddle)
Thanks to all the other excellent answers, I created a mixin that combines the best solutions here into a simple and reusable interface. It executes an
Ember.RSVP.hash
inafterModel
for the models you specify, then injects the properties into the controller insetupController
. It does not interfere with the standardmodel
hook, so you would still define that as normal.Example use:
Here is the mixin: