12

I am trying to make datatables sort my columns. The first column works okay as it's a simple number. However the next column is an input field. When I try to make that sort then nothing happens.

<table width="100%" cellspacing="0" class="table sortable no-margin">
<thead>
<tr>
   <th scope="col" class="sorting" style="width: 57px;">
        <span class="column-sort">
        <a href="#" title="Sort up" class="sort-up"></a>
        <a href="#" title="Sort down" class="sort-down"></a>
        </span>
        ID
   </th>
   <th scope="col" class="sorting_desc" style="width: 94px;">
        <span class="column-sort">
        <a href="#" title="Sort up" class="sort-up"></a>
        <a href="#" title="Sort down" class="sort-down"></a>
        </span>
        Order
   </th>
</tr>
</thead>
<tbody>
<tr id="row_20" class="odd">
    <td id="refKey_20" style="text-align:center;" class="">
        1Y
    </td>
    <td class=" sorting_1">
        <input type="text" value="160" size="3" name="item.Order" 
        maxlength="3" id="Order_20" >
    </td>

</tr>
<tr id="row_19" class="even">
    <td id="refKey_19" style="text-align:center;" class="">
        1X
    </td>
    <td class=" sorting_1">
        <input type="text" value="150" size="3" name="item.Order" 
        maxlength="3" id="Order_19" >
    </td>

</tr>
</tbody>
</table>

Is there some way that I can get datatables to sort input fields?

6 Answers 6

12

The easiest way is to add a hidden span inside columns <span style="visibility:hidden">value of the input</span>

Sign up to request clarification or add additional context in comments.

2 Comments

Nice trick! First hidden span, then the input. all inside the column
Very nice! simple and easy. In my case I just changed from visibility:hidden to display:none so it doesn't take DOM space. Thanks!
10

You should look at this example that explains how to do sorting on input fields. Basically you declare a sorting function

/* Create an array with the values of all the input boxes in a column */
$.fn.dataTableExt.afnSortData['dom-text'] = function  ( oSettings, iColumn )
{
    var aData = [];
    $( 'td:eq('+iColumn+') input', oSettings.oApi._fnGetTrNodes(oSettings) ).each( function () {
        aData.push( this.value );
    } );
    return aData;
}

And then tell to your table to use that

$('#example').dataTable( {
    "aoColumns": [
        null,
        { "sSortDataType": "dom-text" }
    ]
} );

or wit aoColumnDefs

$('#example').dataTable( {
    "aoColumnDefs": [{ "sSortDataType": "dom-text" , aTarget: "yourclass"}]
} );

4 Comments

But I have a problem. I use the same refresh code for different tables. Your code hardcodes the aoColumns. Is it possible to set these up as classes on the td columns? Or alternatively can I make a different set of "aoColumns" and use different ones for each table?
@Gemma i usually had to set-up manually aoColumns for each table, i think that you should have different sets of aoColumns and than use them as needed while keeping the other options fixed
Did you try aoColumnDefs. I am just trying to learn about that. I think that can set based on the class of a th.
@Gemma, never tried that but it should work, i added that to my answer
9

For versions of Datatables 1.10+ the names of some option variables have been changed and a new API introduced. Documentation here: http://datatables.net/examples/plug-ins/dom_sort.html.

Here is a working version of the above accepted answer in 1.10+:

$(document).ready(function () {
    var table = $('#example').DataTable({
        "columnDefs": [
            {
                "orderDataType": "dom-input",
                "targets": 0, // Just the first column
            },
        ],
    });
});

The custom sort function:

$.fn.dataTable.ext.order['dom-input'] = function (settings, col) {
    return this.api().column(col, { order: 'index' }).nodes().map(function (td, i) {
        return $('input', td).val();
    });
}

1 Comment

You must add type: 'string' to the columnDefs array object to get it to work on alphanumeric fields
1
jQuery.fn.dataTableExt.oSort['textbox-asc'] = function (a, b) {
    var vala = $('#' + $(a).filter('input').attr('id')).val().toLowerCase();
    var valb = $('#' + $(b).filter('input').attr('id')).val().toLowerCase();
    if (vala === '')
        return 1;
    if (valb === '')
        return -1;
    return vala < valb ? -1 : vala > valb ? 1 : 0;
};

jQuery.fn.dataTableExt.oSort['textbox-desc'] = function (a, b) {
    var vala = $('#' + $(a).filter('input').attr('id')).val().toLowerCase();
    var valb = $('#' + $(b).filter('input').attr('id')).val().toLowerCase();
    if (vala === '')
        return 1;
    if (valb === '')
        return -1;
    return vala < valb ? 1 : vala > valb ? -1 : 0;
};

then use it like this

 $(datatable).dataTable({
                    "iDisplayLength": 50,
                    "bLengthChange": false,
                    "bPaginate": false,                        
                    "columns": [
                        null, { "sType": "textbox" }
                    ],
                });

Comments

0

If you decide to use the columns option where you are rending information from a JSON file you can easily add a hidden span on your render property. It appears as though DataTables looks for text to order and if it cannot find any, it will break. The example at https://datatables.net/examples/plug-ins/dom_sort.html uses a table that has already been rendered. Here is an example using an API:

...columns([{ 
        "data": "receivedDate",
        "render": function (data, type, row, meta)
        {

            if (data == "null")
            {
                return "<input type='text' id='datepicker_" + meta.row + "' class='datepicker form-control' /><span class='hidden'><span>";
            }
            else
            {
                return "<input type='text' id='datepicker_" + meta.row + "' class='datepicker form-control' value='" + moment(data).format("MM/DD/YYYY") + "'/><span class='hidden'>" + moment(data).format('MM/ DD / YYYY') + "</span>";
            }
        }
    }]);

Comments

-1

Set an invisible div with the value before the input field.

<tbody>
<tr id="row_20" class="odd">
    <td id="refKey_20" style="text-align:center;" class="">
        1Y
    </td>
    <td class=" sorting_1">
        <div style="display:none;">160</div>
        <input type="text" value="160" size="3" name="item.Order" 
        maxlength="3" id="Order_20" >
    </td>

</tr>
<tr id="row_19" class="even">
    <td id="refKey_19" style="text-align:center;" class="">
        1X
    </td>
    <td class=" sorting_1">
        <div style="display:none;">150</div>
        <input type="text" value="150" size="3" name="item.Order" 
        maxlength="3" id="Order_19" >
    </td>
</tr>
</tbody>

1 Comment

This doesn't work when the input value is edited by the user, without code to update the value on the change event, which seems way too much work.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.