Ember计算属性未更新

时间:2014-02-04 20:18:13

标签: javascript ember.js

我不太清楚为什么我的计算属性没有返回更新的值。

我有一个用户可以点击的选项列表,该操作会更新控制器的属性,即Ember对象。我有一个循环遍历该对象的计算属性,查找具有该Ember对象属性的非空值的键,如果找到一个,则返回false,否则为true。

以下是这些内容:

App.SimpleSearch = Ember.Object.extend({
    init: function() {
        this._super();

        this.selectedOptions = Ember.Object.create({
            "Application" : null,
            "Installation" : null,
            "Certification" : null,
            "Recessed Mount" : null,
            "Width" : null,
            "Height" : null,
            "Heating" : null,
            "Power" : null
        });
    },

    selectedOptions: {},

    numOfOptions: 0,

    allOptionsSelected: function() {
        var selectedOptions = this.get('selectedOptions');
        for (var option in selectedOptions) {
            console.log(selectedOptions.hasOwnProperty(option));
            console.log(selectedOptions[option] === null);
            if (selectedOptions.hasOwnProperty(option)
                && selectedOptions[option] === null) return false;
        }
        return true;
    }.property('selectedOptions')
});


App.SimpleSearchRoute = Ember.Route.extend({
    model: function() {
        return App.SimpleSearch.create({
            'SimpleSearchOptions': App.SimpleSearchOptions,
            'numOfOptions': App.SimpleSearchOptions.length
        });
    },
    setupController: function(controller, model) {
        controller.set('model', model);
    }
});


App.SimpleSearchController = Ember.ObjectController.extend({
    getProductsResult: function() {
        var productsFromQuery;
        return productsFromQuery;
    },

    setSelection: function (option, selectionValue) {
        this.get('selectedOptions').set(option, selectionValue);
        this.notifyPropertyChange('allOptionsSelected');
    },

    actions: {
        registerSelection: function(option) {
            console.log('registering selection');
            console.log(this.get('allOptionsSelected'));
            console.log(this.get('selectedOptions'));
            this.setSelection(option.qname, option.value);
        },

控制器中的操作registerSelection正好点火,但我只看到console.log模型中的SimpleSearch一次。一旦第一次计算属性,之后就不会注意了,这意味着只要调用此属性,计算属性就不会观察selectedOptions的变化:

setSelection: function (option, selectionValue) {
    this.get('selectedOptions').set(option, selectionValue);
    this.notifyPropertyChange('allOptionsSelected');
},

编辑:

我实际上解决了我的问题而没有改变任何事情。

我改变了以下一行:

this.notifyPropertyChange('allOptionsSelected');

为:

this.get('model').notifyPropertyChange('selectedOptions');
需要在模型(或具有特定属性的观察者的Ember对象)的上下文中调用

notifyPropertyChange,并且作为参数发送的字符串是已更新的属性的名称。 / p>

在我做出改变后,它按预期工作。

2 个答案:

答案 0 :(得分:9)

Ember不会观察对象的任何变化,它会观察到一个属性。

这对你有什么影响?那么在这个方法中你正在看selectedOptions,但是该对象本身仍然是同一个对象,你可能正在改变它的属性,而不是对象本身。然后你告诉Ember在allOptionsSelected已经改变的控制器的范围内,所以它重新计算它,但它不会重新计算它,因为它不是脏的,它只是改变了。您真的想说selectedOptions已更改为让allOptionsSelected重新计算其值。不幸的是,你在控制器的范围内这样做,所以告诉控制器属性已经改变并不重要。

allOptionsSelected: function() {
  var selectedOptions = this.get('selectedOptions');
  for (var option in selectedOptions) {
     console.log(selectedOptions.hasOwnProperty(option));
     console.log(selectedOptions[option] === null);
     if (selectedOptions.hasOwnProperty(option)
        && selectedOptions[option] === null) return false;
     }
  return true;
}.property('selectedOptions')

这是一个虚拟示例,显示了实际更新的原因。

http://emberjs.jsbin.com/iCoRUqoB/1/edit

老实说,既然你没有看特定的属性,我可能会做一个数组,或者在对象上创建一个处理添加/删除/修改属性的方法,这样你就可以从它的范围内触发一个属性更改来更新所有父元素有变化的听众。

答案 1 :(得分:1)

Ember计算属性相关键可以是

  1. 属性键。示例中的:'jobTitle'
  2. 计算属性键。示例中的:'companyName'
  3. 对象的属性键。示例中的: 'salesAccount.name和salesAccount.website'
  4. 从Ember.model定义中提取的示例:

    ...
       jobTitle : DS.attr('string'),
       salesAccount: belongsTo('salesAccount'),
    
       companyName: Ember.computed('jobTitle', 'salesAccount.name', {
        get: function () {
          return this.get('salesAccount.name');
        }
      }),
    
      companyWebsite: Ember.computed('salesAccount.website', 'companyName',  {
        get: function () {
          return this.get('salesAccount.website');
        }
      })
    ...