Version 5.3 Released!

Click to checkout the new features

Release Notes

Contributors

As part of the v5.x push to make it easier to contribute to Tabulator, there have a number of additions to the library in this release.

ES Lint

An ESLint configuration file has been added to the project source. This will allow most modern IDE's (VSCode, Sublime Text etc...) to statically analyse any code you add to Tabulator and flag whenever it deviates from the expected code formatting.

As part of this release, all the existing source has been updated to ensure conistency, it now passes all of the configured ESLint rules.

Github Pull Request Validation

When you submit a pull request to make changes in Tabulator, there are now some automated GitHub actions that will automatically run validation checks against your code to ensure it meets the ESLint code formatting requirements before it will allow the PR to be merged.

If the linter picks up an issues with submitted code, you will see the failures listed in a report at the bottom of the Conversation tab of the PR. You will need to fix each of the issues before the PR is approved for merging.

failed pr report

Spelling Review

The spelling of all words in the source code has been reviewed. This largley resulted in a lot of spelling tweaks to comment lines but has also resulted in the changing of several internal function names. This shouldn't directly affect any external API's of Tabulator, but may affect you if you have a customized fork of the library.

SCSS Variables

As part of the spelling review a number of the SCSS variable have been adjusted to their correct spelling, for a full list of changed variable names, checkout the upgrade guide.

Debug Tools

By default Tabulator provides a range of console warnings to flag to a developer that something may be wrong with the configuration of the table. In this release a couple of new setup options have been added to disabled these warnings if necessary.

Invalid Component Functions Warnings

Enabled by default, this will provide a console warning if you are trying to call a function on a component that does not exist. With the new optional modular structure this is particularly valueable as it will prompt you if you are trying to use an function on a component for a module that has not been installed

You can disable this using the debugInvalidComponentFuncs option in the table constructor:

var table = new Tabulator("#example-table", {
    debugInvalidComponentFuncs:false, //disable component function warnings
});

Deprecation Warnings

Enabled by default, this will provide a console warning if you attempt to use a setup option that has been deprecated. Where possible an alternative option may be suggested

You can disable this using the debugDeprecation option in the table constructor:

var table = new Tabulator("#example-table", {
    debugDeprecation:false, //disable deprecation warnings
});

Performance Improvements

Column Manipulation

The internal column manager has been updated to improve performance of column rendering.

Actions that result in a column being redrawn, such as toggling visibility, updating definitions adding columns and deleting columns will now function in a fraction of the time they used to, and will now take a consistent amount of time regardless of how may columns the table contains.

Redraw Blocking

The blockRedraw and restoreRedraw functions have now been updated to affect columns as well as rows. This will allow for fast manipulation of multiple columns while only triggering on redraw of the table, allowing for much faster bulk updates.

table.blockRedraw(); //block table redrawing

table.getColumns().forEach((col) => {
    col.updateDefinition({contextMenu:false}) //update the cell definition in some way
});

table.restoreRedraw(); //restore table redrawing

Row Position

The row positioning system used by the gerPosition functionality has been overhauled in this release.

In previous releases, the row posiition was calculated from the unfilterd, un-layed out data, which was fine for simple tables, but when using grouped data or data trees resulted in positions and row numbers that did not match the actual position of the row in the visible table.

In this release row position is now calculated based on a rows display position in the table, and is based only on actual rows, group headers, frozen and calculation rows are excluded from the position data to keep row numbering consistent for actual rows.

The position of each row now also reflects their row number as shown in the rownum formatter, so that there is consitentcy between the row number shown to the user and the ros position. As a result of this row positions now start at 1 instead of 0.

As a result of this rows that are not currently displayed in the table, i.e. they have been filtered out, or are part of collapsed groups or collapsed data trees, no longer have a position as they are not curently part of the display calculations. In these cases a value of false will be returned from any position function to indicate the row is not currently displayed and has no position information.

Getting a Rows Position

Get Position From Table

Use the getRowPosition function to retrieve the numerical position of a row in the table.

The first argument is the row you are looking for, it will take any of the standard row component look up options.

var position = table.getRowPosition(row); //return the position of the row in the filtered/sorted data

This function will only return the position of a row currently displayed in the table. if the row is currently filtered out or is part of a collapsed group or data tree, this will return a value of false

Get Position From Component

Use the getPosition function to retrieve the numerical position of a row in the table.

var rowPosition = row.getPosition(); //return the position of the row in the filtered/sorted data

This function will only return the position of a row currently displayed in the table. if the row is currently filtered out or is part of a collapsed group or data tree, this will return a value of false

Retreive Row By Position

You can retrieve the Row Component of a row at a given position in the table using getRowFromPosition function. By default this will return the row based in its position in all table data, including data currently filtered out of the table.

var rows = table.getRowFromPosition(5); //return 5th row in the visible table data

Watch For Position Change

You can use the watchPosition function on a Row Component to register a callback that is triggered when that rows position changes, this is particularly useful for formatters that are dependent on a rows position.

row.watchPosition((position) => {
    //position - the new position of the row    
});

Frozen Rows

The frozen rows module has had an overhaul in this release. It now offers a number of different table setup options to make freezing rows ate the top of the table really easy.

Freeze a Fixed Number of Rows

If you set the frozenRows table setup option to an integer value then that many rows of data will be frozen at the top of the table. In the example below we will freeze the first two rows of data:

var table = new Tabulator("#example-table", {
    frozenRows:2, //freeze first two rows of data
});

Freeze Rows by Field Value

You can use a combination of the frozenRows and frozenRowsField table setup options to freeze rows based on the value of a particular field in their row data.

Define the field you want to look at in the frozenRowsField option (this defaults to "id" if not set) and then set an array of values to compare against in the frozenRows option.

In the example below we will freeze any rows with a color value of "red" or "green":

var table = new Tabulator("#example-table", {
    frozenRowsField:"color", //freeze first two rows of data
    frozenRows:["red", "green"], //freeze first two rows of data
});

Freeze Rows by Function

For more advanced usage cases where you may need some custom logic to decide which rows are frozen, you can pass a function to the frozenRows option. This function will be called on each row in the table, it will be passed the Row Component for the row as its first argument and should return true if the row is to be frozen:

var table = new Tabulator("#example-table", {
    frozenRows:function(row){
        return row.getData().name.length < 10 // freeze all rows with a name less than 10 characters long
    },
});

Freeze Rows Using The Component

You can freeze a row at the top of the table by calling the freeze function on the Row Component of any row. This will insert the row above the scrolling portion of the table in the table header.

row.freeze();

A frozen row can be unfrozen using the unfreeze function on the Row Component of any row. This will remove the row from the table header and re-insert it back in the table.

row.unfreeze();

Note: Freezing or unfreezing a row will redraw the table.

Editing

Textarea Editor

A new shiftEnterSubmit option has been added to the editorParams of the textarea editor to allow submission of the value of the editor when the shift and enter keys are pressed togeather.

{title:"Example", field:"example", editor:"textarea", editorParams:{
    shiftEnterSubmit:true, //submit cell value on shift enter
}}

Date

The new date editor allows for editing of a date using a standard date type input field. This intended as a simple date picker, if you are looking for advanced date management functionality then it is recomended that you build a custom editor using an external date picker library.

{title:"Example", field:"example", editor:"date", editorParams:{
    min:"01/01/2020", // the minimum allowed value for the date picker
    max:"02/12/2022", // the maximum allowed value for the date picker
    format:"dd/MM/yyyy", // the format of the date value stored in the cell
    elementAttributes:{
        title:"slide bar to choose option" // custom tooltip
    }
}}

The editor has optional properties for the editorParams object:

  • min - the minimum value for the progress bar defaul format is yyyy-mm-dd, if the format param is used then it will expect the date in that format instead
  • max - the minimum value for the progress bar defaul format is yyyy-mm-dd, if the format param is used then it will expect the date in that format instead
  • format - the format for the date to be stored in the table. This accepts any valid Luxon format string, or the value "iso" which accept any ISO formatted data. If the input value is a luxon DateTime object then you should set this option to true. If this value param is ignored then the data should be in the format YYYY-MM-DD(this will not affect the format the user has to enter the data into the table, that is determined by the browser)
  • elementAttributes - set attributes directly on the progress holder element
< class="note"> Browser Styling
Because this editor uses the default date type input element, it is up to each browser to choose how the date picker will function and be styled, which may lead to an inconsistent look and feel. If you need consistent functionality across browsers then it recomended that you make a custom editor using an external date picker library.

Dependency Required
If you use the format param with this editor, you will need to include the luxon.js library to perform the format conversion

Time

The time editor allows for editing of a time using a standard time type input field. This intended as a simple time picker, if you are looking for advanced time management functionality then it is recomended that you build a custom editor using an external time picker library.

{title:"Example", field:"example", editor:"time", editorParams:{
    format:"hh:mm:ss", // the format of the time value stored in the cell
    elementAttributes:{
        title:"slide bar to choose option" // custom tooltip
    }
}}

The editor has optional properties for the editorParams object:

  • format - the format for the time to be stored in the table. This accepts any valid Luxon format string, or the value "iso" which accept any ISO formatted data. If the input value is a luxon DateTime object then you should set this option to true. If this value param is ignored then the data should be in the format hh:mm(this will not affect the format the user has to enter the data into the table, that is determined by the browser)
  • elementAttributes - set attributes directly on the progress holder element
< class="note"> Browser Styling
Because this editor uses the default time type input element, it is up to each browser to choose how the time picker will function and be styled, which may lead to an inconsistent look and feel. If you need consistent functionality across browsers then it recomended that you make a custom editor using an external time picker library.

Dependency Required
If you use the format param with this editor, you will need to include the luxon.js library to perform the format conversion

Date Time

The datetime editor allows for editing of a date and time using a standard datetime type input field. This intended as a simple date-time picker, if you are looking for advanced date-time management functionality then it is recomended that you build a custom editor using an external date-time picker library.

{title:"Example", field:"example", editor:"datetime", editorParams:{
    format:"dd/MM/yyyy hh:mm", // the format of the date value stored in the cell
    elementAttributes:{
        title:"slide bar to choose option" // custom tooltip
    }
}}

The editor has optional properties for the editorParams object:

  • format - the format for the date-time to be stored in the table. This accepts any valid Luxon format string, or the value "iso" which accept any ISO formatted data. If the input value is a luxon DateTime object then you should set this option to true. If this value param is ignored then the data should be in the format YYYY-MM-DDThh:mm(this will not affect the format the user has to enter the data into the table, that is determined by the browser)
  • elementAttributes - set attributes directly on the progress holder element
< class="note"> Browser Styling
Because this editor uses the default datetime-local type input element, it is up to each browser to choose how the date-time picker will function and be styled, which may lead to an inconsistent look and feel. If you need consistent functionality across browsers then it recomended that you make a custom editor using an external date-time picker library.

Dependency Required
If you use the format param with this editor, you will need to include the luxon.js library to perform the format conversion
Compatibility Warning
This editor uses the datetime-local type input element, which is not currently fully supported by the Firefox browser

Importers

Array Importer

The new array importer has been added that will allow loading of row data structured as array of row arrays, with each element in the row array representing a columns data, it is intended for use loading JavaScript arrays of arrays into the table, not JSON formatted strings.

//define some array data
var arrayData = [
  ["Name", "Age", "Likes Cheese"], //column header titles
  ["Bob", 23, true],
  ["Jim", 44, false],
]

//define table
var table = new Tabulator("#example-table", {
    data:arrayData,
    importFormat:"array",
    autoTables:true,
});

Auto Columns
If the autoColumns option is enabled on the table, then the first row of the CSV data should be the column titles.

Sorting

Custom Sort Icons

The existingheaderSortElement option can now accept a callback that is called every time a sorter is changed and allows you to set a different icon for each column sort state:

var table = new Tabulator("#table", {
    headerSortElement: function(column, dir){
        //column - column component for current column
        //dir - current sort direction ("asc", "desc", "none")

        switch(dir){
            case "asc":
                return "<i class='fas fa-sort-up'>";
            break;
            case "desc":
                return "<i class='fas fa-sort-down'>";
            break;
            default:
                return "<i class='fas fa-sort'>";
        }
    },
});

Download

Column Visibility

The download option in the column definition can now be passed a callback function that will be called when a download is started, this function is passed in the Column Component of the column and should return a boolean indicating the visibility of the column in the download.

var table = new Tabulator("#example-table", {
    columns:[
        {title:"id", field:"id", download:function(column){
            //column - column component for current column

            return true; //make column visible in download
        }} 
    ]
});

Output Encoding

The downloadReady function has been replaced in this release with a new function, downloadEncoder, that passes in more information and allows you to take direct control over the encoded output of the downloader.

The first argument of the function is the file contents returned from the downloader, the second argument is the suggested mime type for the output. The function is should return a blob of the file to be downloaded.

var table = new Tabulator("#example-table", {
    downloadEncoder:function(fileContents, mimeType){
        //fileContents - the unencoded contents of the file
        //mimeType - the suggested mime type for the output

        //custom action to send blob to server could be included here

        return new Blob([fileContents], {type:mimeType}); //must return a blob to proceed with the download, return false to abort download
    }
});

As before, if you would prefer to abort the download you can return false from this callback. This could be useful for example if you want to send the created file to a server via ajax rather than allowing the user to download the file.

Clipboard

Column Visibility

The clipboard option in the column definition can now be passed a callback function that will be called when a clipboard copy is started, this function is passed in the Column Component of the column and should return a boolean indicating the visibility of the column in the clipboard data.

var table = new Tabulator("#example-table", {
    columns:[
        {title:"id", field:"id", clipboard:function(column){
            //column - column component for current column

            return true; //make column visible in clipboard data
        }} 
    ]
});

Print

Column Visibility

The print option in the column definition can now be passed a callback function that will be called when a print is started, this function is passed in the Column Component of the column and should return a boolean indicating the visibility of the column in the printed table.

var table = new Tabulator("#example-table", {
    columns:[
        {title:"id", field:"id", print:function(column){
            //column - column component for current column

            return true; //make column visible in printed table
        }} 
    ]
});

HTML Export

Column Visibility

When xporting table data using the getHtml function, the htmlOutput option in the column definition can now be passed a callback function that will be called when the export is started, this function is passed in the Column Component of the column and should return a boolean indicating the visibility of the column in the exported table.

var table = new Tabulator("#example-table", {
    columns:[
        {title:"id", field:"id", htmlOutput:function(column){
            //column - column component for current column

            return true; //make column visible in exported table
        }} 
    ]
});

Events

Several new external events have been added in this release

Table Destroyed

When a table has been destroyed by calling the destroy function, thetableDestroyed event will triggered when all internal functionality has been destroyed and just before all external event listeners are removed from the table:

table.on("tableDestroyed", function(){});

Internal Events

Redraw Events

Several new internal events have been added to help modules handle changes to the table redraw status.

Redraw Blocking

The redraw-blocking event is a dispatch type event, that is triggered when the redrawBlock function has been called but before the column and row managers have blocked redrawing

this.subscribe("redraw-blocking", function() => {
    //do something
});

Redraw Blocked

The redraw-blocked event is a dispatch type event, that is triggered when the redrawBlock function has been called, after the column and row managers have blocked redrawing

this.subscribe("redraw-blocked", function() => {
    //do something
});

Redraw Restoring

The redraw-restoring event is a dispatch type event, that is triggered when the redrawRestore function has been called but before the column and row managers have restored redrawing

this.subscribe("redraw-restoring", function() => {
    //do something
});

Redraw Restored

The redraw-restored event is a dispatch type event, that is triggered when the redrawRestore function has been called, after the column and row managers have restored redrawing

this.subscribe("redraw-restored", function() => {
    //do something
});

Styling

New Classes

Table Editing

When a cell is being edited, the tabulator-editing class is now applied to the tables containing element along with the tabulator class. This should aid in styling the current table that is being edited if needed.

Row Editing

When a cell is being edited, the tabulator-editing is now applied to the row instead of the old tabulator-row-editing class. This class name has been changed to improve the consistency of class naming.

Editable Cells

When a cell is editable, the tabulator-editable class is now applied to the cell. this should allow for easy styling of only editable cells.

Bug Fixes

v5.3.0 Release

The following minor updates and bugfixes have been made:

  • Fixed ordering issues in the array sorter
  • Fixed issue in value filtering logic in list editor
  • The list editor now correctly highlights current values in the list when used as a header filter with the multiselect option enabled
  • The listOnEmpty option for the list editor now works correctly
  • Fixed issue with list editor loosing focus on mobile when keyboard is displayed causing page resize
  • Fixed issue with clear button in list editor not allowing access to input
  • The float and integer validators now correctly invalidate symbolic strings
  • Fixed exception thrown when exporting html with either the getHTML function or the html downloader with no style attribute set
  • The getGroups function now correctly returns an empty array after row grouping has been disabled by the setGroupBy function
  • Fixed regression in movable rows module when moving grouped rows
  • Fixed issue with recursive loop in reactive data module when the watched data array is updated
  • Frozen column and frozen row functionality can now work at the the same time without visual corruption
  • It is no longer possible to erroniously drag a movable row beyond the bottom of the table
  • Fixed layout glitch when using bottom column calculations and scrolling in rtl mode
  • Fixed regression with fitData layout mode, causing the column widths to be reset on table resize or visibility change
  • Filtering the table to 0 results while using the virtual vertical renderer will no longer incorrectly reset the horizontal scroll position
  • Fix horizontal scroll bar positioning issue when minHeight is set in table options
  • Fixed issue with progress formatter nor respecting the hozAlign column definition option
  • Fixed exception thrown when destroy function is called on table.
  • Non fixed height tables now correctly recalculate their height after render pipeline is updated
  • Fix issue with remtote mode paginated tables gaining uneeded horizontal scroll bar after data is loaded into the table from an empty state

v5.3.1 Release

The following minor updates and bugfixes have been made:

  • Fixed regression in list editor deprecated functionality check
  • Prevent list editor blur when mobile keyboard is shown
  • Removed unessisary console logging from the list editor
  • Fixed issue with column calculation updates when new row added while row grouping is enabled
  • Fixed issue with data tree row parent lookup on uninitialized rows
  • Console warning will now be displayed if a columns maxWidth is set to be smaller than its minWidth
  • Added compatibility console warning for the dataTree option and movableRows
  • Fixed issue when a grouped row is deleted when the history module is in use
  • Fixed issue with the interaction monitor not correctly identifying which column header had been clicked when using grouped columns
  • When finding a column based off its DOM element, grouped columns are now correctly traversed to find matching child columns
  • Fixed width calculation rounding issue in fitColumns layout function that resulted in horizontal scrollbar appearing
  • Double clicking on a non-editable cell now correctly selects only the contents of that cell rather than the entire row
  • fixed issue with internal render mode check not returning current render mode
  • Row group visibility toggles now function correctly with the basic vertical renderer
  • Collapsed row data is now correctly updated when row data is updated

Donate