How to apply ascending sort to split data in datatable

Viewed 556

I created a table using datatable jquery plugin. The data also includes "/", so I split it up and completed the process of making each word into a dropdown list. Now I want to sort each splite word in ascending order.

As a method found through Googling, it is a method of ordering the data before splitting. I want to know how to orderby data after split. The language I am using is Hangul, and the syntax for ascending Hangul is as follows.

(a<b)?-1:(a==b)?0:1;

this.api().columns().every( function () {
            var column = this;
            var colTitle = this.header().innerHTML;
            var select = $('<select><option value="" selected>' + colTitle + '</option></select>')
                .appendTo( $(column.header()).empty() )
                .on( 'change', function () {
                    var val = $.fn.dataTable.util.escapeRegex(
                        $(this).val()
                     );
                    column
            .search( this.value )
            .draw();
            } );

            column.data().unique().sort().each( function( d, j ) {
                   var name = d.split("/");
                    name.forEach(function(number) {
                        var optionExists = ($("select option[value='"+number+"']").length > 0);
                        if(!optionExists){
                            select.append( '<option value="'+number+'">'+number+'</option>' );
                        }
                    });
            } );
        } );
1 Answers

I don't think the language you are using is relevant here, because the default sort() method is basically the same as the one you refer to in the question: (a<b)?-1:(a==b)?0:1. (But see my note at the end for more thoughts about that.)

There are two issues I think need to be fixed:

1. Split first, the remove duplicates, then sort

Currently, your code removes duplicates and splits the cell data before performing the sort - so we need to reverse that. This requires us to create a new array in which we will collect unsorted, unique values after performing the cell split:

var items = [];

2. Separate column ordering from column filtering

If you place the select list in the heading cell, then every time you click on the drop-down you will also trigger the DataTables column sorting functionality. So we need to keep these two things separate.

The easiest way to do this is to create a second heading row and put the dropdown in the header row above the column heading label (where column sorting is controlled):

$('#example thead tr').clone(true).appendTo( '#example thead' );

Here is a demo:

$(document).ready(function() {

  $('#example thead tr').clone(true).appendTo( '#example thead' );

  var table = $('#example').DataTable( {
    initComplete: function () {
      this.api().columns().every( function () {
        var column = this;
        var colIdx = column.index();
        var colTitle = this.header().innerHTML;

        var select = $('<select><option value="" selected> --select--</option></select>')
          .appendTo( $('#example thead tr:eq(0) th:eq(' + colIdx + ')').empty() )
          .on( 'change', function () {
          var val = $.fn.dataTable.util.escapeRegex(
            $(this).val()
          );
          column
            .search( val ? val : '', true, false )
            .draw();
        } );
 
        var items = [];
        
        // first split each cell's data, and discard duplicates:
        column.data().toArray().forEach( function ( cell, x ) {
          cell.split("/").forEach( function ( item, y ) {
            if (! items.includes(item)) {
              items.push(item);
            }
          } );
        } );

        // then sort the results:
        items.sort();

        // now we can build the drop-down list:
        items.forEach( function ( option, z ) {
          select.append( '<option value="' + option + '">' + option + '</option>' )
        } );

      } );
    }
  } );

} );
<head>
  <meta charset="UTF-8">
  <title>Demo</title>
  <script src="https://code.jquery.com/jquery-3.5.1.js"></script>
  <script src="https://cdn.datatables.net/1.10.22/js/jquery.dataTables.js"></script>
  <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.22/css/jquery.dataTables.css">
  <link rel="stylesheet" type="text/css" href="https://datatables.net/media/css/site-examples.css">

</head>

<body>

<div style="margin: 20px;">

    <table id="example" class="display dataTable cell-border" style="width:100%">
        <thead>
            <tr>
                <th>Number</th>
                <th>Animal</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>one/two/three</td>
                <td>horse/chicken/dog</td>
            </tr>
            <tr>
                <td>two/three/four</td>
                <td>chicken/pig/sheep</td>
            </tr>
            <tr>
                <td>four/five/six</td>
                <td>sheep/horse/goat</td>
            </tr>
        </tbody>

    </table>

</div>

</body>


Language-sensitive string comparisons

If you still have a problem with the way your Hangul data is being sorted, then you can use a custom comparison function.

This may be the case even in Western scripts, if you want to sort in "dictionary" order, so that a word such as "éléphant" is sorted alongside "elephant" (otherwise it would be sorted after "zebra").

See Intl.Collator for more details regarding language-sensitive string comparisons.

Related