Row Indexes vs. Display Positions in DataTables

29 Dec 2020

Table of Contents


Introduction

When data is loaded into a DataTables object, it is assigned a row index - basically, it is added to an array structure. Rows are loaded in the order they are presented to DataTables - for example, when parsing a JSON source, or when loading the contents of a pre-populated HTML table:

HTML
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<table id="example" class="display dataTable cell-border" style="width:100%">
    <thead>
        <tr>
            <th>Name</th>
            <th>Position</th>
            <th>Office</th>
            <th>Age</th>
            <th>Start date</th>
            <th>Salary</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>Tiger Nixon</td>
            <td>System Architect</td>
            <td>Edinburgh</td>
            <td>61</td>
            <td>2011/04/25</td>
            <td>$320,800</td>
        </tr>
        <tr>
            <td>Garrett Winters</td>
            <td>Accountant</td>
            <td>Tokyo</td>
            <td>63</td>
            <td>2011/07/25</td>
            <td>$170,750</td>
        </tr>

        [not all rows shown]

        <tr>
            <td>Michael Bruce</td>
            <td>Javascript Developer</td>
            <td>Singapore</td>
            <td>29</td>
            <td>2011/06/27</td>
            <td>$183,000</td>
        </tr>
        <tr>
            <td>Donna Snider</td>
            <td>Customer Support</td>
            <td>New York</td>
            <td>27</td>
            <td>2011/01/25</td>
            <td>$112,000</td>
        </tr>
    </tbody>
</table>

So, Tiger Nixon is assigned to row index 0 internally in DataTables. This row index never changes, as long as the DataTables object exists and the row is not removed from the DataTables object.

Use a Row Index

We can use these indexes in various ways, for example:

JavaScript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
$(document).ready(function() {

  var table = $('#example').DataTable();
  //
  // use the internal index of a row:
  //
  var idx = 1;
  var row = table.row( idx ).data();
  console.log(row[0] + ' has internal row index ' + idx);

  idx = 2;
  var row = table.row( idx ).data();
  console.log(row[0] + ' has internal row index ' + idx);

} );

Output:

Garrett Winters has internal row index 1
Ashton Cox has internal row index 2

Get a Row Index

If you want to find the row index of a specific row, you can use one of the following functions, depending on the object you are using (row, column, or cell):

For example, assume you have a click event defined on every <td> cell in your table:

JavaScript
1
2
3
$('#example td').on('click', function () {
  var rowIndex = table.cell( this ).index().row;
} );

In this case the index() call returns an object containing row, column, and columnVisible fields. The row value represents the internal DataTables row index.

There is also a column().index() function which returns the column index (either the visible column index if columns can be hidden, or the original column index).

Display Position

However, we may also want to know where a row is displayed in a table - its visual position, like a row number in a spreadsheet.

We may also need to take into account the fact that the row may not be on the current page (assuming DataTables pagination) - and not even part of the DOM. jQuery cannot help us in this case.

We can use the indexOf() function to find the first occurrence of an item in a DataTables API object:

JavaScript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
$(document).ready(function() {

  var table = $('#example').DataTable();

  //
  // get the display position of a row:
  //
  var name = 'Cedric Kelly';
  console.log( name + ' is at table row ' + (getPosition( 0, name ) +1) );

  name = 'Charde Marshall';
  console.log( name + ' is at table row ' + (getPosition( 0, name ) +1) );

  function getPosition( colIdx, value) {
    return table.column( colIdx, {order: 'current'} ).data().indexOf( value );
  }

  //
  // get the page and row-in-page positions:
  // see also: https://datatables.net/plug-ins/api/page.jumpToData()
  //
  var pos = getPosition( 0, name );
  if ( pos >= 0 ) {
    var pageLen = table.page.info().length;
    var pageNum = Math.floor( pos / pageLen );
    var rowInPage = pos - ( pageLen * pageNum );
    console.log( name + ' is at page ' + (pageNum +1) + ' row ' + (rowInPage +1) );
  }

} );

Output:

Cedric Kelly is at table row 10
Charde Marshall is at table row 11
Charde Marshall is at page 2 row 1

This example uses column( columnSelector, modifier ), where:

  • columnSelector is an integer
  • modifier is the object {order: 'current'}

In this case, the modifier is a DataTables selector-modifier where current means rows are processed in the order they are currently applied in the table (accounting for sorting and filtering).

All Data Indexes

Consider the following initComplete() function:

JavaScript
1
2
3
4
5
"initComplete": function(settings, json) {
  var api = this.api();
  var tableData = $( api.rows( {order: 'index'} ).data() );
  console.log( tableData );
}

This creates a JavaScript object containing an array of arrays (or an array of objects, depending on how your data was provided to DataTables).

The {order: 'index'} selector ensures that the order of rows matches the original iternal index order.

You can also use {order: 'current'} to capture your data with rows ordered as per the current display order.

If you use rows().data() without a selector, then this defaults to using the display order.

Note that $( api.rows( {order: 'index'} ).data() ) creates a shallow copy of the table’s data. Changes to the DataTables data will be reflected in the tableData object.

If you want a deep copy, you can use the jQuery extend() function:

JavaScript
1
var tableData = $.extend(true, {}, $( api.rows( {order: 'index'} ).data() ));