【问题标题】:How to sort drop down list numerically in DataTables如何在 DataTables 中对下拉列表进行数字排序
【发布时间】:2015-09-10 09:07:47
【问题描述】:

我有这个代码。它所做的只是用 DataTables 显示 并将每一列的下拉选择过滤器放在底部。

var dataSet = [
  [1,"Airi Satou", "Accountant", "Tokyo", "5407", "2008/11/28", "$162,700"],
  [2,"Angelica Ramos", "Chief Executive Officer (CEO)", "London", "5797", "2009/10/09", "$1,200,000"],
  [10,"Gavin Joyce", "Developer", "Edinburgh", "8822", "2010/12/22", "$92,575"],
  [3,"Jennifer Chang", "Regional Director", "Singapore", "9239", "2010/11/14", "$357,650"],
  [5,"Brenden Wagner", "Software Engineer", "San Francisco", "1314", "2011/06/07", "$206,850"],
  [9,"Fiona Green", "Chief Operating Officer (COO)", "San Francisco", "2947", "2010/03/11", "$850,000"],
  [12,"Shou Itou", "Regional Marketing", "Tokyo", "8899", "2011/08/14", "$163,000"],
  [23,"Martena Mccray", "Post-Sales support", "Edinburgh", "8240", "2011/03/09", "$324,050"],
  [99,"Unity Butler", "Marketing Designer", "San Francisco", "5384", "2009/12/09", "$85,675"]
];

 $(document).ready(function() {

var columns = [
    {title: "ID"},
    {title: "Name"}, 
    {title: "Position"}, 
    {title: "Office"}, 
    {title: "Extn."}, 
    {title: "Start date"}, 
    {title: "Salary"}
];

// Footer construction
var $tfoot = $("#example tfoot tr");
for (var i = 0, len = columns.length; i < len ; i++){
    $tfoot.append("<th>");
}

$('#example').DataTable( {
    data: dataSet,
    columns: columns,
    initComplete: function (setting, json) {
        this.api().columns().every( function () {
            var column = this;
            var select = $('<select><option value=""></option></select>')
                .appendTo( $(column.footer()).empty() )
                .on( 'change', function () {
                    var val = $.fn.dataTable.util.escapeRegex(
                        $(this).val()
                    );
 
                    column
                        .search( val ? '^'+val+'$' : '', true, false )
                        .draw();
                } );
 
            column.data().unique().sort().each( function ( d, j ) {
                select.append( '<option value="'+d+'">'+d+'</option>' )
            } );
        } );
    } 
    
} );
} );
<link href="https://cdn.datatables.net/r/dt/jq-2.1.4,dt-1.10.9,b-1.0.3,b-flash-1.0.3/datatables.min.css" rel="stylesheet"/>
<script src="https://cdn.datatables.net/r/dt/jq-2.1.4,dt-1.10.9,b-1.0.3,b-flash-1.0.3/datatables.min.js"></script>

<table id="example" class="display" width="100%">
<tfoot><tr></tr></tfoot>
</table>

运行 sn -p 后可以看到,第一个 ID 列没有按数字排序。这是截图:

如何启用它? 这与其他问题不同,因为它特定于 DataTables。

【问题讨论】:

  • @Haketo,这不是一个重复的问题,因为数组可能包含最初可能不知道的数字或字符串。
  • @Gyrocode.com 那么第一个答案不适用于字符串值"111" &lt; "12" BTW OP 状态的数字。所以是的,它是重复的
  • @Haketo, example on DataTables site 不正确,因为 OP 发现包含数字数据的列存在问题。 DataTables 网站上的示例之所以有效,是因为这些数字都是具有欺骗性的两位数。
  • @Haketo,问题显示在问题中,数字被排序为字符串,没有sort 的参数。但是,其他列可能需要按字符串排序或在必要时使用自定义排序函数。

标签: javascript jquery html json datatables


【解决方案1】:

解决方案

列数据类型在初始化时由jQuery DataTables自动确定,默认支持data types

initComplete函数中,您可以暂时按升序对每一列进行排序,然后在添加所有下拉框后恢复初始顺序,请参见下面的代码。

initComplete: function (settings, json) {
    // Get initial order
    var orderInit = this.api().order();
    
    this.api().columns().every( function (index) {
        var column = this;
        var select = $('<select><option value=""></option></select>')
            .appendTo( $(column.footer()).empty() )
            .on( 'change', function () {
                var val = $.fn.dataTable.util.escapeRegex(
                    $(this).val()
                );

                column
                    .search( val ? '^'+val+'$' : '', true, false )
                    .draw();
            } );

        // NOTE: Temporarily sort the column data before retrieving it
        // with data() function.
        column.order('asc').draw(false).data().unique().each( function ( d, j ) {
            select.append( '<option value="'+d+'">'+d+'</option>' )
        } );
    } );
  
    // Restore initial order
    this.api().order(orderInit).draw(false);
} 

演示

var dataSet = [
  [1,"Airi Satou", "Accountant", "Tokyo", "5407", "2008/11/28", "$162,700"],
  [2,"Angelica Ramos", "Chief Executive Officer (CEO)", "London", "5797", "2009/10/09", "$1,200,000"],
  [10,"Gavin Joyce", "Developer", "Edinburgh", "8822", "2010/12/22", "$92,575"],
  [3,"Jennifer Chang", "Regional Director", "Singapore", "9239", "2010/11/14", "$357,650"],
  [5,"Brenden Wagner", "Software Engineer", "San Francisco", "1314", "2011/06/07", "$206,850"],
  [9,"Fiona Green", "Chief Operating Officer (COO)", "San Francisco", "2947", "2010/03/11", "$850,000"],
  [12,"Shou Itou", "Regional Marketing", "Tokyo", "8899", "2011/08/14", "$163,000"],
  [23,"Martena Mccray", "Post-Sales support", "Edinburgh", "8240", "2011/03/09", "$324,050"],
  [99,"Unity Butler", "Marketing Designer", "San Francisco", "5384", "2009/12/09", "$85,675"]
];

$(document).ready(function() {

var columns = [
    {title: "ID"},
    {title: "Name"}, 
    {title: "Position"}, 
    {title: "Office"}, 
    {title: "Extn."}, 
    {title: "Start date"}, 
    {title: "Salary"}
];

// Footer construction
var $tfoot = $("#example tfoot tr");
for (var i = 0, len = columns.length; i < len ; i++){
    $tfoot.append("<th>");
}

$('#example').DataTable( {
    data: dataSet,
    columns: columns,
    initComplete: function (settings, json) {
        // Get initial order
        var orderInit = this.api().order();
        
        this.api().columns().every( function (index) {
            var column = this;
            var select = $('<select><option value=""></option></select>')
                .appendTo( $(column.footer()).empty() )
                .on( 'change', function () {
                    var val = $.fn.dataTable.util.escapeRegex(
                        $(this).val()
                    );
 
                    column
                        .search( val ? '^'+val+'$' : '', true, false )
                        .draw();
                } );
 
            column.order('asc').draw(false).data().unique().each( function ( d, j ) {
                select.append( '<option value="'+d+'">'+d+'</option>' )
            } );
        } );
      
        // Restore initial order
        this.api().order(orderInit).draw(false);
    } 
    
} );
} );
<link href="https://cdn.datatables.net/r/dt/jq-2.1.4,dt-1.10.9,b-1.0.3,b-flash-1.0.3/datatables.min.css" rel="stylesheet"/>
<script src="https://cdn.datatables.net/r/dt/jq-2.1.4,dt-1.10.9,b-1.0.3,b-flash-1.0.3/datatables.min.js"></script>

<table id="example" class="display" width="100%">
<tfoot><tr></tr></tfoot>
</table>

注意事项

有关更多详细信息和进一步讨论,请参阅issue #661 on GitHub

【讨论】:

  • 很好的答案,但请在解决方案部分中指定 Salary 列的附加逻辑。
  • @neversaint,添加了更好的解决方案,它使用 DataTables 内部排序功能并且不需要自定义功能。
  • @Gyrocode.com:你是救生员。也感谢您回答我的“移动按钮”问题。
  • 快到 2020 年了,它仍然是正确的修复程序。谢谢!
【解决方案2】:

原因

默认情况下,没有定义排序顺序的函数的数组排序方法会将您的数组排序为字符串,以便您得到预期的结果。你可以在这里阅读更多信息 - Array.prototype.sort()。因此,您需要添加一个函数,以便对数字和字符串的数据进行正确排序。

解决方案

添加sortFunction函数并将其用作sort()函数的参数,如下所示:

var sortFunction = function(a, b) {
    if(a < b) return -1;
    if(a > b) return 1;
    return 0;
};

column.data().unique().sort(sortFunction).each( function ( d, j ) {

演示

var dataSet = [
  [1,"Airi Satou", "Accountant", "Tokyo", "5407", "2008/11/28", "$162,700"],
  [2,"Angelica Ramos", "Chief Executive Officer (CEO)", "London", "5797", "2009/10/09", "$1,200,000"],
  [10,"Gavin Joyce", "Developer", "Edinburgh", "8822", "2010/12/22", "$92,575"],
  [3,"Jennifer Chang", "Regional Director", "Singapore", "9239", "2010/11/14", "$357,650"],
  [5,"Brenden Wagner", "Software Engineer", "San Francisco", "1314", "2011/06/07", "$206,850"],
  [9,"Fiona Green", "Chief Operating Officer (COO)", "San Francisco", "2947", "2010/03/11", "$850,000"],
  [12,"Shou Itou", "Regional Marketing", "Tokyo", "8899", "2011/08/14", "$163,000"],
  [23,"Martena Mccray", "Post-Sales support", "Edinburgh", "8240", "2011/03/09", "$324,050"],
  [99,"Unity Butler", "Marketing Designer", "San Francisco", "5384", "2009/12/09", "$85,675"]
];

 $(document).ready(function() {

var columns = [
    {title: "ID"},
    {title: "Name"}, 
    {title: "Position"}, 
    {title: "Office"}, 
    {title: "Extn."}, 
    {title: "Start date"}, 
    {title: "Salary"}
];

// Footer construction
var $tfoot = $("#example tfoot tr");
for (var i = 0, len = columns.length; i < len ; i++){
    $tfoot.append("<th>");
}

$('#example').DataTable( {
    data: dataSet,
    columns: columns,
    initComplete: function (setting, json) {
        this.api().columns().every( function () {
            var column = this;
            var select = $('<select><option value=""></option></select>')
                .appendTo( $(column.footer()).empty() )
                .on( 'change', function () {
                    var val = $.fn.dataTable.util.escapeRegex(
                        $(this).val()
                    );
 
                    column
                        .search( val ? '^'+val+'$' : '', true, false )
                        .draw();
                } );
 
                var sortFunction = function(a, b) {
                    if(a < b) return -1;
                    if(a > b) return 1;
                    return 0;
                };
                column.data().unique().sort(sortFunction).each( function ( d, j ) {
                select.append( '<option value="'+d+'">'+d+'</option>' )
            } );
        } );
    } 
    
} );
} );
<link href="https://cdn.datatables.net/r/dt/jq-2.1.4,dt-1.10.9,b-1.0.3,b-flash-1.0.3/datatables.min.css" rel="stylesheet"/>
<script src="https://cdn.datatables.net/r/dt/jq-2.1.4,dt-1.10.9,b-1.0.3,b-flash-1.0.3/datatables.min.js"></script>

<table id="example" class="display" width="100%">
<tfoot><tr></tr></tfoot>
</table>

【讨论】:

  • 很好的答案,但是如果您删除 sort(),其他选择框将包含未排序的数据。这不是一个完整的解决方案。
  • 只需要做return a - b你的代码没有处理字符串值"111" &lt; "12"return true
  • @Haketo - 你确定吗? return a - b 仅适用于数字,但我们正在比较数字和字符串。所以我们需要重构整个代码——首先验证列中的值是数字还是字符串,然后使用适当的排序函数。
  • Salary 列看起来像一个带有数字的列,但实际上它被视为string,因为它的值具有“$”和“,”符号。因此,应该为此列编写附加函数。例如,该函数可以克隆现有数组,将值数组修改为对象数组,其中每个对象将具有两个属性 - 主值和修改值 - 没有'$'和','的实数。然后按实数排序,删除它们并返回正确排序的主值数组。
【解决方案3】:

不一定要有 sort() 方法。

所以,只要改变它:

column.data().unique().each( function ( d, j ) {
    select.append( '<option value="'+d+'">'+d+'</option>' )
});

请找JSFIDDLE

编辑:添加 unique()(我删除错误)+ 更新 jsfiddle

【讨论】:

  • 谢谢@Gyrocode.com!我,有错误删除。将尽快改变小提琴我将在电脑上
  • 很好的答案,但是如果您删除 sort(),其他选择框将包含未排序的数据。这不是一个完整的解决方案。
  • @Gyrocode.com:谢谢。你是对的,其他列需要正确排序。例如,第 2 列或第 3 列也可能包含数值。您将如何处理?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-02
  • 2010-12-14
  • 2016-10-05
  • 2017-04-09
  • 2012-08-31
相关资源
最近更新 更多