9

Emberモデルのコレクションを複数のプロパティで並べ替える必要があり、同じ方向/順序で並べ替える必要はありません。つまり、プロパティa昇順で並べ替え、プロパティb降順で並べ替える必要があります。これを達成する方法はありますか?

アップデート

sortAscendingプロパティを配列に設定しようとしましたが、機能しません。ソースを調べたところ、この機能は(まだ)そのままではサポートされていないようです。

4

3 に答える 3

15

ArrayControllerの場合:

sortProperties: ["propA:asc", "propB:desc"]
sortedModel: Ember.computed.sort("model", "sortProperties");

次にsortedModel、テンプレートの#eachハンドラーで参照します。

于 2014-05-11T18:27:31.607 に答える
5

複数の順序(方向)で並べ替えることができるミックスインを作成することにしました。SortableMixinこれにより、可能な限り下位互換性を確保するように試みが拡張されます。実際には通常通り使用できますSortableMixin。追加されるのは、昇順でソートする必要があるsortAscendingPropertiesソートプロパティ名(配列のメンバー)の配列であるプロパティです。sortPropertyプロパティが含まれている場合はsortAscendingProperties昇順で並べ替えられ、含まれていない場合sortAscendingはデフォルトの一種である、に従って並べ替えられます。最高の名前ではないと思いますが、私
はミックスインと呼びました。MultiSortableMixin

(function() {

    var get = Ember.get, set = Ember.set, forEach = Ember.EnumerableUtils.forEach;

    /**
     * extends the SortableMixin by allowing sorting by multiple orders.
     *
     * sortProperties - array of strings
     * sortAscending - default sort order
     * sortAscendingProperties - properties which are listed here will be sorted in ascending order, those which are not listed - will be sorted according to sortAscending
     */
    Ember.MultiSortableMixin = Ember.Mixin.create(Ember.SortableMixin, {
        /**
         Specifies the arrangedContent's sort direction

         @property {Array} sortAscendingProperties
         */
        sortAscendingProperties: null,
        orderBy: function(item1, item2) {
            var result = 0,
                    sortProperties = get(this, 'sortProperties'),
                    sortAscending = get(this, 'sortAscending'),
                    sortAscendingProperties = get(this, 'sortAscendingProperties');

            Ember.assert("you need to define `sortProperties`", !!sortProperties);

            forEach(sortProperties, function(propertyName) {
                if (result === 0) {
                    result = Ember.compare(get(item1, propertyName), get(item2, propertyName));
                    //use default sortAscending if propertyName is not listed in sortAscendingProperties
                    var sa = (sortAscendingProperties && sortAscendingProperties.indexOf(propertyName) > -1) || sortAscending;
                    if ((result !== 0) && !sa) {
                        result = (-1) * result;
                    }
                }
            });

            return result;
        },
        //overrided to add more watched props. TODO - the contents of this method is the same as parent's - find the way to just add watched stuff
        arrangedContent: Ember.computed('content', 'sortProperties.@each', 'sortAscendingProperties.@each', 'sortAscending', function(key, value) {
            var content = get(this, 'content'),
                    isSorted = get(this, 'isSorted'),
                    sortProperties = get(this, 'sortProperties'),
                    self = this;

            if (content && isSorted) {
                content = content.slice();
                content.sort(function(item1, item2) {
                    return self.orderBy(item1, item2);
                });
                forEach(content, function(item) {
                    forEach(sortProperties, function(sortProperty) {
                        Ember.addObserver(item, sortProperty, this, 'contentItemSortPropertyDidChange');
                    }, this);
                }, this);
                return Ember.A(content);
            }

            return content;
        }),
    // unneeded in this mixin, overrided to disable functionality from SortableMixin. TODO - find a way to just remove it
        sortAscendingDidChange: Ember.observer(function() {
            //empty
        }, 'sortAscending')
    });

})();

使用例:

App.ThingsController = Ember.ArrayController.extend(Ember.MultiSortableMixin, {
    sortProperties: ['prop1', 'prop2', 'prop3'], 
    sortAscending: false,
    sortAscendingProperties: ['prop2', 'prop3'], 
    //your stuff
});

この例では、のコンテンツはprop1(降順)、次にprop2prop3(両方とも昇順)ThingsControllerで並べ替えられます。

于 2013-03-04T12:37:28.920 に答える
0

これは、Emberのすぐに使える機能ではありません。しかし、SortableMixinのコードを見ると、Ember.compareを使用して2つのエンティティを比較していることがわかります。

orderBy: function(item1, item2) {
    var result = 0,
        sortProperties = get(this, 'sortProperties'),
        sortAscending = get(this, 'sortAscending');

    Ember.assert("you need to define `sortProperties`", !!sortProperties);

    forEach(sortProperties, function(propertyName) {
      if (result === 0) {
        result = Ember.compare(get(item1, propertyName), get(item2, propertyName));
        if ((result !== 0) && !sortAscending) {
          result = (-1) * result;
        }
      }
    });

    return result;
  },

また、Ember.compareには、 ComparableMixinのチェックが含まれています。

var Comparable = Ember.Comparable;
  if (Comparable) {
    if (type1==='instance' && Comparable.detect(v.constructor)) {
      return v.constructor.compare(v, w);
    }

    if (type2 === 'instance' && Comparable.detect(w.constructor)) {
      return 1-w.constructor.compare(w, v);
    }
  }

したがって、私の提案する解決策は次のとおりです。

1-すべてのsortingPropertiesのラッパーオブジェクトを含むフィールドをモデルに追加します(例: "combinedAandB")

App.YourModel = Ember.Object.extend({
a : null,
b : null,
combinedAandB : function(){
  // the following Object should implement SortableMixin
  var comparator = App.AandBComparator.create(this.get("a"), this.get("b"));
  return comparator;
}.property("a","b")

2 -ComparatorModel(App.AandBComparator)は、ComparableMixinを実装する必要があります。この比較方法の内部では、目的の並べ替え動作(propaの昇順とpropbの降順)を尊重します。

3-これで、ArrayControllerをインスタンス化し、結合されたプロパティに基づいて並べ替えることができます。

var yourModelController = //whereever you may get that one from
yourModelController.set("sortProperties", "combinedAandB");

注:これは、要件を読んだときに私が得た自発的なアイデアです。私はまだこれを実装していません。したがって、これはおそらく完璧ではありません:-)

于 2013-02-21T10:53:20.283 に答える