Ember:在ArrayController中使用itemController不起作用(TypeError:无法调用null的方法'lookup')

时间:2013-08-12 18:54:04

标签: ember.js

按照Ember上的示例在我的ArrayController定义中设置itemController会导致阻塞错误消息:

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()
});

我找到解决此问题的唯一方法是......

1)在#each处理程序(jsfiddle)中传递itemController:

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

...或...

2)将一个容器属性添加到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'})
    ]
});

这两种解决方案都感觉很乱,而且非常错误。在ArrayController本身设置itemController我做错了什么?

4 个答案:

答案 0 :(得分:6)

来自控制器的itemController和每个视图没有关系。 虽然它做同样的事情:在指定的控制器中包装一个对象。

您的第一个实现会抛出Cannot call method 'lookup' of null,因为container的{​​{1}}实例为null。当您通过其他容器创建控制器时,将设置容器。如果你使用:

,这是抽象的
AddressesController

而不是

this.controllerFor('addresses')

所以这项工作http://jsfiddle.net/marciojunior/GRaa5/

  

1)在#each处理程序

中传递itemController

就像我之前说过的那样,来自控制器的 App.AddressesController.create ... 和每个助手都没有关系。所以你可以混合他。

itemController

在行动http://jsfiddle.net/marciojunior/spA9Q/

中查看此内容
  

2)将一个容器属性添加到ArrayController

这项工作是因为我之前的解释,

  

因为{{#each addresses itemController="address"}} <li>{{line1}}, {{city}}</li> {{/each}} 的{​​{1}}实例为空

完成@colymba示例有效,因为在setupController之前:

container

ember使用AddressesController在该钩子中提供控制器,然后容器也存在于生成的控制器中。

答案 1 :(得分:2)

看着小提琴,它并不是最好的方式。为了快速清理代码,我得到了这个小提琴:http://jsfiddle.net/colymba/kV8LM/

我所做的是,添加一条路由AddressesRouteIndexRoute重定向到:

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);
    }
});

使用命名约定有助于AddressesRoute,Ember自动实例化Controller和View。

相应地更改视图,将其名称更改为addresses并更新{{#each}}以循环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>

{{#each}}循环也可以只写{{#each controller}},因为它默认会查找contentmodel。在这两种情况下,controller告诉View它应该访问其控制器以查找{{#each}}循环的内容,否则itemController不会被使用(因为它没有&#39} ; t存在于View上)。 (这与@intuitivepixel所说的相关)

模型和控制器与您的相同:

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 :(得分:1)

首先,这段代码对我来说似乎有些奇怪,但无论如何,这里的事情是你在路由器中创建一个新的'AddressesController'实例,你需要将其更改为:

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'));
  }
})

答案 3 :(得分:0)

尝试在itemController内实例化ArrayController时,我最初遇到了同样的错误。虽然,我的错误是破坏init方法的结果:

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

我通过将默认行为恢复到init方法来修复:

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