I realise this is an old topic but handling nested content is not directly covered AFAIKT in the guides.
I also noticed that the array controller is never in the view context by default.
I think you can achieve the result you are looking for as follows:
App.PostsController = Em.ArrayController.extend({
itemController: 'post'
});
App.PostController = Em.ObjectController.extend({
needs: [ 'comments'],
isSelected: function() {
this.get('controllers.comments').anyBy('isSelected')
}.property('controllers.comments.@each.isSelected')
});
App.CommentsController = Em.ArrayController.extend({
itemController: 'comment'
});
App.CommentController = Em.ObjectController.extend({
isSelected: false
});
Then in the post template:
{{title}}
{{body}}
{{etc}}
{{#view controller=controllers.comments}}
{{#each controller}}
...
{{/each}}
{{/view}}
The important thing I found is that without the use of the view helper the comments array controller context was completely out of the picture when #each is used. Using view
sets the context to the array controller, and using #each on controller
and NOT content
things just work.
The router does however need to setup the comments controller for the post in setupController
. eg:
setupController: function(controller, model) {
this.controllerFor('comments').set('model', model.get('comments'));
this._super.apply(this, arguments);
}
The above works for the singular post route, but since the original question is trying to do this for a collection of posts some more work is needed in the route. You will probably have to create a comments controller for each post and set comments
directly on the post controller, rather than relying on needs
since AFAIKT there would only be a singular ‘comments’ controller and that wouldn’t work for multiple posts.
I would happy to be enlightened on how to make this work better if anyone else has a better suggestion.
I’m still not satisfied this is the right approach when dealing with nested object graphs/complex resources. The user interface cannot be functional if everything is decomposed to addressable router based fragments as you can only deal with a single slice of something at a time. What if I have say a person that has multiple addresses, multiple emails or multiple other related important things and I want it all presented / editable. I won’t be using lots of routes to see just a slice of a person when those things are logically part of the person. Having to fetch a model and then construct a controller decorator hierarchy manually is not really a good solution.
I am thinking there should be a way similar to needs
where the controller can declare that it wants nested controller facades created for certain content properties rather than the router having to do it. I’m relatively new to Ember so there may be a very simple way to do that but I’m not aware of one yet having poured over the documentation.
UPDATE: I’m using the code from @mmun’s PR above and its working terrifically. Its a lot saner than the combination of needs
(and some alias properties) and manually setting up the nested controllers in routes. Thanks @mmun ! I just hope something this useful makes it into Ember proper, its an amazingly simple yet powerful approach for decorating model properties as nested controllers. I still need the view helper/wrapper for setting context around {{#each}}
but the combination of Em.computed.controller and the view helper works well for rendering and interacting with arbitrarily nested/embedded object graphs at an Ember route endpoint.