Release Notes
- Contributors
- Debug Tools
- Performance Improvements
- Row Position
- Frozen Rows
- Editing
- Importers
- Sorting
- Download
- Clipboard
- HTML Export
- Events
- Internal Events
- Styling
- Bug Fixes
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.
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 row = 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
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.
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
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.
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
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.
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 }} ] });
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, the tableDestroyed 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
v5.3.2 Release
The following minor updates and bugfixes have been made:
- Fixed issue with unresolved promise returned from updateData function when data has a length of 0
- Fixed issue with table attempting to redraw data while it is being destroyed
- Interaction events in child nested tables no longer cause an exception in the parent table when triggered
- Using the headerSortElement option with the headerSort column definition option no longer causes an exception
- Double clicking on editable cells no longer prevent editing of cell contents
- Calling the moveColumn function on the table no longer breaks column resize handle positioning
- The columnHeaderSortMulti option and the headerSortTristate column definition options now work correctly together
- Fixed issue with row display pipeline not correctly persisting first registered pipeline handler
v5.3.3 Release
The following minor updates and bugfixes have been made:
- Removed legacy display index functionality from modules
- Fixed scope issue in persistence module when tracking column definition props
- Making changes to the table now works without exception after disabling grouping by passing a value of false to the setGroupBy function
- The column headers now correctly maintain their height when only frozen columns are visible
- Table holder min-width is now correctly cleared when the empty table placeholder is removed
- Update getRows function to return an empty array when an invalid row range lookup value is used
- Fix issue with row selection on an invalid string type index causing all rows to be selected
- Striping of rows in the bootstrap themes is correctly applied when the table-striped class is applied to the table
v5.3.4 Release
The following minor updates and bugfixes have been made:
- Fixed regression in row lookup functionality that prevented the legacy value of true from returning the current rows array
- The minimum table holder width is now correctly removed even if no placeholder is set
- Minimum column header height is now correctly applied to the headers container element rather than the header element, which was hiding frozen rows
- Frozen rows are now visible on paginated tables with no height set