在Ember.js中,当ArrayController上的属性发生更改时,如何通知ArrayController的相应itemController

时间:2014-04-18 02:01:26

标签: ember.js ember-controllers

我有一个EmailsController(ArrayController),它存储所有电子邮件。我有一个EmailController(ObjectController),它有一个参数存储是否选择了实际的电子邮件。我正在尝试在电子邮件模板中实现一个按钮,用于选择或取消选择所有电子邮件。所以我需要通过EmailsController的动作通知EmailController并更改EmailController的isChecked参数。

我正在尝试使用itemController,needs和controllerBinding参数,但没有任何效果。

以下是控制器:

App.EmailsController = Ember.ArrayController.extend({
    needs: ["Email"],
    itemController: 'Email',
    checkAll: true,
    actions: {
        checkAllEmails: function() {
            this.toggleProperty("checkAll");
            console.log(this.get("checkAll"));
        } 
    }
});


App.EmailController = Ember.ObjectController.extend({
    needs: ["Emails"],
    controllerBinding: 'controllers.Emails',
    isChecked: true,
    checkAllChanged: function() {
        //this should execute, but currently it does not
        this.set("isChecked",this.get('controller.checkAll'));
    }.property("controller")
});

这是相应的jsFiddle:http://jsfiddle.net/JqZK2/4/ 目标是通过Check All按钮切换复选框的选择。

谢谢!

2 个答案:

答案 0 :(得分:4)

你混合了几种不同的机制,并使用了一些错误的约定。虽然找到这些东西并不容易,但不要担心。

引用控制器

即使使用大写格式创建控制器,也会以小写格式存储,needs属性应为:

needs: ['emails'],

然后通过controllers属性访问其他控制器:

this.get('controllers.emails.checkAll')

计算属性

计算属性可以用作变量的getter / setter,也可以用作别名其他属性的方法。例如,如果您希望电子邮件控制器上的isChecked属性直接链接到电子邮件控制器的checkAll属性的值,则可以执行以下操作:

isChecked: function() {
  return this.get('controllers.emails.checkAll');
}.property('controllers.emails.checkAll')

虽然计算属性可以做得更多,但这个基本形式实际上只是一个计算别名,并且有一个实用程序函数可以使它更容易:

isChecked: Ember.computed.alias('controllers.emails.checkAll')

<强>观测量

observable基本上创建了一个方法,当它观察到的值发生变化时将被调用。计算后的别名会导致所有项目在您单击其中任何一个项目时取消选中或检查,因为它们的isChecked属性直接链接到父控制器的checkAll属性。不应将checkAllChanged方法标识为属性,而应使用observes

checkAllChanged: function() {
  this.set("isChecked",this.get('controllers.emails.checkAll'));
}.observes("controllers.emails.checkAll")

这样,当父控制器上的checkAll属性发生更改时,此方法会将所有项目的isChecked属性更新为其值,但如果取消选中或检查单个项目,则不会; t影响其他项目。

<强>绑定

绑定有点弃用;从阅读Ember github存储库中的问题我相信Ember的创建者似乎更喜欢使用计算属性,别名和observable。这并不是说他们不会工作,如果你的目标是避免每次输出controllers.emails,你可以像你一样创建一个(我不会称之为控制器,因为这真的很模糊):

emailsBinding: 'controllers.emails'

改为使用计算别名:

emails: Ember.computed.alias('controllers.emails')

然后您可以将观察者更改为:

checkAllChanged: function() {
  this.set("isChecked",this.get('emails.checkAll'));
}.observes("emails.checkAll")

以下是jsFiddle的更新版本:http://jsfiddle.net/tMuQn/

答案 1 :(得分:3)

您可以遍历电子邮件,从父控制器更改其属性。您无需指定needs或观察变量。

App.EmailsController = Ember.ArrayController.extend({
    itemController: 'email',
    actions: {
      checkAllEmails: function() {
        this.forEach(function(email) {
          email.toggleProperty("isChecked");
        });
      } 
    }
});

此外,您通常不会像使用isChecked = true那样设置初始值;我相信这会在原型上创建一个静态共享属性(而不是你想要的)。相反,在init上设置属性,或者从原始json数据传递它。

请参阅代码:http://jsfiddle.net/JqZK2/5/