我们假设数据表的单元格呈现如下:
columnDefs: [
{
targets: 0,
type: 'percent',
render: function (data, type, full, meta) {
let html = '<span class="sort-value">' + data + '</span>';
html += "(<span class='sort-percent'>" + full.percent + "</span>%)";
return html;
}
}
}
此时,通过点击标题,我想使用带有渲染的HTML元素的
sort-value
类名的值,以ASC方向进行第一次排序。
第二个排序相同,但 DESC 方向按带有
sort-value
类名的值。
对于第三种排序,我想按具有
sort-percent
类名的值在 ASC 方向上排序。
对于第四种排序,我想按具有
sort-percent
类名的值在 DESC 方向上排序。
然后我想一遍又一遍地重复这个序列。
那么,第四次排序的时候,应该是这样的:
因此我为此创建了逻辑并引入了以下两个变量:
var previously_sorted_index = 0;
var sort_state = 0; // 0: default, 1: sort-value ASC, 2: sort-value DESC, 3: percentage ASC, 4: percentage DESC
每当单击标题并执行排序时,
sort_state
值就会更新,这效果很好。为了更好地理解,这是我的代码:
$('#table thead th').on('click', function() {
var colIdx = $(this).index();
if(previously_sorted_index == colIdx) {
sort_state ++;
if(sort_state == 5)
sort_state = 1;
} else {
previously_sorted_index = colIdx;
sort_state = 1;
}
});
问题是我使用数据表的排序插件自定义了排序,但它没有按预期工作。 它只是使用单元格的 HTML 元素执行字符串排序。
这是我的自定义代码
$.extend($.fn.dataTableExt.oSort, {
"percent-pre": function (a) {
let div = document.createElement('div');
div.innerHTML = a;
let sort_val_el = div.getElementsByClassName("sort-value");
let sort_percent_el = div.getElementsByClassName("sort-percent");
let sort_val = parseFloat(sort_val_el.length > 0 ? sort_val_el[0].innerHTML : 0);
let percentage_val = parseFloat(sort_percent_el.length > 0 ? sort_percent_el[0].innerHTML : 0);
return [sort_val, percentage_val];
},
"percent-asc": function (a, b) {
if(sort_state == 1) {
return a[0] > b[0] ? 1 : -1;
} else if(sort_state == 3) { // percentage ASC/DESC
return a[1] > b[1] ? 1 : -1;
}
return 0;
},
"percent-desc": function (a, b) {
if (sort_state == 2) { // sort-value ASC/DESC
return b[0] > a[0] ? 1 : -1;
} else if(sort_state == 4) { // percentage ASC/DESC
return b[1] > a[1] ? 1: -1;
}
return 0;
}
});
我调试了一下,
sort_state
的值完全按照预期更新了。
当
percent-pre
返回单个值而不是像我的代码中那样的数组时(例如,仅 percent
值),排序将完全基于该值进行。
如果返回一个数组并根据
sort_state
值对数组中任意元素的值进行排序是行不通的。
我的代码有问题吗?
谢谢!
正如@andrewJames提到的,Datatable v1.x不提供带有自定义排序插件的
-asc
、-desc
选项。
所以我更新了Datatable到v2.0,它提供了以上两个选项,但是有一种不进行排序的状态(状态0 - 默认顺序),所以连续按排序就会按ASC排序, DESC,然后是Default(未排序)状态。然后,在第4次排序时,又变成ASC,所以这样的话,一个周期就是6次。 我无法使用v2.0的排序功能,因为我希望一个周期是4次。
可能还有删除默认状态的功能。在默认情况下(未排序状态),我们必须强制绘制排序箭头方向才能有 4 个排序周期...
我用 v1.x 解决了这个问题,如下:
数据表列定义中有
orderDataType:
选项。
columnDefs: [
{
targets: 1,
type: 'percent',
render: function (data, type, full, meta) {
let html = '<span class="sort-value">' + data + '</span>';
html += "(<span class='sort-percent'>" + full.percent + "</span>%)");
return html;
},
orderDataType: 'custom-sort'
},
....
]
点击表头时,数值更新为4次循环。
var previously_sorted_index = 0;
var sort_state = 0; // 0: default, 1: sort-value ASC, 2: sort-value DESC, 3: percentage ASC, 4: percentage DESC
$('#table thead th').on('click', function() {
var colIdx = $(this).index();
if(previously_sorted_index == colIdx) {
sort_state ++;
if(sort_state == 5)
sort_state = 0;
} else {
previously_sorted_index = colIdx;
sort_state = 1;
}
});
使用订单插件自定义排序功能。
$.fn.dataTable.ext.order['custom-sort'] = function(settings, colIdx) {
return this.api().column(colIdx, {order: 'index'}).nodes().map(function(td, i) {
let sortValue = $(td).find('.sort-value').text();
let sortPercent = $(td).find('.sort-percent').text();
if (sort_state % 4 < 2) {
// First two sorts use sort-value
return parseFloat(sortValue) || 0;
} else {
// Next two sorts use sort-percent
return parseFloat(sortPercent) || 0;
}
});
};
这里重要的是
type: 'percent'
如果删除此选项,自定义订单功能将无法使用。