Renderers
There are occasions when the data source for the table's rows does not contain the value that you would want to display in the table. You may wish to transform it to a different representation (such as a time stamp into a human readable format), combine data points (first and last names, perhaps) or perform some computation on the value (maybe calculating margin from turnover and expense values).
This transformation of the original data into the value that will be shown in the DataTable is called rendering in DataTables' terminology and is performed using the columns.render
option.
Data rendering
The primary advantage of using a data renderer in DataTables is that you can modify the output data without modifying the original data. The columns.data
method can be used to get and set data, but the set operation adds significant complexity and it is recommended that the columns.data
option be used simply to point to the original representation of the data and allow a renderer (columns.render
), which is read only, to transform the data.
columns.render
can be utilised in a number of different ways:
- As a function to transform data
- As a string to select data from an object
Functions
Using columns.render
is the most common method as it provides absolute control over the data that will be displayed to the end user (this is a regular Javascript function, so you can do virtually anything you wish with the data).
The function is passed in three parameters:
- The data that is pointed to by
columns.data
. Ifcolumns.data
isnull
,null
will be the value given here. - The data type being requested by DataTables - this allows the function to support orthogonal data.
- The original and full data object or array for the row.
The value that is returned from the function is whatever DataTables will use for the data being requested (display, ordering, search, etc).
Consider for example the following data structure which contains the data for a row:
{
"product": "Toy car",
"creator": {
"firstName": "Fiona",
"lastName": "White"
},
"created": "2015-11-01",
"price": 19.99,
"cost": 12.53
}
Adding formatting
In our DataTable, if we wish to have a column that shows the price, it is relatively common to wish to prefix it with a currency sign. In this case we use a dollar sign (see also the built-in number renderer below which provides advanced formatting options):
{
data: 'price',
render: function ( data, type, row ) {
return '$'+ data;
}
}
Joining strings
In our DataTable if we wish to have a single column that shows the full name of the creator we can concatenate strings using the following columns
definition (note in particular how the create
object is passed in as the first parameter due to its assignment using the columns.data
option):
{
data: 'creator',
render: function ( data, type, row ) {
return data.firstName +' '+ data.lastName;
}
}
Transforming data
For another column we wish to display the created
value, but formatted using the US standard MM-DD-YYYY formatting. This can be done simply by splitting the string and rearranging the component parts. We also wish for the date to be sortable, and since DataTables has built in support for ISO8601 formatted string (the original format), we wish to perform the transformation only for the display
and filter
data type - see orthogonal data for more):
{
data: 'created',
render: function ( data, type, row ) {
var dateSplit = data.split('-');
return type === "display" || type === "filter" ?
dateSplit[1] +'-'+ dateSplit[2] +'-'+ dateSplit[0] :
data;
}
}
Computing values
Finally, to create a margin column from the price
and cost
fields we can use a function to compute the required values - note that in this case columns.data
is null
- as a result the first parameter passed into the columns.render
method is also null
, but the third parameter provides access to the original data source object, so we can continue use the data from there:
{
data: null,
render: function ( data, type, row ) {
return Math.round( ( row.price - row.cost ) / row.price * 100 )+'%';
}
}
Strings
A less common option for formatters is as a string to simply point at the data that should be used in the table. This is similar to the way that columns.data
is often used, although keep in mind that the renderer will only have access to the data pointed to by columns.data
rather than the full row.
Continuing the examples using the JSON data structure from above, consider a column that should show the first name of the creator:
{
data: 'creator',
render: 'firstName'
}
There is no advantage to this method over simply using data: 'creator.firstName'
in the example presented here, but if you have complex data with orthogonal data included in the data source object, this can sometimes be useful.
Built-in helpers
DataTables has a number of built in rendering helpers that can be used to easily format data - more can be added using plug-ins (see below):
date
- formatting dates (since 1.12)datetime
- formatting date times (since 1.12)number
- for formatting numberstext
- to securely display text from a potentially unsafe source (HTML entities are escaped)time
- formatting times (since 1.12).
The built in rendering helpers can be accessed under the DataTable.render
object (since 1.11) or $.fn.dataTable.render
(which is an alias to the same object). They are functions (allowing options to be passed into them) which should be immediately executed and their result assigned to the columns.render
method. This might sound a little complicated, but it simply means you would use something like the following:
{
data: 'price',
render: DataTable.render.number( ... )
}
Date and time helpers
We'll discuss the date
, datetime
and time
helper functions together, as they all share the same API. These renderers can be used to:
- Format an ISO-8601 string into a locale aware display string without any additional software,
- Format an ISO-8601 string to a custom format via either Moment.js or Luxon,
- Transform between a custom format in the data and another custom format for display (again using Moment.js or Luxon).
The date
, datetime
and time
helper functions have the following function signatures:
DataTable.render.datetime() // Display a locale aware date / time from an ISO-8601 string
DataTable.render.datetime(to) // Display a custom format date / time from an ISO-8601 string
DataTable.render.datetime(to, locale) // Display a custom format date / time with a given locale
DataTable.render.datetime(from, to, locale) // Transform from one custom format to another, with a given locale.
where:
to
is the format that you wish to be shown in the DataTable. Note that if this option is used, you must include either Moment.js or Luxon on your page. Each library has its own formatting token support. Please refer to their documentation for the formatting options available (Moment.js documentation | Luxon).locale
is the locale to be passed to Moment.js or Luxon. If you use this option and it isn't the defaulten
, you will need to be sure to load that locale for the library you are using.from
the date / time format that should be parsed from the column - this is required when the detection of non-ISO8601 date/time formats is needed. It also uses the Moment.js and Luxon parsing tokens, and note that the parsing is strict - it must exactly match the format of your date.
Examples for Date / time handling in DataTables are available here.
Number helper
The number
helper provides the ability to easily format, you guessed it, numbers! When dealing with numbers, you may often wish to add formatting such as prefix and postfix characters (currency indicators for example), use a thousands separator and specify a precision for the number. This is all possible with the number
helper.
This number helper function has the following function signature:
DataTable.render.number() // Locale aware number display (since 1.12)
DataTable.render.number(null, null, precision, prefix, postfix) // Locale aware display with decimal places, prefix and postfix (since 1.12)
DataTable.render.number(thousands, decimal, precision, prefix, postfix) // Thousands and decimal specified
where:
thousands
is the character to use for the thousands separator (can benull
in which case a locale aware separator is used)decimal
is the character to use for the decimal character (can benull
in which case a locale aware character is used)precision
is the floating point precision - 0 for integers, 1 for a single decimal place, etc (optional)prefix
is a prefix string (optional)postfix
is a postfix string (optional)
For example, to display the price
data point from the data structure shown above in the format $19.99
we would use:
{
data: 'price',
render: DataTable.render.number( null, null, 2, '$' )
}
Note that null
is used for the thousands and decimal characters. This is recommends as it will allow DataTables to display the number is a format suitable for your end user automatically.
Additionally, if the number
helper encounters a value which is not a valid number (either number
or string
that contains a number) it will return the value after escaping any HTML entities in it (to help protect against potential security attacks).
An example of the number renderer is available here.
Text helper
The text
helper will ensure that any potentially dangerous HTML in the source data will not be executed by escaping the HTML entities. This can be useful if the data being loaded may come from a potentially untrusted data source and can help mitigate XSS attacks.
The text
helper doesn't take any parameters making its use simply:
{
data: 'product',
render: DataTable.render.text()
}
Custom helpers
Rendering helpers are simply functions which are attached to the DataTable.render
object (which can also be access through $.fn.dataTable.render
) to make them easily accessible from a single location. These functions must return a function that will operate with the columns.render
method.
Consider for example the following simple plug-in that will truncate text after a given number of characters and show ellipsis if the string is longer that the number of characters allowed:
DataTable.render.ellipsis = function ( cutoff ) {
return function ( data, type, row ) {
if ( type === 'display' ) {
var str = data.toString(); // cast numbers
return str.length < cutoff ?
str :
str.substr(0, cutoff-1) +'…';
}
// Search, order and type can use the original data
return data;
};
};
We can then use that in our DataTables column definitions:
{
data: 'description',
render: DataTable.render.ellipsis( 10 )
}
A more comprehensive ellipsis rendering helper is available in the DataTables plug-ins repository with word break and HTML escaping control. Others will be available in the same repository as they are developed.
Contributing
If you have written a rendering helper that you would like to share with the DataTables community, first of all, thank you! Rendering helpers can be committed to the Plug-ins repository and pull requests are very welcome. Alternatively, if you don't have a GitHub account, post your code in the DataTables forums.