Fiddle with the mostly-working code: http://jsfiddle.net/VDA2p/16/
Excerpt of Route believe where the problem lies:
// #/listings/:listing_id/videos
App.VideosRoute = Ember.Route.extend({
model: function(params) {
return this.modelFor('listing');
}
});
If I select a "videos" link, the url is '/listings/1/videos' (for example) and my content loads just fine. If I were to visit this url directly though through the address bar, no videos are retrieved. I've been playing around with calls to serialize() but can't get it working and I'm not sure I'm even on the right path. I've also noticed that once I visit the url directly and get no videos, if I then go directly to the '/listings' url (which loads content just fine) and select any of the "videos" links, the video content is no longer loaded for any of entries. However, if I refresh my browser/app while on the '/listings' url then content exists under the "videos" links.
UPDATE 1:
If I change the original code segment above to instead be
// #/listings/:listing_id/videos
App.VideosRoute = Ember.Route.extend({
model: function(params) {
return App.Listings.find(params.listing_id);
}
});
it works as expected, although I do not understand why.
UPDATE 2:
It did break the "View Video" link however when accessing the '/listings/1/videos' url directly and not via a link. It is now displaying as '/listings/null/videos/1' even though when you click on it the individual video loads just fine. Using the back button takes you back to '/listings/1/videos' where all of the "View Video" links no longer have a 'null' in them.
Attempting to go to a '/listings/1/videos/2' url directly, for example, throws the error of "Error: assertion failed: You used the dynamic segment video_id in your router, but App.Video did not exist and you did not override your state's model
hook." which I am now working to hunt down as well. Selecting the "View Video" link though will load the data just fine.
What you want to do is use a nested routing structure. This allows each nested level to do its serializing/deserializing as the route is evaluated.
For example, if you directly type in the URL /listings/1/videos/2
the App.ListingsRoute
's methods are called, then App.ListingRoute
's, then App.VideosRoute
's, and then finally App.VideosVideoRoute
's. In your old router, the flat nature didn't allow for the URL sections /listings
or /listings/:listing_id
to be properly handled, causing the errors you saw.
Some of the names of templates and routes are slightly different than the original example due to the added nesting. Check the emberjs routing docs if you want more details on the naming schemes for nested routes.
The renderTemplate
portion of the code tells ember to render the template into the {{outlet}}
provided by the application
route. The default is to assume there are nested {{outlet}}
s in each of the nested routes.
Router:
App.Router.map(function() {
this.resource('listings', function() {
this.resource('listing', { path: '/:listings_id' }, function(){
this.resource('videos', function() {
this.route('video', { path: '/:videos_id' });
});
});
});
});
Routes:
// #/index
App.IndexRoute = Ember.Route.extend({
redirect: function(){
this.transitionTo('listings');
}
});
// #/listings
App.ListingsIndexRoute = Ember.Route.extend({
model: function() {
return App.Listings.find();
},
renderTemplate: function() {
this.render({into: 'application'});
}
});
// #/listings/:listing_id
App.ListingRoute = Ember.Route.extend({});
// #/listings/:listings_id/videos
App.VideosIndexRoute = Ember.Route.extend({
model: function(params) {
return this.modelFor('listing').get("videos");
},
renderTemplate: function() {
this.render({into: 'application'});
}
});
// #/listings/:listings_id/videos/:videos_id
App.VideosVideoRoute = Ember.Route.extend({
renderTemplate: function() {
this.render({into: 'application'});
}
})