Following the examples on Ember for setting the itemController in my ArrayController definition causes the blocking error message:
TypeError: Cannot call method 'lookup' of null
JSFiddle: http://jsfiddle.net/jgillick/M4BVV/
// Addresses array controller
App.AddressesController = Ember.ArrayController.extend({
itemController: 'address'
});
// Address object controller
App.AddressController = Ember.ObjectController.extend({
city: function(){
return "San Francisco";
}.property()
});
The only way that I have found to fix this is either...
{{#each addresses itemController="address"}}
<li>{{line1}}, {{city}}</li>
{{/each}}
...or...
var addresses = App.AddressesController.create({
container: indexController.get('container'),
content: [
App.Address.create({'line1': '700 Hansen Wy'}),
App.Address.create({'line1': '900 Hansen Wy'})
]
});
Both of these solutions feel hacky and very wrong. What am I doing wrong with setting itemController in the ArrayController itself?
The itemController
from the controller and the each view, don't have relation.
Although that do the same thing: wraps an object in a specified controller.
Your first implementation throws Cannot call method 'lookup' of null
, because the container
instance of the AddressesController
is null. The container is setup when you create a controller by other container. This is abstracted for you, if you use:
this.controllerFor('addresses')
instead of
App.AddressesController.create ...
So this work http://jsfiddle.net/marciojunior/GRaa5/
1) Pass itemController in the #each handler
Like I said before, itemController
from controller, and each helper, don't have relation. So you can mix him.
{{#each addresses itemController="address"}}
<li>{{line1}}, {{city}}</li>
{{/each}}
See this in action http://jsfiddle.net/marciojunior/spA9Q/
2) Add a container property to the ArrayController
This work because of the my previous explanation,
because the
container
instance of theAddressesController
is null
Finishing the @colymba example works, because before of the setupController:
setupController: function(controller, model){
controller.set('content', model);
}
ember provide a controller in that hook using the controllerFor
, then the container is present in the generated controller too.
Looking at the fiddle, it wasn't really the best way to go at it. Giving the code a quick clean up, I got this fiddle working: http://jsfiddle.net/colymba/kV8LM/
What I did is, add a route AddressesRoute
, which IndexRoute
redirects to:
App.Router.map(function() {
this.route("addresses");
});
App.IndexRoute = Ember.Route.extend({
redirect: function() {
this.transitionTo('addresses');
}
});
App.AddressesRoute = Ember.Route.extend({
model: function(params){
return [
App.Address.create({'line1': '700 Hansen Wy'}),
App.Address.create({'line1': '900 Hansen Wy'})
];
},
setupController: function(controller, model){
controller.set('content', model);
}
});
Using naming conventions helps, with the AddressesRoute
, Ember instantiate automatically the Controller and the View.
Changing the View accordingly, its name to addresses
and updating the {{#each}}
to loop over content
:
<script type="text/x-handlebars" data-template-name="addresses">
<h2>Index Content:</h2>
<p>
Length: {{content.length}}
</p>
<ul>
{{#each addresses in controller}}
<li>{{line1}}, {{city}}</li>
{{/each}}
</ul>
</script>
The {{#each}}
loop could also just be written {{#each controller}}
since it will look for content
or model
by default. In both cases, controller
tells the View that it should access its Controller to find the content for the {{#each}}
loop, otherwise the itemController
isn't used (since it doesn't exist on the View). (which relates to what @intuitivepixel said)
The model and controller are the same as you had:
App.Address = Ember.Object.extend();
App.AddressController = Ember.ObjectController.extend({
city: function(){
return "San Francisco";
}.property()
});
App.AddressesController = Ember.ArrayController.extend({
itemController: 'address'
});
App.IndexController = Ember.ObjectController.extend();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With