我需要按多个属性对 Ember 模型的集合进行排序,而不需要以相同的方向/顺序。即我需要按属性a升序排序,按属性b降序排序。有没有办法做到这一点?
更新
我尝试将sortAscending
属性设置为数组,但它不起作用。在查看源代码后,似乎不支持开箱即用的此功能(尚)。
我需要按多个属性对 Ember 模型的集合进行排序,而不需要以相同的方向/顺序。即我需要按属性a升序排序,按属性b降序排序。有没有办法做到这一点?
我尝试将sortAscending
属性设置为数组,但它不起作用。在查看源代码后,似乎不支持开箱即用的此功能(尚)。
在您的 ArrayController 中:
sortProperties: ["propA:asc", "propB:desc"]
sortedModel: Ember.computed.sort("model", "sortProperties");
然后sortedModel
在模板的#each
处理程序中引用。
我决定创建一个允许在多个订单(方向)中排序的mixin 。它将SortableMixin
尝试扩展到尽可能多的向后兼容。实际上它可以用作常规SortableMixin
。它添加的是sortAscendingProperties
属性,它是排序属性名称(数组的成员sortProperty
)的数组,应该按升序排序。如果属性在sortAscendingProperties
,则按升序排序,否则将按 排序sortAscending
,这是一种默认值。尽管我认为这不是最好的名称,但我
将 mixin 称为。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
});
在此示例中,内容ThingsController
将按prop1排序- 降序排列,然后按prop2和prop3排序 - 均按升序排列。
这不是 Ember 的开箱即用功能。但是查看SortableMixin 的代码可以看到它使用 Ember.compare 来比较两个实体:
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包含对Comparable Mixin的检查:
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 - 向您的模型添加一个附加字段,其中包含所有排序属性的包装对象,例如“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) 应该实现 Comparable Mixin。在此比较方法中,尊重您想要的排序行为(prop a 升序和 prop b 降序)。
3 - 现在您可以实例化一个 ArrayController 并根据您的组合属性对其进行排序:
var yourModelController = //whereever you may get that one from
yourModelController.set("sortProperties", "combinedAandB");
注意:这只是我在阅读您的要求时的一个自发想法。我还没有实现这个。所以这可能并不完美:-)