Tutorial: Sorting

Sorting


Edit this page

How the sorting works

If you want to sort data in your datasource array, you can simply invoke an Array.prototype.sort() function and call the render() function to refresh the table. You don't need any plugin for this. However, this operation alters the structure of the datasource, and in many cases you want to leave the datasource intact, while displaying its content in a specified order. Here's where column sorting plugin comes in handy.

Column sorting plugin works as a proxy between the datasource and the Handsontable rendering module. It can map indices of displayed rows (called logical indices) to the indices of corresponding rows in datasource (called physical indices) and vice versa. This way you can alter the order of rows which are being presented to user, without changing the datasource internal structure.

This simple mechanism gives you a lot of flexibility, but it also introduces a few pitfalls if the developer is not full aware of the way plugin works.

How to enable the plugin

The property which is responsible for enabling and configuring the column sorting is called columnSorting (pretty unexpected, huh :P ). The value of this property can be either a Boolean or an Object.

If the columnSorting is of type Boolean, then true means the plugin is enabled and false means the plugin is disabled. The important thing to remember is that enabling the plugin using true does not sort the table content right away. The table has to be sorted either by a user or programmatically.

If the columnSorting is an Object, then it means that the plugin is enabled and configured according to the properties passed in the configObject. The configObject can be used to set the initial sorting parameters, which are:

  • column : Number - this index of column, by which you want to sorter the table.
  • sortOrder : Boolean - defines the order of sorting (true for ascending, false for descending). This arguments is optional. If it's not specified, the default order is ascending.

As all settings, columnSorting can be altered during the lifetime of a table, using updateSettings() method.

Examples:

// enables the plugin, but does not sort the table
var hot = new Handsontable(document.getElementById('example'), {
  columnSorting: true
});

// enables the plugin and sort the table by the values from the first column in ascending order
var hot = new Handsontable(document.getElementById('example'), {
  columnSorting: {
    column: 0
  }
});

// enables the plugin and sort the table by the values from the first column in descending order
var hot = new Handsontable(document.getElementById('example'), {
  columnSorting: {
    column: 0
    sortOrder: false
  }
});

// disable plugin
hot.updateSettings({
  columnSorting: false
});

How to determine if sorting is enabled

To check whether sorting has been enabled for a particular Handsontable instance, use sortingEnabled property.

hot.sortingEnabled ? doSomething() : doSomethingElse();

The fact that column sorting has been enabled, does not imply, that the table content is sorted. To check whether a table has been sorted you can check the sortColumn property. If table instance has this property defined then it has been sorted. The value of sortColumn is the index of a column by which the table has been sorted. Additionally, you can check sorting order using sortOrder property. If sortOrder is true, then the order is ascending, otherwise, the order is descending.

Simple function, which checks whether the table has been sorted could look like this:

function isSorted(hotInstance) {
  return hotInstance.sortingEnabled && typeof hotInstance.sortColumn !== 'undefined';
}

How to sort a table

There are 3 ways you can sort a table:

  • using columnSorting property
  • by clicking on the table header
  • invoking the sort() method

The first possibility has been discussed in How to enable the plugin section.

The second option is probably the most popular one. If the plugin is enabled, clicking on column header causes table to be sorted by the corresponding values in ascending order. As usual, if you click the header again, the order will switch to descending.

The last recommended way of sorting the table is using the sort() method. When columnSorting plugin is enabled, it exposes a new method in Handsontable instance, called sort(). The method accepts 2 arguments: column and order.

  • column : Number - argument is the index of column, by which you want to sorter the table. This argument is required.
  • order: Boolean - defines the order of sorting (true for ascending, false for descending). This arguments is optional. If it's not specified, the default order is ascending.

Example:

if (hot.sortingEnabled) {
  // will sort table using values from the first column in descending order
  hot.sort(0, false);
}

Rows indices translation

The main task of column sorting plugin is mapping the data source rows indices to displayed rows indices and vice versa. The indices of displayed rows are called logical indices and the indices in datasource array are called physical indices. In general, every logical index has a corresponding physical index.

Most of the time, this whole mapping logic takes place under the hood and you don't have to even bother remembering it, because a vast majority of important operations and functions is interested only in physical indices. For example, if the cell value changes, the afterChange event is triggered. All event listeners will receive a row index of the row, where the change took place. This will be the physical index of the modified row. Same scheme applies to other events.

On the other hand, each time a cell renderer is invoked, the row index that is being passed to the renderer function is always a logical row index, because the logic of the renderer should correspond to the parameters of the displayed row, instead of the parameters of the actual row in the datasource.

However, sometimes you might need to know which physical row is displayed as the first logical row and the other way around. To do so, you have to use sortIndex an extra property, which is being added to Handsontable instance, when column sorting plugin is enabled.

sortIndex is a 2D array which maps indices of visible rows (logical indices) to indices of rows stored in datasource (physical indices).

Example: My table is sorted. I have changed row 4 and I want to know which row in data source got updated. So I want to get the physical index, having the logical index. This is the code I have to write:

physicalIndex = instance.sortIndex[logicalIndex][0];

The reverse mapping is a bit more complicated, nonetheless is also possible. In fact, columnSorting plugin has two dedicated methods which translates logical indices to physical and vice versa (called translateRow() and untranslateRow()) but they are currently inaccessible from the global scope.

Click on a column header to sort. Only the table view is sorted. The data source remains in the original order. For an in depth documentation of column sorting plugin see the Understanding column sorting plugin wiki page.

Sorting indicator

Since 0.15.0-beta3 it is possible to enable a sorting indicator to the sortable columns. To do that, you need to add a sortIndicator setting:

sortIndicator: true

Note, that you can enable this option for either the entire table (when setting it in the main config object) or for certain columns only (when using it in the columns array))
The following example has this feature enabled.