【问题标题】:Sort content of ArrayController对 ArrayController 的内容进行排序
【发布时间】:2012-05-16 22:59:10
【问题描述】:

我有一个 Ember.ArrayController 包含未排序的内容。

我想知道是否可以在不使用新属性的情况下对 ArrayController 的内容进行排序。

我当然可以创建一个新属性:

App.MyArrayController = Em.ArrayController.extend({
  mySortMethod: function(obj1, obj2) {
    // some code here
  },
  updateSortedContent: function() {
    var content = this.get('content');
    if (content) {
      var sortedContent = content.copy();
      sortedContent.sort(this.mySortMethod);
      this.set('sortedContent', sortedContent);
    }
  }.observes('content')
});

但我希望有更好的方法,不重复内容。

【问题讨论】:

标签: arrays sorting ember.js


【解决方案1】:

更新

Ember 的最新版本实际上内置了排序功能。ArrayController 现在包括Ember.SortableMixin,如果您指定sortProperties(数组)和可选的sortAscending(布尔值),它将参与。

注意:使用新的 SortableMixin,您仍然需要参考 arrangedContent 来获取排序后的版本。模型本身将保持不变。 (感谢 Jonathan Tran)

App.userController = Ember.ArrayController.create({
  content: [],
  sortProperties: ['age'],
  sortAscending: false
})

原始答案

正确的方法是使用 ArrayProxy 的arrangedContent 属性。此属性旨在被覆盖以提供内容数组的排序或过滤版本。

App.userController = Ember.ArrayController.create({
  content: [],
  sort: "desc",
  arrangedContent: Ember.computed("content", function() {
    var content, sortedContent;
    content = this.get("content");
    if (content) {
      if (this.get("sort") === "desc") {
        this.set("sort", "asc");
        sortedContent = content.sort(function(a, b) {
          return a.get("age") - b.get("age");
        });
      } else {
        this.set("sort", "desc");
        sortedContent = content.sort(function(a, b) {
          return b.get("age") - a.get("age");
        });
      }
      return sortedContent;
    } else {
      return null;
    }
  }).cacheable()
});

【讨论】:

  • 定义一个 sortProperty 默认排序。是否可以仅在注册用户请求时(通过下拉菜单或其他方式)更改以适应排序?
  • 您将默认排序属性和升序定义为您的内容的“正常”。然后你做一个小动作,通过按钮或下拉菜单改变这两个属性,魔法就会发生。我在控制器上有一个 reSort 方法,它将排序属性(我只使用一个)设置为按钮作为参数发送的内容。如果该属性与已设置的属性相同,则将其解释为将顺序反转为降序的指示。 gist.github.com/3744939
  • 注意:使用新的SortableMixin,你仍然需要参考arrangedContent来获得排序后的版本。起初这让我绊倒了。
  • @JonathanTran 你能解释一下,你的意思是'你仍然需要参考排列内容'吗?我需要在哪里推荐它?
  • @SatA 在您的模板中,或任何您需要排序版本的地方,不要使用content。那是原始模型数组,不会排序。
【解决方案2】:

您必须在 Ember 中手动对数组进行排序,包括任何数组控制器的内容。您始终可以将 content 替换为已排序的数组,而不是保留两个数组。

更新

这是我认为您正在寻找的示例:http://jsfiddle.net/ud3323/yjs8D/

更新 #2

更新了此示例以使用新的视图上下文更改。 https://gist.github.com/2494968

车把

<script type="text/x-handlebars" >
Will Display and Sort by Age (after 2 sec)<br/><br/>

{{#each App.userController}}
    {{#view App.RecordView}}
        {{name}} - {{age}}
    {{/view}}
{{/each}}
</script>

JavaScript

App = Ember.Application.create({
    ready: function() {
        Ember.run.later(this, function() {
            Ember.run.later(this, function() {
                App.get('userController').set('content', [
                   Ember.Object.create({ name:"Jeff", age:24 }),
                   Ember.Object.create({ name:"Sue", age:32 }),
                   Ember.Object.create({ name:"Jim", age:12 })
               ]);
      }, 2000);
        Ember.run.later(this, function() {
            // Make the controller's content sort again in reverse this time
            App.userController.notifyPropertyChange('content');
        }, 4000);
    }
});

App.userController = Ember.ArrayController.create({
    content: [],

    contentDidChange: Ember.observer(function(userCtr, prop) {
        if(!Ember.empty(this.get('content'))) {
            console.log('about to begin sort');
            this.sortContent();
        }

        this._super();
    }, 'content'),

    sort:"desc",

    sortContent:function() {
        var content = this.get("content"), sortedContent;

        if (this.get("sort") == "desc") {
            this.set("sort", "asc");
            sortedContent = content.sort( function(a,b){
                return a.get("age") - b.get("age");
            });
        } else {
            this.set("sort","desc");
            sortedContent = content.sort( function(a,b){
                return b.get("age") - a.get("age");
            });
        }

        this.set("content",sortedContent);
    }
});

App.RecordView = Ember.View.extend({});

【讨论】:

  • 是的,但是我不知道在哪里替换它,因为如果'内容'观察者替换内容,回调将被再次发送,一次又一次,......
  • 它有效!我已经尝试过了,但是在对内容进行排序之前我打电话给this._super(),所以它不起作用。无论如何,谢谢你
  • 是的,这是一个无证的小 Ember 陷阱。您必须在最后调用_super(),因为Ember.ArrayProxy 中定义的contentDidChange 将在content 属性上添加Ember.ArrayProxy 需要的观察者。所以诀窍是你想在添加这些观察者之前更改content,否则你会遇到无限循环问题,听起来你已经经历过;)
猜你喜欢
  • 1970-01-01
  • 2016-05-17
  • 2011-01-24
  • 1970-01-01
  • 1970-01-01
  • 2013-06-07
  • 2014-07-28
  • 2011-03-13
  • 2012-09-10
相关资源
最近更新 更多