Ember控制器计算属性(类型为Object)更新不起作用

时间:2014-11-07 02:22:31

标签: javascript ember.js

我正在尝试将排序属性(sortPropertiessortAscending)与数据列表中的过滤器结合起来。

我有一个ArrayController和两个动作,一个用于排序,一个用于过滤器。筛选操作在filters对象上设置属性,但依赖于filters的属性不会重新计算。

相关控制器代码:

App.PostsController = Ember.ArrayController.extend({
  filters: Ember.Object.create({}),
  filteredContent: function () {
    var ret = this.get('arrangedContent');
    Object.keys(this.filters).forEach(function (name) {
      ret = ret.filter(this.filters.get(name));
    }, this);
    return ret;
  // I expect this to cause `filteredContent` to depend on `filters` property
  }.property('arrangedContent', 'filters'),

  actions: {
    sort: function(property, isSorted) {
      this.set('sortProperties', [property]);
      if (isSorted) {
        this.toggleProperty('sortAscending');
      } else {
        this.set('sortAscending', true); 
      }
    },
    filter: function (property, value) {
      var filters = this.get('filters');
      switch (property) {
        case 'id':
          // I expect that call to `set` would trigger `filteredContent` property update
          filters.get('id') || filters.set('id', function (post) {
            return post.get('id') < value;
          });
          break;
        case 'title':
          filters.get('title') || filters.set('title', function (post) {
            return post.get('title').indexOf(value) !== -1;
          });
          break;
      }

    }
  }
});

所以,我的问题是为什么filters.set()不会导致filteredContent函数运行?

所有代码都在这里 - http://jsbin.com/silun/7/edit?html,js,output

1 个答案:

答案 0 :(得分:1)

您正在更新filters对象的属性,因此您需要观察正在更改的特定对象属性。

您可以通过明确列出要依赖的属性来执行此操作:

filteredContent: function () {
  //...
}.property('arrangedContent', 'filters.id', 'filters.title'),

或使用名为property brace expansion的简写符号。

filteredContent: function () {
  //...
}.property('arrangedContent', 'filters.{id,title}'),

更新了JSBin:http://jsbin.com/nuyegowede/1/edit

更新

新的JSBin,filters为数组:http://jsbin.com/yayihazoza/1/edit

如果您想要无限制的过滤器属性而不更新计算属性,则可以使用configure filters作为数组而不是对象。这使您可以使用Ember的数组观察器功能(@each在阵列更改时自动更新过滤。

filters现在是一个过滤器对象数组,采用以下形式:

   {
     name: 'name-of-filter',
     filter: function(){
       // implementation of filter here
     }
   }

更新filter将过滤器对象推送到filters数组:

filter: function (property, value) {
      var filters = this.get('filters');
      console.log("filter", property, value);

      switch (property) {
        case 'id':
          if (filters.findBy('name', 'id') === undefined) {
            filters.pushObject({
              name: 'id',
              filter: function (post) {
                return (post.get('id') < value);
              }
            });
          }
          break;
        case 'title':
          if (filters.findBy('name', 'title') === undefined) {
            filters.pushObject({
              name: 'title',
              filter: function (post) {
                return post.get('title').indexOf(value) !== -1;
              }
            });
          }
          break;
      }

    }

更新computed属性以使用新的过滤器对象,并监听对数组中每个项目的更改

  filteredContent: function () {
    var ret = this.get('arrangedContent');
    var filters = this.get('filters');

    filters.forEach(function (filterObj) {
      ret = ret.filter(filterObj.filter);
    }, this);
    return ret;
  }.property('arrangedContent', 'filters.@each'), // <-- notice the new @each