Ember: Using itemController in ArrayController does not work (TypeError: Unable to call the 'lookup' method from null)

Following the Ember examples for setting the itemController element in my definition, the ArrayController raises a lock 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 I found to fix this is ...

1) Pass the itemController in the #each ( jsfiddle ) handler:

 {{#each addresses itemController="address"}} <li>{{line1}}, {{city}}</li> {{/each}} 

... or...

2) Add container property to ArrayController ( jsfiddle ):

 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 seem to be hacked and very wrong. What am I doing wrong with setting itemController in ArrayController itself?

+4
source share
4 answers

itemController from the controller and each view are not related. Although this does the same thing: wraps the object in the specified controller.

Your first implementation throws a Cannot call method 'lookup' of null , because the container AddressesController instance is null. The container is configured when the controller is created by another container. This is abstracted for you if you use:

 this.controllerFor('addresses') 

instead

  App.AddressesController.create ... 

So this work is http://jsfiddle.net/marciojunior/GRaa5/

1) Skip the Controller element in the #each handler

As I said, itemController from the controller and each assistant are not related. Therefore, you can mix it.

 {{#each addresses itemController="address"}} <li>{{line1}}, {{city}}</li> {{/each}} 

See this in action http://jsfiddle.net/marciojunior/spA9Q/

2) Add container property to ArrayController

This work is due to my previous explanation,

since the container AddressesController instance is null

Shutting down the @colymba example, because before setting up the Controller:

 setupController: function(controller, model){ controller.set('content', model); } 

ember provides the controller in this hook using controllerFor , then the container is also present in the generated controller.

+6
source

Looking at the violin, in fact, this was not the best way. Giving the code a quick clean, I got this fiddle: http://jsfiddle.net/colymba/kV8LM/

What I did was add the AddressesRoute route, 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 AddressesRoute , Ember automatically starts Controller and View.

Respectively change the view, its name to addresses and update {{#each}} to the end of the 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 loop {{#each}} can also be simply written {{#each controller}} , because it will look for the default content or model . In both cases, the controller tells View that it must access its controller in order to find the contents for the {{#each}} itemController , otherwise the itemController will not be used (since it does not exist in the view). (which relates to what @intuitivepixel said)

The model and controller are the same as yours:

 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(); 
+2
source

first of all, this code seems a little strange to me, but in any case, the fact is that you are creating a new instance of "AddressesController" in the router, you need to change it to something like this:

 App.IndexRoute = Ember.Route.extend({ setupController: function(indexController) { this.controllerFor('addresses').set('content', [App.Address.create({'line1': '700 Hansen Wy'}), App.Address.create({'line1': '900 Hansen Wy'})]); indexController.set('addresses', this.controllerFor('addresses')); } }) 
+1
source

I initially had the same error when trying to instantiate an itemController inside an ArrayController . Although, my error was the result of clobbering the init method:

 App.UsersController = Ember.ArrayController.extend({ init: function() { console.log('i am USERS CONTROLLER'); }, itemController: 'user', }); 

which I fixed by restoring the default behavior for the init method:

 App.UsersController = Ember.ArrayController.extend({ init: function() { this._super(); console.log('i am USERS CONTROLLER'); }, itemController: 'user', }); 
0
source

Source: https://habr.com/ru/post/1496651/


All Articles