Table component
Create interactive table with sorting, filtering and pagination features.
Create table
New in 4.2.8, updated in 4.2.23
If you need to create interactive table with ordering, filtering, searching and pagination features, you can use Metro UI table
component.
To create table
, add attribute data-role="table"
to your HTML table element and setup, if need, additional options with special attributes.
You can create table
and for your own HTML table with predefined data and for the table with remote data definition.
An important condition - is the creation of sections thead
and tbody
.
<table class="table" data-role="table">
...
</table>
Table options
You can use different options to define table behavior. This options you can use in <table>
tag definition.
Option | Data-* | Default | Desc |
check |
data-check |
false | Enable checkbox or radio for each row |
checkType |
data-check-type |
checkbox | Draw checkbox or radio for each row |
checkStyle |
data-check-style |
1 | Set style for checkbox or radio, 1 or 2 |
checkName |
data-check-name |
null | Set name for checkbox or radio |
checkColIndex |
data-check-col-index |
0 | Data column index from 0 for checkbox or radio value |
checkStoreKey |
data-store-key |
TABLE:$1:KEYS | Key for storage (used window.storage), where check value are stored. $1 will be replaced with table id. |
rownum |
data-rownum |
false | Show/hide rows numbers |
rownumTitle |
data-rownum-title |
# | Title for rownum head cell |
filters |
data-filters |
Table filters definition, comma separated value with functions names | |
filtersOperator |
data-filters-operator |
and | Defined how filters combined, value and or or |
source |
data-source |
null | Link to external data |
searchMinLength |
data-search-min-length |
1 | Min length for begin searching |
searchThreshold |
data-search-threshold |
500 | The threshold in ms to begin searching, while user press keys for search phrase and the interval between key press less than this value, searching not started |
searchFields |
data-search-fields |
Comma-separated value with column names, where will be search | |
showRowsSteps |
data-show-rows-steps |
true | Show/hide rows steps box |
showSearch |
data-show-search |
true | Show/hide search field |
showTableInfo |
data-show-table-info |
true | Show/hide table info block |
showPagination |
data-show-pagination |
true | Show/hide table pagination |
paginationShortMode |
data-pagination-short-mode |
true | Show table pagination in short mode |
showActivity |
data-show-activity |
true | Show activity for table operations |
muteTable |
data-mute-table |
true | Mute table for table operations |
rows |
data-rows |
10 | How many rows will be displayed on page, if this value is -1, all rows will be displayed |
rowsSteps |
data-rows-steps |
10, 25, 50, 100 | Steps fo rows select box |
staticView |
data-static-view |
false | If true, table always displayed as defined |
viewSaveMode |
data-view-save-mode |
client | Where table view will be saved, values: client, server |
viewSavePath |
data-view-save-path |
TABLE:$1:OPTIONS | Key for client-side, href for server-side. $1 will be replaced with table id |
decimalSeparator |
data-decimal-separator |
. (dot) | Decimal separator for numeric values. Used for right sorting |
thousandSeparator |
data-thousand-separator |
, (comma) | Thousand separator for numeric values. Used for right sorting |
tableRowsCountTitle |
data-table-rows-count-title |
Show entries: | Title for rows steps box |
tableSearchTitle |
data-table-search-title |
Search: | Title for search input |
tableInfoTitle |
data-table-info-title |
Showing $1 to $2 of $3 entries | Title for table info block |
paginationPrevTitle |
data-pagination-prev-title |
Prev | Title pagination prev button |
paginationNextTitle |
data-pagination-next-title |
Next | Title pagination next button |
allRecordsTitle |
data-all-records-title |
All | Title all records in rows steps block |
inspectorTitle |
data-inspector-title |
Inspector | Title for table inspector window |
activityType |
data-activity-type |
cycle | Activity type for long operations |
activityStyle |
data-activity-style |
color | Activity style for long operations |
activityTimeout |
data-activity-timeout |
100 | Timeout between activity show and table operation start |
cellWrapper |
data-cell-wrapper |
true | If true, cell data will be placed in div with class cell-wrapper |
horizontalScroll |
data-horizontal-scroll |
false | Helper to create table horizontal scrolling for wide table |
<table class="table striped table-border mt-4"
data-role="table"
data-rows="5"
data-rows-steps="5, 10"
data-show-activity="false"
data-source="data/table.json"
data-rownum="true"
data-check="true"
data-check-style="2"
>
</table>
Columns definition
For right works component, you must right define columns.
Columns must be defined in thead
section.
You can use any attributes to define its:
Attribute | Desc |
data-name |
Column name |
data-sortable |
Sortable column or not. Values: true , false |
data-sort-dir |
Initial sorting direction. Values: asc , desc |
data-format |
Data format helper for right sorting. Values: string (default), date , number , int , float , money |
data-format-mask |
If you data is date, and date not in ECMAScript date format, you must define data mask (see Extensions for string.toDate in this article) |
data-size |
If can define size for column. |
data-show |
If can define show or hide column. |
data-cls |
If can define additional classes for column heading cell. |
data-cls-column |
If can define additional classes for column data cells. |
<table class="table" data-role="table">
<thead>
<tr>
<th data-sortable="true" data-sort-dir="asc">Name</th>
<th data-sortable="true">Office</th>
<th data-sortable="true" data-format="number">Age</th>
<th data-sortable="true" data-format="date">Start date</th>
<th data-sortable="true" data-show="false" data-format="money">Salary</th>
</tr>
</thead>
...
</table>
Currently, you can define only one row in head section.
Data definition
Data must be defined in tbody
section.
If you want to add classes to data cell, use head cell
attribute data-cls-column
.
Name | Office | Age | Start date | Salary |
---|---|---|---|---|
Tiger Nixon | Edinburgh | 61 | 2011/04/25 | $320,800 |
Garrett Winters | Tokyo | 63 | 2011/07/25 | $170,750 |
Ashton Cox | San Francisco | 66 | 2009/01/12 | $86,000 |
Cedric Kelly | Edinburgh | 22 | 2012/03/29 | $433,060 |
Airi Satou | Tokyo | 33 | 2008/11/28 | $162,700 |
Brielle Williamson | New York | 61 | 2012/12/02 | $372,000 |
Herrod Chandler | San Francisco | 59 | 2012/08/06 | $137,500 |
Rhona Davidson | Tokyo | 55 | 2010/10/14 | $327,900 |
Colleen Hurst | San Francisco | 39 | 2009/09/15 | $205,500 |
Sonya Frost | Edinburgh | 23 | 2008/12/13 | $103,600 |
<table class="table" data-role="table">
<thead>
<tr>
<th >Name</th>
<th >Office</th>
<th data-cls-column="bg-cyan fg-white text-center">Age</th>
<th data-cls-column="bg-orange fg-white text-center" >Start date</th>
<th data-cls-column="bg-green fg-white text-right" >Salary</th>
</tr>
</thead>
<tbody>
<tr>
<td>Tiger Nixon</td>
<td>Edinburgh</td>
<td>61</td>
<td>2011/04/25</td>
<td>$320,800</td>
</tr>
...
</tbody>
</table>
Table sorting
To use sorting
, you must define columns, who can be sorted.
To create sortable column, add attribute data-sortable="true"
to head cell.
If you need to sort on this column after table init, add attribute data-sort-dir="asc|desc"
for initializing sorting direction.
If data for sortable column is a not string, you must use attribute data-format
.
If data is date and date not in ECMAScript format, you must add attribute data-format-mask
.
More about covert string to date you can read in this article
<table class="table" data-role="table">
<thead>
<tr>
<th data-sortable="true" data-sort-dir="asc">ID</th>
<th data-sortable="true">Name</th>
<th data-sortable="true" data-format="date" data-format-mask="%d-%m-%y" >Start</th>
<th data-sortable="true" data-format="int">Age</th>
<th data-sortable="true" data-format="money">Salary</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Tiger Nixon</td>
<td>Edinburgh</td>
<td>25/04/2011</td>
<td>61</td>
<td>$320,800</td>
</tr>
...
</tbody>
</table>
Table search
Table component support interactive search. To activate search function you must:
- Enable search input field with attribute
data-show-search="true"
(enabled by default) - Set min string length for search with attribute
data-search-min-length
(default: 1) - Setup threshold for start search with attribute
data-search-threshold
(default: 500)
<table class="table"
data-role="table"
data-show-search="true"
data-search-min-length="3"
data-search-threshold="300"
>
</table>
By default, all fields are searched. You can define the fields to be searched for.
To define it use attribute data-search-fields
.
Fields list is must be a comma separated string with field names, defined in head cell attribute data-name
.
<table class="table"
data-role="table"
data-show-search="true"
data-search-min-length="3"
data-search-threshold="300"
data-search-fields="name, age">
<thead>
<tr>
<th data-name="id" >ID</th>
<th data-name="name" >Name</th>
<th data-name="start" >Start</th>
<th data-name="age" >Age</th>
<th data-name="salary" >Salary</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Tiger Nixon</td>
<td>Edinburgh</td>
<td>25/04/2011</td>
<td>61</td>
<td>$320,800</td>
</tr>
...
</tbody>
</table>
Filtering
Table components contains API to create custom filters for data.
These filters
works before search
and is connected with it by the and
operator if search is not empty.
These filters are user-defined functions and can be applied in two ways: with attribute data-filters
and with table api method addFilter
.
In both cases, the functions must be defined before they are used.
Use attribute
<script>
function myFilter(row, heads){
var is_active_index = 0;
heads.forEach(function(el, i){
if (el.name === "name") {
is_active_index = i;
}
});
return row[is_active_index].includes("Jak");
}
</script>
<table class="table"
data-role="table"
data-filters="myFilter"
>
...
</table>
Use table API
<div>
<input type="checkbox" data-role="switch"
data-caption="Apply filter" onchange="toggleFilter(this.checked)">
</div>
<table class="table striped table-border mt-4" id="t-flt"
data-role="table"
data-rows="5"
data-rows-steps="5, 10"
data-source="data/table.json"
data-show-rows-steps="false"
data-show-search="false"
>
</table>
<script>
var filterIndex;
function toggleFilter(checked){
var table = $('#t-flt').data('table');
if (checked) {
filterIndex = table.addFilter(function(row, heads){
var is_active_index = 0;
heads.forEach(function(el, i){
if (el.name === "name") {
is_active_index = i;
}
});
return row[is_active_index].includes("Jak");
}, true);
} else {
table.removeFilter(filterIndex, true);
}
}
</script>
Filters operator
By default, all filters applied with operator and
.
You can set this to operator or
with attribute data-filters-operator="or"
.
<div>
<input type="checkbox" data-role="switch"
data-caption="Apply filter Jak"
onchange="toggleFilter2(this.checked)">
<input type="checkbox" data-role="switch"
data-caption="Apply filter Simon"
onchange="toggleFilter3(this.checked)">
</div>
<table class="table striped table-border mt-4" id="t-flt-2"
data-role="table"
data-rows="5"
data-rows-steps="5, 10"
data-source="data/table.json"
data-show-rows-steps="false"
data-show-search="false"
data-filters-operator="or"
>
</table>
<script>
var filterIndex2, filterIndex3;
function toggleFilter2(checked){
var table = $('#t-flt-2').data('table');
if (checked) {
filterIndex2 = table.addFilter(function(row, heads){
var is_active_index = 0;
heads.forEach(function(el, i){
if (el.name === "name") {
is_active_index = i;
}
});
return row[is_active_index].includes("Jak");
}, true);
} else {
table.removeFilter(filterIndex2, true);
}
}
function toggleFilter3(checked){
var table = $('#t-flt-2').data('table');
if (checked) {
filterIndex3 = table.addFilter(function(row, heads){
var is_active_index = 0;
heads.forEach(function(el, i){
if (el.name === "name") {
is_active_index = i;
}
});
return row[is_active_index].includes("Simon");
}, true);
} else {
table.removeFilter(filterIndex3, true);
}
}
</script>
Filters
works before search
and is connected with it by the and
operator if search is not empty.
Pagination
To use pagination option, this options must be anabled with attribute data-show-pagination="true"
(enabled by default).
By default, used pagination short mode. If you need show all pages links in pagination, you can set it with attribute data-pagination-short-mode="false"
.
Pagination short mode
<table class="table" data-role="table"
data-pagination-short-mode="true">
...
</table>
Pagination all mode
<table class="table" data-role="table"
data-pagination-short-mode="false">
...
</table>
To set title
for Previous
and Next
buttons,
use attributes data-pagination-prev-title
, data-pagination-next-title
.
Rows counter
When component works, it creates special select block before a table to set displayed table rows count.
You can change default rows counter steps with attribute data-rows-steps="..."
.
This is a comma delimiter value. To set a default rows count, use attribute data-rows="..."
To hide this block, set attribute data-show-rows-steps
to false
or define custom wrapper.
To add all rows mode, you must add -1
value to data-rows-steps
.
<table data-role="table"
data-rows-steps="-1, 5, 10, 20, 30, 100"
data-rows="5"
>
...
</table>
Table info
Table info block contains information about rows and current position in table.
To enable this feature, use attribute data-show-table-info="true"
(enabled by default).
You can change template
for table info with attribute data-table-info-title
.
By default value for this attribute is Showing $1 to $2 of $3 entries
.
Where $1
- from records, $2
- to records, $3
- total records.
<table class="table" data-role="table"
data-table-info-title="Display from $1 to $2 of $3 records"
>
</table>
Table inspector
Component table contains inside a table inspector
to manipulate columns in visual mode.
To open inspector
, you must call API method openInspector()
or toggleInspector()
, and to close it - closeInspector();
.
Table view
For each table, a view
is created, which stores information about the current state of the table.
All changes that the user makes in the table inspector are saved in this view
.
You can setup view options
with special attributes:
data-static-view="true|false"
- use static view or notdata-view-save-mode="client|server"
- how view is storeddata-view-save-path="storage_key|url"
- where view is stored
Client
<!-- $1 in save path will be replaced with table id -->
<table class="table" data-role="table"
data-view-save-mode="client"
data-view-save-path="TABLE:$1:KEYS"
>
</table>
Server
<table class="table" data-role="table"
data-view-save-mode="server"
data-view-save-path="//server.com/save_view.php"
>
</table>
View format
Object view have next format:
{
0: {index: 0, index-view: 0, show: true, size: 50}
1: {index: 1, index-view: 1, show: true, size: ""}
2: {index: 2, index-view: 2, show: true, size: 150}
3: {index: 3, index-view: 3, show: true, size: 80}
4: {index: 4, index-view: 4, show: true, size: 150}
...
}
Where index
- field index in original data,
index-view
- field index in displayed table,
show
- field displayed or not,
size
- field size.
Export table data to CSV
You can exporting table data into CSV file.
To export data, you must use API method export(to, mode, filename, options)
.
var table = $(el).data('table');
table.export('CSV', 'all', 'table-export.csv', {
csvDelimiter: "\t",
csvNewLine: "\r\n",
includeHeader: true
});
Export to...
Currently supported only CSV
target.
Export modes
all
- all table dataall-filtered
- all with applied filters and searchchecked
- checked rowsview
- rows, displayed in current page
Export options
csvDelimiter
- default\t
csvNewLine
- default\r\n
includeHeader
- defaulttrue
External data
You can create table from external JSON data.
To create it, use attribute data-source
.
<table class="table striped table-border mt-4"
data-role="table"
data-source="data/table.json"
>
</table>
External data format
To use external source, you must create JSON data in specific format. Example of JSON file.
{
header: [...],
data: [...]
}
Header
In header
, you must describe information about all table columns.
Each item can contains the next data:
name
- column namesortable
- sortable or notsortDir
- sort direction asc or descformat
- column formatcls
- classes for head cellclsColumn
- classes for data cellsize
- column sizeshow
- show or hide columntemplate
- template for cell data. Usethis.value
to manipulate with cell valuethousandSeparator
- thousand separator for numbersdecimalSeparator
- decimal separator for numbers
See this article for details about micro templating in Metro UI.
"header": [
{
"name": "id",
"title": "ID",
"size": 50,
"sortable": true,
"sortDir": "asc",
"format": "number"
},
{
"name": "name",
"title": "Name",
"sortable": true
},7
{
"name": "start",
"title": "Start",
"sortable": true,
"size": 150,
"format": "date",
"formatMask": "dd-mm-yyyy"
},
{
"name": "age",
"title": "Age",
"sortable": true,
"size": 80
},
{
"name": "salary",
"title": "Salary",
"sortable": true,
"size": 150,
"format": "money",
"show": true
}
]
Data
In data section you must put simple text or html data.
"data": [
[
1,
"Aidan",
"31-12-2017",
63,
"$7,843"
],
[
2,
"Ferris",
"13-06-2018",
28,
"$8,877"
],
[
3,
"Joseph",
"06-02-2018",
43,
"$5,645"
],
]
Events
When table works, it generates a series of events that you can use to interact with the component.
Option | Data-* | Desc |
onDraw |
data-on-draw |
Event fired when the table was drawn. |
onDrawRow |
data-on-draw-row |
Event fired when draw row. |
onDrawCell |
data-on-draw-cell |
Event fired when draw cell. |
onAppendRow |
data-on-append-row |
Event fired when row added to table. |
onAppendCell |
data-on-append-cell |
Event fired when cell added to row. |
onSortStart |
data-on-sort-start |
Event fired when sorting process stated. |
onSortStop |
data-on-sort-stop |
Event fired when sorting process stopped. |
onSortItemSwitch |
data-on-sort-item-switch |
Event fired when table rows switched on sorting process. |
onSearch(filter, items) |
data-on-search |
Event fired on search. |
onRowsCountChange(val) |
data-on-rows-count-change |
Event fired when user change rows count to display. |
onDataLoad(source) |
data-on-data-load |
Event fired before data will be loaded. |
onDataLoaded(source, response) |
data-on-data-loaded |
Event fired after data loaded. |
onDataLoadError(source, xhr, textStatus, errorThrown) |
data-on-data-load-error |
Event fired when data loads stop with error. |
onFilterRowAccepted(row) |
data-on-filter-row-accepted |
Row accepted by filters. |
onFilterRowDeclined(row) |
data-on-filter-row-declined |
Row declined by filters. |
onCheckClick() |
data-on-check-click |
|
onCheckClickAll() |
data-on-check-click-all |
|
onCheckDraw() |
data-on-check-draw |
|
onViewSave() |
data-on-view-save |
|
onViewGet() |
data-on-view-get |
|
onTableCreate(el) |
data-on-table-create |
Event fired after the table created. |
Methods
You can use table API methods to interact with it.
- draw()
- sorting(dir)
- search(val)
- loadData(source, review)
- reload(review)
- next()
- prev()
- first()
- last()
- page(num)
- addFilter(func, redraw)
- removeFilter(func_index)
- removeFilters()
- getItems()
- getHeads()
- getFilteredItems()
- getSelectedItems()
- getStoredKeys()
- clearSelected()
- clearSelected(redraw)
- getFilters()
- getFiltersIndexes()
- openInspector()
- closeInspector()
- toggleInspector()
- resetView()
- export(to, mode, filename, options)
- deleteItem(field_index, val)
- deleteItemByName(field_name, val)
- deleteItem(field_index, function(val){return true|false})
- deleteItemByName(field_name, function(val){return true|false})
Customize
You can customize style of table and its elements with next options:
clsTable | data-cls-table |
Additional class for table |
clsHead | data-cls-head |
Additional class for table head |
clsHeadRow | data-cls-head-row |
Additional class for table head row |
clsHeadCell | data-cls-head-cell |
Additional class for table head cell |
clsBody | data-cls-body |
Additional class for table body |
clsBodyRow | data-cls-body-row |
Additional class for table body row |
clsBodyCell | data-cls-body-cell |
Additional class for table body cell |
clsFooter | data-cls-footer |
Additional class for table footer |
clsFooterRow | data-cls-footer-row |
Additional class for table footer row |
clsFooterCell | data-cls-footer-cell |
Additional class for table footer cell |
clsPagination | data-cls-pagination |
Additional class for table pagination |
clsTableTop | data-cls-table-top |
Additional class for table top block |
clsTableBottom | data-cls-table-bottom |
Additional class for table bottom block |
clsTableInfo | data-cls-table-info |
Additional class for table info block |
clsTablePagination | data-cls-table-pagination |
Additional class for table pagination block |
clsRowsCount | data-cls-rows-count |
Additional class for rows count block |
clsSearch | data-cls-search |
Additional class for search block |
clsRow | data-cls-row |
Additional class for each data row |
clsRowEven | data-cls-row-even |
Additional class for even data rows |
clsRowOdd | data-cls-row-odd |
Additional class for odd data rows |
Custom elements wrappers
You can set custom wrappers for search
, rows counter
, table info
and pagination
elements.
To set it, use special named attributes:
data-search-wrapper
,
data-rows-wrapper
,
data-info-wrapper
,
data-pagination-wrapper
.
<div class="row mb-2">
<div class="cell-md-8 my-search-wrapper"></div>
<div class="cell-md-4 my-rows-wrapper"></div>
</div>
<p class="h3 text-center my-info-wrapper"></p>
<div class="d-flex flex-justify-center my-pagination-wrapper"></div>
<table class="table table-border striped"
data-role="table"
data-rows-steps="5, 10"
data-rows="5"
data-info-wrapper=".my-info-wrapper"
data-pagination-wrapper=".my-pagination-wrapper"
data-search-wrapper=".my-search-wrapper"
data-rows-wrapper=".my-rows-wrapper"
data-source="data/table.json">
</table>
<div class="d-flex flex-justify-center my-pagination-wrapper"></div>
Horizontal scroll
You can enable horizontal scrolling for wide table. To enable it, use attribute data-horizontal-scroll="true"
.
<table class="table table-border striped"
data-role="table"
data-rows-steps="-1, 5, 10"
data-rows="5"
data-horizontal-scroll="true"
data-source="data/table-wide.json">
</table>
You can stop horizontal scrolling with attribute data-horizontal-scroll-stop
.
<table class="table table-border striped"
data-role="table"
data-rows-steps="-1, 5, 10"
data-rows="5"
data-horizontal-scroll="true"
data-horizontal-scroll-stop="lg"
data-source="data/table-wide.json">
</table>