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

Ember controller computed property (of type Object) update doesnt work

本文关键字:类型 更新 不起作用 Object 控制器 计算 属性 Ember      更新时间:2023-09-26

我正在尝试将排序属性(sortPropertiessortAscending)与数据列表上的筛选器相结合。

我有一个ArrayController和两个操作,一个用于排序,另一个用于筛选。Filter操作设置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,输出

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

您可以通过明确列出要依赖的属性来做到这一点:

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

或者通过使用称为属性大括号展开的简写表示法。

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

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

更新

filters为数组的新JSBin: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;
      }
      
    }

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

  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