Javascript 余烬控制器计算属性(对象类型)更新不起作用

Javascript 余烬控制器计算属性(对象类型)更新不起作用,javascript,ember.js,Javascript,Ember.js,我正在尝试将排序属性(sortProperties和sortAscending)与数据列表上的筛选器相结合 我有一个ArrayController和两个操作,一个用于排序,一个用于过滤器。过滤器操作设置过滤器对象的属性,但不重新计算依赖于过滤器的属性 相关控制器代码: App.PostsController = Ember.ArrayController.extend({ filters: Ember.Object.create({}), filteredContent: functio

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

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

相关控制器代码:

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

    }
  }
});
App.PostsController=Ember.ArrayController.extend({
过滤器:Ember.Object.create({}),
filteredContent:函数(){
var ret=this.get('arrangedContent');
Object.keys(this.filters).forEach(函数(名称){
ret=ret.filter(this.filters.get(name));
},这个);
返回ret;
//我希望这会导致'filteredContent'依赖于'filters'属性
}.property('arrangedContent','filters'),
行动:{
排序:函数(属性,isSorted){
this.set('sortProperties',[property]);
如果(已排序){
此.toggleProperty('sortAscending');
}否则{
此.set('sortAscending',true);
}
},
过滤器:函数(属性、值){
var filters=this.get('filters');
交换机(属性){
案件编号:
//我希望调用'set'会触发'filteredContent'属性更新
filters.get('id')| | filters.set('id',函数(post){
return post.get('id')<值;
});
打破
“标题”一案:
filters.get('title')| | filters.set('title',函数(post){
return post.get('title').indexOf(value)!=-1;
});
打破
}
}
}
});
所以,我的问题是为什么
filters.set()
不会导致
filteredContent
函数运行


所有代码都在这里–

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

可以通过显式列出要依赖的属性来实现这一点:

filteredContent: function () {
  //...
}.property('arrangedContent', 'filters.id', 'filters.title'),
或者使用一种叫做的速记符号

更新的JSBin:

更新 带有
过滤器的新JSBin作为数组:

如果希望在不更新计算属性的情况下不受限制地使用过滤器属性,则可以将configure
filters
用作数组而不是对象。这使您可以使用Ember的阵列观察者功能(在阵列更改时自动更新过滤)

过滤器
现在是一个过滤器对象数组,其形式如下:

   {
     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;
      }
      
    }
过滤器:函数(属性、值){
var filters=this.get('filters');
日志(“过滤器”、属性、值);
交换机(属性){
案件编号:
if(filters.findBy('name','id')==未定义){
pushObject过滤器({
名称:“id”,
过滤器:功能(post){
返回(post.get('id')<值);
}
});
}
打破
“标题”一案:
if(filters.findBy('name','title')==未定义){
pushObject过滤器({
姓名:'头衔',
过滤器:功能(post){
return post.get('title').indexOf(value)!=-1;
}
});
}
打破
}
}
更新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
filteredContent:function(){
var ret=this.get('arrangedContent');
var filters=this.get('filters');
filters.forEach(函数(filterObj){
ret=ret.filter(filterbj.filter);
},这个);
返回ret;

}.property('arrangedContent','filters.@each'),//非常感谢您的回答!如果我想查看一个无限的属性列表(所有属性),该怎么办?除非您编写自己的可观察对象类,否则无法在不明确声明或自己设置观察者的情况下观察每个属性。@gryzzly您可以将定义过滤器的方式更改为ember可以自动观察的方式,例如将单个过滤器对象放入数组中,然后观察。@c4p I tried与array完全相同,不起作用:(这是基于array的版本嘿,太酷了!我认为
”过滤器。[]“
实际上就足够了
@each
监视属性,如果属性在从数组中添加/删除时重新计算,这就足够了。@torazaburo不确定我是否理解您的问题–当
过滤器
对象的属性发生更改(添加、更新或删除)时,我希望
过滤器内容
重新加载@torazaburo噢,那当然更新了jsbin。但问题是filteredContent函数甚至没有运行。
  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