Datatables
Bootstrap 5 Datatables
The Datatable is a component which mix tables with advanced options like searching, sorting and pagination.
Note: Read the API tab to find all available options and advanced customization
*
*
UMD autoinits are enabled
by default. This means that you don't need to initialize
the component manually. However if you are using MDBootstrap ES format then you should pass
the required components to the initMDB
method.
Video tutorial
Basic example - HTML markup
The Datatable component can render your data in three ways. In the first one, you simply
create a HTML markup for your table nested within a div tag with a datatable
class for styling and
data-mdb-datatable-init
that initialize JS interactions tat run under the hood. You can also
customize your table by adding data-mdb-attributes to the wrapper. Some of the more
advanced options for columns, described in the
Advanced Data Structure section can be also
used by setting data-mdb-attributes directly to a th tag (f.e.
<th data-mdb-sort="false">
).
Datatable collects information from HTML markup to create a data structure - the
<table>
element will be replaced in the DOM with a different node after
component initializes.
Name | Position | Office | Age | Start date | Salary |
---|---|---|---|---|---|
Tiger Nixon | System Architect | Edinburgh | 61 | 2011/04/25 | $320,800 |
Garrett Winters | Accountant | Tokyo | 63 | 2011/07/25 | $170,750 |
Ashton Cox | Junior Technical Author | San Francisco | 66 | 2009/01/12 | $86,000 |
Cedric Kelly | Senior Javascript Developer | Edinburgh | 22 | 2012/03/29 | $433,060 |
Airi Satou | Accountant | Tokyo | 33 | 2008/11/28 | $162,700 |
Brielle Williamson | Integration Specialist | New York | 61 | 2012/12/02 | $372,000 |
Herrod Chandler | Sales Assistant | San Francisco | 59 | 2012/08/06 | $137,500 |
Rhona Davidson | Integration Specialist | Tokyo | 55 | 2010/10/14 | $327,900 |
Colleen Hurst | Javascript Developer | San Francisco | 39 | 2009/09/15 | $205,500 |
Sonya Frost | Software Engineer | Edinburgh | 23 | 2008/12/13 | $103,600 |
Jena Gaines | Office Manager | London | 30 | 2008/12/19 | $90,560 |
Quinn Flynn | Support Lead | Edinburgh | 22 | 2013/03/03 | $342,000 |
Charde Marshall | Regional Director | San Francisco | 36 | 2008/10/16 | $470,600 |
Haley Kennedy | Senior Marketing Designer | London | 43 | 2012/12/18 | $313,500 |
<div data-mdb-datatable-init class="datatable">
<table id="exampleTable">
<thead>
<tr>
<th class="th-sm">Name</th>
<th class="th-sm">Position</th>
<th class="th-sm">Office</th>
<th class="th-sm">Age</th>
<th class="th-sm">Start date</th>
<th class="th-sm">Salary</th>
</tr>
</thead>
<tbody>
<tr>
<td>Tiger Nixon</td>
<td>System Architect</td>
<td>Edinburgh</td>
<td>61</td>
<td>2011/04/25</td>
<td>$320,800</td>
</tr>
<tr>
<td>Garrett Winters</td>
<td>Accountant</td>
<td>Tokyo</td>
<td>63</td>
<td>2011/07/25</td>
<td>$170,750</td>
</tr>
<tr>
<td>Ashton Cox</td>
<td>Junior Technical Author</td>
<td>San Francisco</td>
<td>66</td>
<td>2009/01/12</td>
<td>$86,000</td>
</tr>
<tr>
<td>Cedric Kelly</td>
<td>Senior Javascript Developer</td>
<td>Edinburgh</td>
<td>22</td>
<td>2012/03/29</td>
<td>$433,060</td>
</tr>
<tr>
<td>Airi Satou</td>
<td>Accountant</td>
<td>Tokyo</td>
<td>33</td>
<td>2008/11/28</td>
<td>$162,700</td>
</tr>
<tr>
<td>Brielle Williamson</td>
<td>Integration Specialist</td>
<td>New York</td>
<td>61</td>
<td>2012/12/02</td>
<td>$372,000</td>
</tr>
<tr>
<td>Herrod Chandler</td>
<td>Sales Assistant</td>
<td>San Francisco</td>
<td>59</td>
<td>2012/08/06</td>
<td>$137,500</td>
</tr>
<tr>
<td>Rhona Davidson</td>
<td>Integration Specialist</td>
<td>Tokyo</td>
<td>55</td>
<td>2010/10/14</td>
<td>$327,900</td>
</tr>
<tr>
<td>Colleen Hurst</td>
<td>Javascript Developer</td>
<td>San Francisco</td>
<td>39</td>
<td>2009/09/15</td>
<td>$205,500</td>
</tr>
<tr>
<td>Sonya Frost</td>
<td>Software Engineer</td>
<td>Edinburgh</td>
<td>23</td>
<td>2008/12/13</td>
<td>$103,600</td>
</tr>
<tr>
<td>Jena Gaines</td>
<td>Office Manager</td>
<td>London</td>
<td>30</td>
<td>2008/12/19</td>
<td>$90,560</td>
</tr>
<tr>
<td>Quinn Flynn</td>
<td>Support Lead</td>
<td>Edinburgh</td>
<td>22</td>
<td>2013/03/03</td>
<td>$342,000</td>
</tr>
<tr>
<td>Charde Marshall</td>
<td>Regional Director</td>
<td>San Francisco</td>
<td>36</td>
<td>2008/10/16</td>
<td>$470,600</td>
</tr>
<tr>
<td>Haley Kennedy</td>
<td>Senior Marketing Designer</td>
<td>London</td>
<td>43</td>
<td>2012/12/18</td>
<td>$313,500</td>
</tr>
</tbody>
</table>
</div>
// Initialization for ES Users
import { Datatable, initMDB } from "mdb-ui-kit";
initMDB({ Datatable });
Need even more robust tables? Try Data Den.
- Quick customization & hyper-focus on data management
- Easily integrate it with any project (not only MDB)
- Column Pinning, Drag&Drop Columns, Advanced Filtering & much more
For enterprise projects & users seeking advanced data controls. Tailor your data your way.
Basic data structure
The second option is a very basic data structure, where columns are represented by an array of strings and so is each row. The table will match each string in a row to a corresponding index in a columns array. This data structure, as it's based on indexes, not key-value pairs, can be easily used for displaying data from the CSV format.
<div id="datatable"></div>
// Initialization for ES Users
import { Datatable, initMDB } from "mdb-ui-kit";
initMDB({ Datatable });
const basicData = {
columns: ['Name', 'Position', 'Office', 'Age', 'Start date', 'Salary'],
rows: [
["Tiger Nixon", "System Architect", "Edinburgh", "61", "2011/04/25", "$320,800"],
["Garrett Winters", "Accountant", "Tokyo", "63", "2011/07/25", "$170,750"],
["Ashton Cox", "Junior Technical Author", "San Francisco", "66", "2009/01/12", "$86,000"],
["Cedric Kelly", "Senior Javascript Developer", "Edinburgh", "22", "2012/03/29", "$433,060"],
["Airi Satou", "Accountant", "Tokyo", "33", "2008/11/28", "$162,700"],
["Brielle Williamson", "Integration Specialist", "New York", "61", "2012/12/02", "$372,000"],
["Herrod Chandler", "Sales Assistant", "San Francisco", "59", "2012/08/06", "$137,500"],
["Rhona Davidson", "Integration Specialist", "Tokyo", "55", "2010/10/14", "$327,900"],
["Colleen Hurst", "Javascript Developer", "San Francisco", "39", "2009/09/15", "$205,500"],
["Sonya Frost", "Software Engineer", "Edinburgh", "23", "2008/12/13", "$103,600"],
["Jena Gaines", "Office Manager", "London", "30", "2008/12/19", "$90,560"],
["Quinn Flynn", "Support Lead", "Edinburgh", "22", "2013/03/03", "$342,000"],
["Charde Marshall", "Regional Director", "San Francisco", "36", "2008/10/16", "$470,600"],
["Haley Kennedy", "Senior Marketing Designer", "London", "43", "2012/12/18", "$313,500"]
],
};
new Datatable(document.getElementById('datatable'), basicData)
const basicData = {
columns: ['Name', 'Position', 'Office', 'Age', 'Start date', 'Salary'],
rows: [
["Tiger Nixon", "System Architect", "Edinburgh", "61", "2011/04/25", "$320,800"],
["Garrett Winters", "Accountant", "Tokyo", "63", "2011/07/25", "$170,750"],
["Ashton Cox", "Junior Technical Author", "San Francisco", "66", "2009/01/12", "$86,000"],
["Cedric Kelly", "Senior Javascript Developer", "Edinburgh", "22", "2012/03/29", "$433,060"],
["Airi Satou", "Accountant", "Tokyo", "33", "2008/11/28", "$162,700"],
["Brielle Williamson", "Integration Specialist", "New York", "61", "2012/12/02", "$372,000"],
["Herrod Chandler", "Sales Assistant", "San Francisco", "59", "2012/08/06", "$137,500"],
["Rhona Davidson", "Integration Specialist", "Tokyo", "55", "2010/10/14", "$327,900"],
["Colleen Hurst", "Javascript Developer", "San Francisco", "39", "2009/09/15", "$205,500"],
["Sonya Frost", "Software Engineer", "Edinburgh", "23", "2008/12/13", "$103,600"],
["Jena Gaines", "Office Manager", "London", "30", "2008/12/19", "$90,560"],
["Quinn Flynn", "Support Lead", "Edinburgh", "22", "2013/03/03", "$342,000"],
["Charde Marshall", "Regional Director", "San Francisco", "36", "2008/10/16", "$470,600"],
["Haley Kennedy", "Senior Marketing Designer", "London", "43", "2012/12/18", "$313,500"]
],
};
new mdb.Datatable(document.getElementById('datatable'), basicData)
Advanced data structure
The last and most advanced data structure allows customizing each column (sort, width, fixed, field) and matches values from each row to a column in which the `field` equals to a given key value. This data format can be easily used to display JSON data.
You can also use a mixed version, where columns are an array of object and each row is an array of strings.
<div id="datatable"></div>
// Initialization for ES Users
import { Datatable, initMDB } from "mdb-ui-kit";
initMDB({ Datatable });
const advancedData = {
columns: [
{ label: 'Name', field: 'name', sort: true },
{ label: 'Position', field: 'position', sort: false },
{ label: 'Office', field: 'office', sort: false },
{ label: 'Age', field: 'age', sort: false },
{ label: 'Start date', field: 'date', sort: true },
{ label: 'Salary', field: 'salary', sort: false },
],
rows: [
{ name: "Tiger Nixon", position: "System Architect", office: "Edinburgh", age: 61, date: "2011/04/25", salary: "$320,800" },
{ name: "Garrett Winters", position: "Accountant", office: "Tokyo", age: 63, date: "2011/07/25", salary: "$170,750" },
{ name: "Ashton Cox", position: "Junior Technical Author", office: "San Francisco", age: 66, date: "2009/01/12", salary: "$86,000" },
{ name: "Cedric Kelly", position: "Senior Javascript Developer", office: "Edinburgh", age: 22, date: "2012/03/29", salary: "$433,060" },
{ name: "Airi Satou", position: "Accountant", office: "Tokyo", age: 33, date: "2008/11/28", salary: "$162,700" },
{ name: "Brielle Williamson", position: "Integration Specialist", office: "New York", age: 61, date: "2012/12/02", salary: "$372,000" },
{ name: "Herrod Chandler", position: "Sales Assistant", office: "San Francisco", age: 59, date: "2012/08/06", salary: "$137,500" },
{ name: "Rhona Davidson", position: "Integration Specialist", office: "Tokyo", age: 55, date: "2010/10/14", salary: "$327,900" },
{ name: "Colleen Hurst", position: "Javascript Developer", office: "San Francisco", age: 39, date: "2009/09/15", salary: "$205,500" },
{ name: "Sonya Frost", position: "Software Engineer", office: "Edinburgh", age: 23, date: "2008/12/13", salary: "$103,600" },
{ name: "Jena Gaines", position: "Office Manager", office: "London", age: 30, date: "2008/12/19", salary: "$90,560" },
{ name: "Quinn Flynn", position: "Support Lead", office: "Edinburgh", age: 22, date: "2013/03/03", salary: "$342,000" },
{ name: "Charde Marshall", position: "Regional Director", office: "San Francisco", age: 36, date: "2008/10/16", salary: "$470,600" },
{ name: "Haley Kennedy", position: "Senior Marketing Designer", office: "London", age: 43, date: "2012/12/18", salary: "$313,500" }
],
};
new Datatable(document.getElementById('datatable'), advancedData)
const advancedData = {
columns: [
{ label: 'Name', field: 'name', sort: true },
{ label: 'Position', field: 'position', sort: false },
{ label: 'Office', field: 'office', sort: false },
{ label: 'Age', field: 'age', sort: false },
{ label: 'Start date', field: 'date', sort: true },
{ label: 'Salary', field: 'salary', sort: false },
],
rows: [
{ name: "Tiger Nixon", position: "System Architect", office: "Edinburgh", age: 61, date: "2011/04/25", salary: "$320,800" },
{ name: "Garrett Winters", position: "Accountant", office: "Tokyo", age: 63, date: "2011/07/25", salary: "$170,750" },
{ name: "Ashton Cox", position: "Junior Technical Author", office: "San Francisco", age: 66, date: "2009/01/12", salary: "$86,000" },
{ name: "Cedric Kelly", position: "Senior Javascript Developer", office: "Edinburgh", age: 22, date: "2012/03/29", salary: "$433,060" },
{ name: "Airi Satou", position: "Accountant", office: "Tokyo", age: 33, date: "2008/11/28", salary: "$162,700" },
{ name: "Brielle Williamson", position: "Integration Specialist", office: "New York", age: 61, date: "2012/12/02", salary: "$372,000" },
{ name: "Herrod Chandler", position: "Sales Assistant", office: "San Francisco", age: 59, date: "2012/08/06", salary: "$137,500" },
{ name: "Rhona Davidson", position: "Integration Specialist", office: "Tokyo", age: 55, date: "2010/10/14", salary: "$327,900" },
{ name: "Colleen Hurst", position: "Javascript Developer", office: "San Francisco", age: 39, date: "2009/09/15", salary: "$205,500" },
{ name: "Sonya Frost", position: "Software Engineer", office: "Edinburgh", age: 23, date: "2008/12/13", salary: "$103,600" },
{ name: "Jena Gaines", position: "Office Manager", office: "London", age: 30, date: "2008/12/19", salary: "$90,560" },
{ name: "Quinn Flynn", position: "Support Lead", office: "Edinburgh", age: 22, date: "2013/03/03", salary: "$342,000" },
{ name: "Charde Marshall", position: "Regional Director", office: "San Francisco", age: 36, date: "2008/10/16", salary: "$470,600" },
{ name: "Haley Kennedy", position: "Senior Marketing Designer", office: "London", age: 43, date: "2012/12/18", salary: "$313,500" }
],
};
new mdb.Datatable(document.getElementById('datatable'), advancedData)
Search
The search field is not a part of the Datatable - place an input field on your page and use
.search()
method to filter entries.
<div data-mdb-input-init class="form-outline mb-4">
<input type="text" class="form-control" id="datatable-search-input" />
<label class="form-label" for="datatable-search-input">Search</label>
</div>
<div id="datatable">
</div>
// Initialization for ES Users
import { Datatable, Input, initMDB } from "mdb-ui-kit";
initMDB({ Datatable, Input });
const data = {
columns: [
{
label: 'Name',
field: 'name'
},
'Position',
'Office',
'Age',
'Start date',
'Salary',
],
rows: [
["Tiger Nixon", "System Architect", "Edinburgh", "61", "2011/04/25", "$320,800"],
["Garrett Winters", "Accountant", "Tokyo", "63", "2011/07/25", "$170,750"],
["Ashton Cox", "Junior Technical Author", "San Francisco", "66", "2009/01/12", "$86,000"],
["Cedric Kelly", "Senior Javascript Developer", "Edinburgh", "22", "2012/03/29", "$433,060"],
["Airi Satou", "Accountant", "Tokyo", "33", "2008/11/28", "$162,700"],
["Brielle Williamson", "Integration Specialist", "New York", "61", "2012/12/02", "$372,000"],
["Herrod Chandler", "Sales Assistant", "San Francisco", "59", "2012/08/06", "$137,500"],
["Rhona Davidson", "Integration Specialist", "Tokyo", "55", "2010/10/14", "$327,900"],
["Colleen Hurst", "Javascript Developer", "San Francisco", "39", "2009/09/15", "$205,500"],
["Sonya Frost", "Software Engineer", "Edinburgh", "23", "2008/12/13", "$103,600"],
["Jena Gaines", "Office Manager", "London", "30", "2008/12/19", "$90,560"],
["Quinn Flynn", "Support Lead", "Edinburgh", "22", "2013/03/03", "$342,000"],
["Charde Marshall", "Regional Director", "San Francisco", "36", "2008/10/16", "$470,600"],
["Haley Kennedy", "Senior Marketing Designer", "London", "43", "2012/12/18", "$313,500"]
],
};
const instance = new Datatable(document.getElementById('datatable'), data)
document.getElementById('datatable-search-input').addEventListener('input', (e) => {
instance.search(e.target.value);
});
const data = {
columns: [
{
label: 'Name',
field: 'name'
},
'Position',
'Office',
'Age',
'Start date',
'Salary',
],
rows: [
["Tiger Nixon", "System Architect", "Edinburgh", "61", "2011/04/25", "$320,800"],
["Garrett Winters", "Accountant", "Tokyo", "63", "2011/07/25", "$170,750"],
["Ashton Cox", "Junior Technical Author", "San Francisco", "66", "2009/01/12", "$86,000"],
["Cedric Kelly", "Senior Javascript Developer", "Edinburgh", "22", "2012/03/29", "$433,060"],
["Airi Satou", "Accountant", "Tokyo", "33", "2008/11/28", "$162,700"],
["Brielle Williamson", "Integration Specialist", "New York", "61", "2012/12/02", "$372,000"],
["Herrod Chandler", "Sales Assistant", "San Francisco", "59", "2012/08/06", "$137,500"],
["Rhona Davidson", "Integration Specialist", "Tokyo", "55", "2010/10/14", "$327,900"],
["Colleen Hurst", "Javascript Developer", "San Francisco", "39", "2009/09/15", "$205,500"],
["Sonya Frost", "Software Engineer", "Edinburgh", "23", "2008/12/13", "$103,600"],
["Jena Gaines", "Office Manager", "London", "30", "2008/12/19", "$90,560"],
["Quinn Flynn", "Support Lead", "Edinburgh", "22", "2013/03/03", "$342,000"],
["Charde Marshall", "Regional Director", "San Francisco", "36", "2008/10/16", "$470,600"],
["Haley Kennedy", "Senior Marketing Designer", "London", "43", "2012/12/18", "$313,500"]
],
};
const instance = new mdb.Datatable(document.getElementById('datatable'), data)
document.getElementById('datatable-search-input').addEventListener('input', (e) => {
instance.search(e.target.value);
});
Advanced search
When using the searching method, you can specify which columns it should take under consideration - pass as a second argument a field (or array of fields). By default, searching will apply to all columns.
<div class="input-group mb-4">
<input type="text" class="form-control" id="advanced-search-input" placeholder="phrase in:column1,column2" />
<button data-mdb-ripple-init class="btn btn-primary" id="advanced-search-button" type="button">
<i class="fa fa-search"></i>
</button>
</div>
<div id="datatable"></div>
// Initialization for ES Users
import { Datatable, Ripple, initMDB } from "mdb-ui-kit";
initMDB({ Datatable, Ripple });
const data = {
columns: [
{
label: 'Name',
field: 'name'
},
'Position',
'Office',
'Age',
'Start date',
'Salary',
],
rows: [
["Tiger Nixon", "System Architect", "Edinburgh", "61", "2011/04/25", "$320,800"],
["Garrett Winters", "Accountant", "Tokyo", "63", "2011/07/25", "$170,750"],
["Ashton Cox", "Junior Technical Author", "San Francisco", "66", "2009/01/12", "$86,000"],
["Cedric Kelly", "Senior Javascript Developer", "Edinburgh", "22", "2012/03/29", "$433,060"],
["Airi Satou", "Accountant", "Tokyo", "33", "2008/11/28", "$162,700"],
["Brielle Williamson", "Integration Specialist", "New York", "61", "2012/12/02", "$372,000"],
["Herrod Chandler", "Sales Assistant", "San Francisco", "59", "2012/08/06", "$137,500"],
["Rhona Davidson", "Integration Specialist", "Tokyo", "55", "2010/10/14", "$327,900"],
["Colleen Hurst", "Javascript Developer", "San Francisco", "39", "2009/09/15", "$205,500"],
["Sonya Frost", "Software Engineer", "Edinburgh", "23", "2008/12/13", "$103,600"],
["Jena Gaines", "Office Manager", "London", "30", "2008/12/19", "$90,560"],
["Quinn Flynn", "Support Lead", "Edinburgh", "22", "2013/03/03", "$342,000"],
["Charde Marshall", "Regional Director", "San Francisco", "36", "2008/10/16", "$470,600"],
["Haley Kennedy", "Senior Marketing Designer", "London", "43", "2012/12/18", "$313,500"]
],
};
const instance = new Datatable(document.getElementById('datatable'), data)
const advancedSearchInput = document.getElementById('advanced-search-input');
const search = (value) => {
let [phrase, columns] = value.split(' in:').map((str) => str.trim());
if (columns) {
columns = columns.split(',').map((str) => str.toLowerCase().trim());
}
instance.search(phrase, columns);
}
document.getElementById('advanced-search-button').addEventListener('click', (e) => {
search(advancedSearchInput.value)
});
advancedSearchInput.addEventListener('keydown', (e) => {
if (e.keyCode === 13) {
search(e.target.value);
}
})
const data = {
columns: [
{
label: 'Name',
field: 'name'
},
'Position',
'Office',
'Age',
'Start date',
'Salary',
],
rows: [
["Tiger Nixon", "System Architect", "Edinburgh", "61", "2011/04/25", "$320,800"],
["Garrett Winters", "Accountant", "Tokyo", "63", "2011/07/25", "$170,750"],
["Ashton Cox", "Junior Technical Author", "San Francisco", "66", "2009/01/12", "$86,000"],
["Cedric Kelly", "Senior Javascript Developer", "Edinburgh", "22", "2012/03/29", "$433,060"],
["Airi Satou", "Accountant", "Tokyo", "33", "2008/11/28", "$162,700"],
["Brielle Williamson", "Integration Specialist", "New York", "61", "2012/12/02", "$372,000"],
["Herrod Chandler", "Sales Assistant", "San Francisco", "59", "2012/08/06", "$137,500"],
["Rhona Davidson", "Integration Specialist", "Tokyo", "55", "2010/10/14", "$327,900"],
["Colleen Hurst", "Javascript Developer", "San Francisco", "39", "2009/09/15", "$205,500"],
["Sonya Frost", "Software Engineer", "Edinburgh", "23", "2008/12/13", "$103,600"],
["Jena Gaines", "Office Manager", "London", "30", "2008/12/19", "$90,560"],
["Quinn Flynn", "Support Lead", "Edinburgh", "22", "2013/03/03", "$342,000"],
["Charde Marshall", "Regional Director", "San Francisco", "36", "2008/10/16", "$470,600"],
["Haley Kennedy", "Senior Marketing Designer", "London", "43", "2012/12/18", "$313,500"]
],
};
const instance = new mdb.Datatable(document.getElementById('datatable'), data)
const advancedSearchInput = document.getElementById('advanced-search-input');
const search = (value) => {
let [phrase, columns] = value.split(' in:').map((str) => str.trim());
if (columns) {
columns = columns.split(',').map((str) => str.toLowerCase().trim());
}
instance.search(phrase, columns);
}
document.getElementById('advanced-search-button').addEventListener('click', (e) => {
search(advancedSearchInput.value)
});
advancedSearchInput.addEventListener('keydown', (e) => {
if (e.keyCode === 13) {
search(e.target.value);
}
})
Selectable rows
When the selectable option is set to true
, user can interact with your table by
selecting rows - you can get the selected rows by listening to the
rowSelected.mdb.datatable
event.
<div id="datatable" data-mdb-selectable="true" data-mdb-multi="true"></div>
// Initialization for ES Users
import { Datatable, initMDB } from "mdb-ui-kit";
initMDB({ Datatable });
const basicData = {
columns: ['Name', 'Position', 'Office', 'Age', 'Start date', 'Salary'],
rows: [
["Tiger Nixon", "System Architect", "Edinburgh", "61", "2011/04/25", "$320,800"],
["Garrett Winters", "Accountant", "Tokyo", "63", "2011/07/25", "$170,750"],
["Ashton Cox", "Junior Technical Author", "San Francisco", "66", "2009/01/12", "$86,000"],
["Cedric Kelly", "Senior Javascript Developer", "Edinburgh", "22", "2012/03/29", "$433,060"],
["Airi Satou", "Accountant", "Tokyo", "33", "2008/11/28", "$162,700"],
["Brielle Williamson", "Integration Specialist", "New York", "61", "2012/12/02", "$372,000"],
["Herrod Chandler", "Sales Assistant", "San Francisco", "59", "2012/08/06", "$137,500"],
["Rhona Davidson", "Integration Specialist", "Tokyo", "55", "2010/10/14", "$327,900"],
["Colleen Hurst", "Javascript Developer", "San Francisco", "39", "2009/09/15", "$205,500"],
["Sonya Frost", "Software Engineer", "Edinburgh", "23", "2008/12/13", "$103,600"],
["Jena Gaines", "Office Manager", "London", "30", "2008/12/19", "$90,560"],
["Quinn Flynn", "Support Lead", "Edinburgh", "22", "2013/03/03", "$342,000"],
["Charde Marshall", "Regional Director", "San Francisco", "36", "2008/10/16", "$470,600"],
["Haley Kennedy", "Senior Marketing Designer", "London", "43", "2012/12/18", "$313,500"]
],
};
const datatable = document.getElementById('datatable');
new mdb.Datatable(datatable, basicData);
datatable.addEventListener('rowSelected.mdb.datatable', (e) => {
console.log(e.selectedRows, e.selectedIndexes, e.allSelected);
})
const basicData = {
columns: ['Name', 'Position', 'Office', 'Age', 'Start date', 'Salary'],
rows: [
["Tiger Nixon", "System Architect", "Edinburgh", "61", "2011/04/25", "$320,800"],
["Garrett Winters", "Accountant", "Tokyo", "63", "2011/07/25", "$170,750"],
["Ashton Cox", "Junior Technical Author", "San Francisco", "66", "2009/01/12", "$86,000"],
["Cedric Kelly", "Senior Javascript Developer", "Edinburgh", "22", "2012/03/29", "$433,060"],
["Airi Satou", "Accountant", "Tokyo", "33", "2008/11/28", "$162,700"],
["Brielle Williamson", "Integration Specialist", "New York", "61", "2012/12/02", "$372,000"],
["Herrod Chandler", "Sales Assistant", "San Francisco", "59", "2012/08/06", "$137,500"],
["Rhona Davidson", "Integration Specialist", "Tokyo", "55", "2010/10/14", "$327,900"],
["Colleen Hurst", "Javascript Developer", "San Francisco", "39", "2009/09/15", "$205,500"],
["Sonya Frost", "Software Engineer", "Edinburgh", "23", "2008/12/13", "$103,600"],
["Jena Gaines", "Office Manager", "London", "30", "2008/12/19", "$90,560"],
["Quinn Flynn", "Support Lead", "Edinburgh", "22", "2013/03/03", "$342,000"],
["Charde Marshall", "Regional Director", "San Francisco", "36", "2008/10/16", "$470,600"],
["Haley Kennedy", "Senior Marketing Designer", "London", "43", "2012/12/18", "$313,500"]
],
};
const datatable = document.getElementById('datatable');
new mdb.Datatable(datatable, basicData);
datatable.addEventListener('rowSelected.mdb.datatable', (e) => {
console.log(e.selectedRows, e.selectedIndexes, e.allSelected);
})
Scroll
Setting maximum height/width will enable vertical/horizontal scrolling.
<div id="datatable" data-mdb-max-height="520" data-mdb-max-width="520"></div>
// Initialization for ES Users
import { Datatable, initMDB } from "mdb-ui-kit";
initMDB({ Datatable });
const basicData = {
columns: ['Name', 'Position', 'Office', 'Age', 'Start date', 'Salary'],
rows: [
["Tiger Nixon", "System Architect", "Edinburgh", "61", "2011/04/25", "$320,800"],
["Garrett Winters", "Accountant", "Tokyo", "63", "2011/07/25", "$170,750"],
["Ashton Cox", "Junior Technical Author", "San Francisco", "66", "2009/01/12", "$86,000"],
["Cedric Kelly", "Senior Javascript Developer", "Edinburgh", "22", "2012/03/29", "$433,060"],
["Airi Satou", "Accountant", "Tokyo", "33", "2008/11/28", "$162,700"],
["Brielle Williamson", "Integration Specialist", "New York", "61", "2012/12/02", "$372,000"],
["Herrod Chandler", "Sales Assistant", "San Francisco", "59", "2012/08/06", "$137,500"],
["Rhona Davidson", "Integration Specialist", "Tokyo", "55", "2010/10/14", "$327,900"],
["Colleen Hurst", "Javascript Developer", "San Francisco", "39", "2009/09/15", "$205,500"],
["Sonya Frost", "Software Engineer", "Edinburgh", "23", "2008/12/13", "$103,600"],
["Jena Gaines", "Office Manager", "London", "30", "2008/12/19", "$90,560"],
["Quinn Flynn", "Support Lead", "Edinburgh", "22", "2013/03/03", "$342,000"],
["Charde Marshall", "Regional Director", "San Francisco", "36", "2008/10/16", "$470,600"],
["Haley Kennedy", "Senior Marketing Designer", "London", "43", "2012/12/18", "$313,500"]
],
};
const datatable = document.getElementById('datatable');
new Datatable(datatable, basicData);
const basicData = {
columns: ['Name', 'Position', 'Office', 'Age', 'Start date', 'Salary'],
rows: [
["Tiger Nixon", "System Architect", "Edinburgh", "61", "2011/04/25", "$320,800"],
["Garrett Winters", "Accountant", "Tokyo", "63", "2011/07/25", "$170,750"],
["Ashton Cox", "Junior Technical Author", "San Francisco", "66", "2009/01/12", "$86,000"],
["Cedric Kelly", "Senior Javascript Developer", "Edinburgh", "22", "2012/03/29", "$433,060"],
["Airi Satou", "Accountant", "Tokyo", "33", "2008/11/28", "$162,700"],
["Brielle Williamson", "Integration Specialist", "New York", "61", "2012/12/02", "$372,000"],
["Herrod Chandler", "Sales Assistant", "San Francisco", "59", "2012/08/06", "$137,500"],
["Rhona Davidson", "Integration Specialist", "Tokyo", "55", "2010/10/14", "$327,900"],
["Colleen Hurst", "Javascript Developer", "San Francisco", "39", "2009/09/15", "$205,500"],
["Sonya Frost", "Software Engineer", "Edinburgh", "23", "2008/12/13", "$103,600"],
["Jena Gaines", "Office Manager", "London", "30", "2008/12/19", "$90,560"],
["Quinn Flynn", "Support Lead", "Edinburgh", "22", "2013/03/03", "$342,000"],
["Charde Marshall", "Regional Director", "San Francisco", "36", "2008/10/16", "$470,600"],
["Haley Kennedy", "Senior Marketing Designer", "London", "43", "2012/12/18", "$313,500"]
],
};
const datatable = document.getElementById('datatable');
new mdb.Datatable(datatable, basicData);
Fixed header
Use the fixedHeader
option to ensure that a table's header is always visible
while scrolling.
<div id="datatable" data-mdb-max-height="460" data-mdb-fixed-header="true"></div>
// Initialization for ES Users
import { Datatable, initMDB } from "mdb-ui-kit";
initMDB({ Datatable });
const basicData = {
columns: ['Name', 'Position', 'Office', 'Age', 'Start date', 'Salary'],
rows: [
["Tiger Nixon", "System Architect", "Edinburgh", "61", "2011/04/25", "$320,800"],
["Garrett Winters", "Accountant", "Tokyo", "63", "2011/07/25", "$170,750"],
["Ashton Cox", "Junior Technical Author", "San Francisco", "66", "2009/01/12", "$86,000"],
["Cedric Kelly", "Senior Javascript Developer", "Edinburgh", "22", "2012/03/29", "$433,060"],
["Airi Satou", "Accountant", "Tokyo", "33", "2008/11/28", "$162,700"],
["Brielle Williamson", "Integration Specialist", "New York", "61", "2012/12/02", "$372,000"],
["Herrod Chandler", "Sales Assistant", "San Francisco", "59", "2012/08/06", "$137,500"],
["Rhona Davidson", "Integration Specialist", "Tokyo", "55", "2010/10/14", "$327,900"],
["Colleen Hurst", "Javascript Developer", "San Francisco", "39", "2009/09/15", "$205,500"],
["Sonya Frost", "Software Engineer", "Edinburgh", "23", "2008/12/13", "$103,600"],
["Jena Gaines", "Office Manager", "London", "30", "2008/12/19", "$90,560"],
["Quinn Flynn", "Support Lead", "Edinburgh", "22", "2013/03/03", "$342,000"],
["Charde Marshall", "Regional Director", "San Francisco", "36", "2008/10/16", "$470,600"],
["Haley Kennedy", "Senior Marketing Designer", "London", "43", "2012/12/18", "$313,500"]
],
};
const datatable = document.getElementById('datatable');
new Datatable(datatable, basicData);
const basicData = {
columns: ['Name', 'Position', 'Office', 'Age', 'Start date', 'Salary'],
rows: [
["Tiger Nixon", "System Architect", "Edinburgh", "61", "2011/04/25", "$320,800"],
["Garrett Winters", "Accountant", "Tokyo", "63", "2011/07/25", "$170,750"],
["Ashton Cox", "Junior Technical Author", "San Francisco", "66", "2009/01/12", "$86,000"],
["Cedric Kelly", "Senior Javascript Developer", "Edinburgh", "22", "2012/03/29", "$433,060"],
["Airi Satou", "Accountant", "Tokyo", "33", "2008/11/28", "$162,700"],
["Brielle Williamson", "Integration Specialist", "New York", "61", "2012/12/02", "$372,000"],
["Herrod Chandler", "Sales Assistant", "San Francisco", "59", "2012/08/06", "$137,500"],
["Rhona Davidson", "Integration Specialist", "Tokyo", "55", "2010/10/14", "$327,900"],
["Colleen Hurst", "Javascript Developer", "San Francisco", "39", "2009/09/15", "$205,500"],
["Sonya Frost", "Software Engineer", "Edinburgh", "23", "2008/12/13", "$103,600"],
["Jena Gaines", "Office Manager", "London", "30", "2008/12/19", "$90,560"],
["Quinn Flynn", "Support Lead", "Edinburgh", "22", "2013/03/03", "$342,000"],
["Charde Marshall", "Regional Director", "San Francisco", "36", "2008/10/16", "$470,600"],
["Haley Kennedy", "Senior Marketing Designer", "London", "43", "2012/12/18", "$313,500"]
],
};
const datatable = document.getElementById('datatable');
new mdb.Datatable(datatable, basicData);
Fixed columns
Making a column sticky requires setting two options - width
and fixed
. A first option is a
number of pixels, while the other one can be either a
true
( in which case the column will stick on the left) or a string
right
.
Using fixed columns in a vertically scrollable table, requires setting an option
fixedHeader
to true
as well.
When using a HTML markup instead of a data structure you can still use this feature by setting
data-mdb-width
and data-mdb-fixed
attributes on your th tags.
<div id="datatable"></div>
// Initialization for ES Users
import { Datatable, initMDB } from "mdb-ui-kit";
initMDB({ Datatable });
const basicData = {
columns: [
{ label: 'Name', field: 'name', sort: true, width: 200, fixed: true },
{ label: 'Position', field: 'position', sort: false, width: 200 },
{ label: 'Office', field: 'office', sort: false, width: 200, fixed: true },
{ label: 'Age', field: 'age', sort: false, width: 200 },
{ label: 'Start date', field: 'date', sort: true, width: 200 },
{ label: 'Salary', field: 'salary', sort: false, width: 200, fixed: 'right' },
],
rows: [
["Tiger Nixon", "System Architect", "Edinburgh", "61", "2011/04/25", "$320,800"],
["Garrett Winters", "Accountant", "Tokyo", "63", "2011/07/25", "$170,750"],
["Ashton Cox", "Junior Technical Author", "San Francisco", "66", "2009/01/12", "$86,000"],
["Cedric Kelly", "Senior Javascript Developer", "Edinburgh", "22", "2012/03/29", "$433,060"],
["Airi Satou", "Accountant", "Tokyo", "33", "2008/11/28", "$162,700"],
["Brielle Williamson", "Integration Specialist", "New York", "61", "2012/12/02", "$372,000"],
["Herrod Chandler", "Sales Assistant", "San Francisco", "59", "2012/08/06", "$137,500"],
["Rhona Davidson", "Integration Specialist", "Tokyo", "55", "2010/10/14", "$327,900"],
["Colleen Hurst", "Javascript Developer", "San Francisco", "39", "2009/09/15", "$205,500"],
["Sonya Frost", "Software Engineer", "Edinburgh", "23", "2008/12/13", "$103,600"],
["Jena Gaines", "Office Manager", "London", "30", "2008/12/19", "$90,560"],
["Quinn Flynn", "Support Lead", "Edinburgh", "22", "2013/03/03", "$342,000"],
["Charde Marshall", "Regional Director", "San Francisco", "36", "2008/10/16", "$470,600"],
["Haley Kennedy", "Senior Marketing Designer", "London", "43", "2012/12/18", "$313,500"]
],
};
const datatable = document.getElementById('datatable');
new Datatable(datatable, basicData);
const basicData = {
columns: [
{ label: 'Name', field: 'name', sort: true, width: 200, fixed: true },
{ label: 'Position', field: 'position', sort: false, width: 200 },
{ label: 'Office', field: 'office', sort: false, width: 200, fixed: true },
{ label: 'Age', field: 'age', sort: false, width: 200 },
{ label: 'Start date', field: 'date', sort: true, width: 200 },
{ label: 'Salary', field: 'salary', sort: false, width: 200, fixed: 'right' },
],
rows: [
["Tiger Nixon", "System Architect", "Edinburgh", "61", "2011/04/25", "$320,800"],
["Garrett Winters", "Accountant", "Tokyo", "63", "2011/07/25", "$170,750"],
["Ashton Cox", "Junior Technical Author", "San Francisco", "66", "2009/01/12", "$86,000"],
["Cedric Kelly", "Senior Javascript Developer", "Edinburgh", "22", "2012/03/29", "$433,060"],
["Airi Satou", "Accountant", "Tokyo", "33", "2008/11/28", "$162,700"],
["Brielle Williamson", "Integration Specialist", "New York", "61", "2012/12/02", "$372,000"],
["Herrod Chandler", "Sales Assistant", "San Francisco", "59", "2012/08/06", "$137,500"],
["Rhona Davidson", "Integration Specialist", "Tokyo", "55", "2010/10/14", "$327,900"],
["Colleen Hurst", "Javascript Developer", "San Francisco", "39", "2009/09/15", "$205,500"],
["Sonya Frost", "Software Engineer", "Edinburgh", "23", "2008/12/13", "$103,600"],
["Jena Gaines", "Office Manager", "London", "30", "2008/12/19", "$90,560"],
["Quinn Flynn", "Support Lead", "Edinburgh", "22", "2013/03/03", "$342,000"],
["Charde Marshall", "Regional Director", "San Francisco", "36", "2008/10/16", "$470,600"],
["Haley Kennedy", "Senior Marketing Designer", "London", "43", "2012/12/18", "$313,500"]
],
};
const datatable = document.getElementById('datatable');
new mdb.Datatable(datatable, basicData);
Async data
Loading content asynchronously is an important part of working with data tables - with MDB
Datatable you can easily display content after fetching it from an API using the
update
method. Additionally, setting a loading
option to
true
will disable all interactions and display a simple loader while awaiting
data.
The example below demonstrates loading data after the button is pressed.
<div id="datatable" data-mdb-loading="true"></div>
// Initialization for ES Users
import { Datatable, initMDB } from "mdb-ui-kit";
initMDB({ Datatable });
const columns = [
{ label: 'Address', field: 'address' },
{ label: 'Company', field: 'company' },
{ label: 'Email', field: 'email' },
{ label: 'Name', field: 'name' },
{ label: 'Phone', field: 'phone' },
{ label: 'Username', field: 'username' },
{ label: 'Website', field: 'website' },
];
const asyncTable = new Datatable(
document.getElementById('datatable'),
{ columns, },
{ loading: true }
);
fetch('https://jsonplaceholder.typicode.com/users')
.then((response) => response.json())
.then((data) => {
asyncTable.update(
{
rows: data.map((user) => ({
...user,
address: `${user.address.city}, ${user.address.street}`,
company: user.company.name,
})),
},
{ loading: false }
);
});
const columns = [
{ label: 'Address', field: 'address' },
{ label: 'Company', field: 'company' },
{ label: 'Email', field: 'email' },
{ label: 'Name', field: 'name' },
{ label: 'Phone', field: 'phone' },
{ label: 'Username', field: 'username' },
{ label: 'Website', field: 'website' },
];
const asyncTable = new mdb.Datatable(
document.getElementById('datatable'),
{ columns, },
{ loading: true }
);
fetch('https://jsonplaceholder.typicode.com/users')
.then((response) => response.json())
.then((data) => {
asyncTable.update(
{
rows: data.map((user) => ({
...user,
address: `${user.address.city}, ${user.address.street}`,
company: user.company.name,
})),
},
{ loading: false }
);
});
Action buttons
With the Datatable it's possible to render custom content, such as action buttons and attach
listeners to their events. Keep in mind, that the component rerenders content when various
actions occur (f.e. sort, search) and event listeners need to be updated. To make it possible,
the components emits a custom event render.mdb.datatable
.
<div id="datatable-custom"></div>
// Initialization for ES Users
import { Datatable, Ripple, initMDB } from "mdb-ui-kit";
initMDB({ Datatable, Ripple });
const customDatatable = document.getElementById('datatable-custom');
const setActions = () => {
document.getElementsByClassName('call-btn').forEach(btn => {
btn.addEventListener('click', () => {
console.log(`call ${btn.attributes['data-mdb-number'].value}`)
})
})
document.getElementsByClassName('message-btn').forEach(btn => {
btn.addEventListener('click', () => {
console.log(`send a message to ${btn.attributes['data-mdb-email'].value}`)
})
})
}
customDatatable.addEventListener('render.mdb.datatable', setActions);
new Datatable(customDatatable, {
columns: [
{ label: 'Name', field: 'name' },
{ label: 'Position', field: 'position' },
{ label: 'Office', field: 'office' },
{ label: 'Contact', field: 'contact', sort: false },
],
rows: [
{
name: 'Tiger Nixon',
position: 'System Architect',
office: 'Edinburgh',
phone: '+48000000000',
email: 'tiger.nixon@gmail.com'
},
{
name: 'Sonya Frost',
position: 'Software Engineer',
office: 'Edinburgh',
phone: '+53456123456',
email: 'sfrost@gmail.com'
},
{
name: 'Tatyana Fitzpatrick',
position: 'Regional Director',
office: 'London',
phone: '+42123432456',
email: 'tfitz@gmail.com'
},
].map((row) => {
return {
...row,
contact: `
<button data-mdb-ripple-init class="call-btn btn btn-outline-primary btn-floating btn-sm" data-mdb-number="${row.phone}"><i class="fa fa-phone"></i></button>
<button data-mdb-ripple-init class="message-btn btn ms-2 btn-primary btn-floating btn-sm" data-mdb-email="${row.email}"><i class="fa fa-envelope"></i></button>`,
};
}),
}, { hover: true });
const customDatatable = document.getElementById('datatable-custom');
const setActions = () => {
document.getElementsByClassName('call-btn').forEach(btn => {
btn.addEventListener('click', () => {
console.log(`call ${btn.attributes['data-mdb-number'].value}`)
})
})
document.getElementsByClassName('message-btn').forEach(btn => {
btn.addEventListener('click', () => {
console.log(`send a message to ${btn.attributes['data-mdb-email'].value}`)
})
})
}
customDatatable.addEventListener('render.mdb.datatable', setActions);
new mdb.Datatable(customDatatable, {
columns: [
{ label: 'Name', field: 'name' },
{ label: 'Position', field: 'position' },
{ label: 'Office', field: 'office' },
{ label: 'Contact', field: 'contact', sort: false },
],
rows: [
{
name: 'Tiger Nixon',
position: 'System Architect',
office: 'Edinburgh',
phone: '+48000000000',
email: 'tiger.nixon@gmail.com'
},
{
name: 'Sonya Frost',
position: 'Software Engineer',
office: 'Edinburgh',
phone: '+53456123456',
email: 'sfrost@gmail.com'
},
{
name: 'Tatyana Fitzpatrick',
position: 'Regional Director',
office: 'London',
phone: '+42123432456',
email: 'tfitz@gmail.com'
},
].map((row) => {
return {
...row,
contact: `
<button data-mdb-ripple-init class="call-btn btn btn-outline-primary btn-floating btn-sm" data-mdb-number="${row.phone}"><i class="fa fa-phone"></i></button>
<button data-mdb-ripple-init class="message-btn btn ms-2 btn-primary btn-floating btn-sm" data-mdb-email="${row.email}"><i class="fa fa-envelope"></i></button>`,
};
}),
}, { hover: true });
Cell formatting
Use cell formatting to color individual cells.
<div id="datatable-cell-format" data-mdb-sort-field="purchases" data-mdb-sort-order="desc"></div>
// Initialization for ES Users
import { Datatable, initMDB } from "mdb-ui-kit";
initMDB({ Datatable });
const rows = [
['Product 1', 10, 103],
['Product 2', 45, 110],
['Product 3', 76, 56],
['Product 4', 89, 230],
['Product 5', 104, 240],
['Product 6', 97, 187],
['Product 7', 167, 130],
['Product 8', 50, 199],
['Product 9', 4, 206],
['Product 10', 120, 88],
['Product 11', 22, 100],
];
const maxValue = Math.max(...rows.map((row) => row[2]));
const minValue = Math.min(...rows.map((row) => row[2]));
const colors = ['#E3F2FD', '#BBDEFB', '#90CAF9', '#64B5F6', '#42A5F5'];
const step = (maxValue - minValue) / (colors.length - 1);
const formatCell = (cell, value) => {
const colorIndex = Math.floor((value - minValue) / step);
cell.style.backgroundColor = colors[colorIndex];
cell.style.fontWeight = 400;
};
const columns = [
{ label: 'Product', field: 'product' },
{ label: 'Quantity', field: 'quantity' },
{ label: 'Purchases', field: 'purchases', format: formatCell },
];
const datatableInstance = new Datatable(
document.getElementById('datatable-cell-format'),
{ rows, columns }
);
const rows = [
['Product 1', 10, 103],
['Product 2', 45, 110],
['Product 3', 76, 56],
['Product 4', 89, 230],
['Product 5', 104, 240],
['Product 6', 97, 187],
['Product 7', 167, 130],
['Product 8', 50, 199],
['Product 9', 4, 206],
['Product 10', 120, 88],
['Product 11', 22, 100],
];
const maxValue = Math.max(...rows.map((row) => row[2]));
const minValue = Math.min(...rows.map((row) => row[2]));
const colors = ['#E3F2FD', '#BBDEFB', '#90CAF9', '#64B5F6', '#42A5F5'];
const step = (maxValue - minValue) / (colors.length - 1);
const formatCell = (cell, value) => {
const colorIndex = Math.floor((value - minValue) / step);
cell.style.backgroundColor = colors[colorIndex];
cell.style.fontWeight = 400;
};
const columns = [
{ label: 'Product', field: 'product' },
{ label: 'Quantity', field: 'quantity' },
{ label: 'Purchases', field: 'purchases', format: formatCell },
];
const datatableInstance = new mdb.Datatable(
document.getElementById('datatable-cell-format'),
{ rows, columns }
);
Clickable rows
Click on the row to preview the message.
Selecting the row with checkbox doesn't trigger rowClicked
event.
Note: To prevent this action with other clickable elements within the row, call
stopPropagation()
method.
Note: This feature cannot be used simultaneously with edit
option.
<div id="datatable-clickable-rows" data-mdb-clickable-rows="true" data-mdb-selectable="true" data-mdb-multi="true"></div>
<!-- Modal -->
<div class="modal fade" tabindex="-1" aria-hidden="true" id="modal-clickable-rows">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="modal-header-clickable-rows"></h5>
<button type="button" class="btn-close" data-mdb-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body mt-4 mb-5" id="modal-body-clickable-rows"></div>
<div class="modal-footer">
<button data-mdb-ripple-init type="button" class="btn btn-outline-primary">
Reply
<i class="fa fa-paper-plane ms-2"></i>
</button>
<button data-mdb-ripple-init type="button" class="btn btn-outline-primary">
Forward
<i class="fa fa-arrow-right ms-2"></i>
</button>
</div>
</div>
</div>
</div>
// Initialization for ES Users
import { Datatable, Ripple, initMDB } from "mdb-ui-kit";
initMDB({ Datatable, Ripple });
const table = document.getElementById('datatable-clickable-rows');
const modal = document.getElementById('modal-clickable-rows');
const modalBody = document.getElementById('modal-body-clickable-rows');
const modalHeader = document.getElementById('modal-header-clickable-rows');
const modalInstance = new mdb.Modal(modal);
const setupButtons = (action) => {
document.getElementsByClassName(`${action}-email-button`).forEach((button) => {
button.addEventListener('click', (e) => {
e.stopPropagation();
const index = button.getAttribute('data-mdb-index');
console.log(`${action} message: ${index}`, messages[index]);
});
});
};
const columns = [
{ label: 'Actions', field: 'actions', sort: false },
{ label: 'From', field: 'from' },
{ label: 'Title', field: 'title' },
{ label: 'Message', field: 'preview', sort: false },
{ label: 'Date', field: 'date' },
];
const messages = [
{
from: 'admin@mdbootstrap.com',
title: 'MDBootstrap spring sale',
message: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur sed metus ultricies, sollicitudin est nec, blandit turpis. Fusce venenatis nisi volutpat, pharetra elit eu, ullamcorper metus. Vestibulum dapibus laoreet aliquam. Maecenas sed magna ut libero consequat elementum. Maecenas euismod pellentesque pulvinar. Morbi sit amet turpis eget dolor rutrum eleifend. Sed bibendum diam nec diam posuere pulvinar. Cras ac bibendum arcu.',
date: '11/12/2019',
},
{
from: 'user@mdbootstrap.com',
title: 'How to purchase MDB5 package?',
message: 'Quisque tempor ligula eu lobortis scelerisque. Mauris tristique mi a erat egestas, quis dictum nibh iaculis. Sed gravida sodales egestas. In tempus mollis libero sit amet lacinia. Duis non augue sed leo imperdiet efficitur faucibus vitae elit. Mauris eu cursus ligula. Praesent posuere efficitur cursus.',
date: '10/12/2019',
},
{
from: 'user@mdbootstrap.com',
title: 'Licence renewal',
message: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur sed metus ultricies, sollicitudin est nec, blandit turpis. Fusce venenatis nisi volutpat, pharetra elit eu, ullamcorper metus. Vestibulum dapibus laoreet aliquam. Maecenas sed magna ut libero consequat elementum. Maecenas euismod pellentesque pulvinar. Morbi sit amet turpis eget dolor rutrum eleifend. Sed bibendum diam nec diam posuere pulvinar. Cras ac bibendum arcu.',
date: '09/12/2019',
},
{
from: 'admin@mdbootstrap.com',
title: 'Black friday offer',
message: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur sed metus ultricies, sollicitudin est nec, blandit turpis. Fusce venenatis nisi volutpat, pharetra elit eu, ullamcorper metus. Vestibulum dapibus laoreet aliquam. Maecenas sed magna ut libero consequat elementum. Maecenas euismod pellentesque pulvinar. Morbi sit amet turpis eget dolor rutrum eleifend. Sed bibendum diam nec diam posuere pulvinar. Cras ac bibendum arcu.',
date: '08/12/2019',
},
];
const rows = messages.map((email, i) => {
const getPreview = (message, length) => {
if (message.length <= length) return message;
return `${message.slice(0, length)}...`;
};
return {
...email,
preview: getPreview(email.message, 20),
actions: `
<a role="button" class="star-email-button text-warning" data-mdb-index="${i}">
<i class="far fa-star"></i>
</a>
<a role="button" class="delete-email-button text-muted ms-2" data-mdb-index="${i}">
<i class="fa fa-trash-alt"></i>
</a>
`,
};
});
table.addEventListener('rowClicked.mdb.datatable', (e) => {
const { index } = e;
const { message, title, from } = messages[index];
modalHeader.innerText = title;
modalBody.innerHTML = `
<h6 class="mb-4">From: <strong>${from}</strong></h6>
<p>${message}</p>
`;
modalInstance.show();
});
table.addEventListener('render.mdb.datatable', () => {
setupButtons('star');
setupButtons('delete');
})
const datatableInstance = new Datatable(table, {
columns,
rows,
});
const table = document.getElementById('datatable-clickable-rows');
const modal = document.getElementById('modal-clickable-rows');
const modalBody = document.getElementById('modal-body-clickable-rows');
const modalHeader = document.getElementById('modal-header-clickable-rows');
const modalInstance = new mdb.Modal(modal);
const setupButtons = (action) => {
document.getElementsByClassName(`${action}-email-button`).forEach((button) => {
button.addEventListener('click', (e) => {
e.stopPropagation();
const index = button.getAttribute('data-mdb-index');
console.log(`${action} message: ${index}`, messages[index]);
});
});
};
const columns = [
{ label: 'Actions', field: 'actions', sort: false },
{ label: 'From', field: 'from' },
{ label: 'Title', field: 'title' },
{ label: 'Message', field: 'preview', sort: false },
{ label: 'Date', field: 'date' },
];
const messages = [
{
from: 'admin@mdbootstrap.com',
title: 'MDBootstrap spring sale',
message: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur sed metus ultricies, sollicitudin est nec, blandit turpis. Fusce venenatis nisi volutpat, pharetra elit eu, ullamcorper metus. Vestibulum dapibus laoreet aliquam. Maecenas sed magna ut libero consequat elementum. Maecenas euismod pellentesque pulvinar. Morbi sit amet turpis eget dolor rutrum eleifend. Sed bibendum diam nec diam posuere pulvinar. Cras ac bibendum arcu.',
date: '11/12/2019',
},
{
from: 'user@mdbootstrap.com',
title: 'How to purchase MDB5 package?',
message: 'Quisque tempor ligula eu lobortis scelerisque. Mauris tristique mi a erat egestas, quis dictum nibh iaculis. Sed gravida sodales egestas. In tempus mollis libero sit amet lacinia. Duis non augue sed leo imperdiet efficitur faucibus vitae elit. Mauris eu cursus ligula. Praesent posuere efficitur cursus.',
date: '10/12/2019',
},
{
from: 'user@mdbootstrap.com',
title: 'Licence renewal',
message: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur sed metus ultricies, sollicitudin est nec, blandit turpis. Fusce venenatis nisi volutpat, pharetra elit eu, ullamcorper metus. Vestibulum dapibus laoreet aliquam. Maecenas sed magna ut libero consequat elementum. Maecenas euismod pellentesque pulvinar. Morbi sit amet turpis eget dolor rutrum eleifend. Sed bibendum diam nec diam posuere pulvinar. Cras ac bibendum arcu.',
date: '09/12/2019',
},
{
from: 'admin@mdbootstrap.com',
title: 'Black friday offer',
message: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur sed metus ultricies, sollicitudin est nec, blandit turpis. Fusce venenatis nisi volutpat, pharetra elit eu, ullamcorper metus. Vestibulum dapibus laoreet aliquam. Maecenas sed magna ut libero consequat elementum. Maecenas euismod pellentesque pulvinar. Morbi sit amet turpis eget dolor rutrum eleifend. Sed bibendum diam nec diam posuere pulvinar. Cras ac bibendum arcu.',
date: '08/12/2019',
},
];
const rows = messages.map((email, i) => {
const getPreview = (message, length) => {
if (message.length <= length) return message;
return `${message.slice(0, length)}...`;
};
return {
...email,
preview: getPreview(email.message, 20),
actions: `
<a role="button" class="star-email-button text-warning" data-mdb-index="${i}">
<i class="far fa-star"></i>
</a>
<a role="button" class="delete-email-button text-muted ms-2" data-mdb-index="${i}">
<i class="fa fa-trash-alt"></i>
</a>
`,
};
});
table.addEventListener('rowClicked.mdb.datatable', (e) => {
const { index } = e;
const { message, title, from } = messages[index];
modalHeader.innerText = title;
modalBody.innerHTML = `
<h6 class="mb-4">From: <strong>${from}</strong></h6>
<p>${message}</p>
`;
modalInstance.show();
});
table.addEventListener('render.mdb.datatable', () => {
setupButtons('star');
setupButtons('delete');
})
const datatableInstance = new mdb.Datatable(table, {
columns,
rows,
});
Datatables - API
Import
Importing components depends on how your application works. If you intend to use the MDBootstrap ES
format, you must
first import the component and then initialize it with the initMDB
method. If you are going to use the UMD
format,
just import the mdb-ui-kit
package.
import { Datatable, initMDB } from "mdb-ui-kit";
initMDB({ Datatable });
import 'mdb-ui-kit';
Usage
Via data attributes
Using the Datatable component doesn't require any additional JavaScript code - simply add
data-mdb-datatable-init
attribute to
.datatable
and use other data attributes to set all options.
For ES
format, you must first import and call the initMDB
method.
<div class="datatable" data-mdb-datatable-init>
<table>
<thead>
<tr>
<th data-mdb-sort="false" data-mdb-fixed="true" data-mdb-width="100">Column 1</th>
<th>Column 2</th>
</tr>
</thead>
<tbody>
<tr>
<td>Value 1</td>
<td>Value 2</td>
</tr>
</tbody>
</table>
</div>
Via JavaScript
const datatableInstance = new Datatable(
document.getElementById('my-datatable'),
{
columns: [
{ label: 'Column 1', width: 100, fixed: true, sort: false },
{ label: 'Column 2'}
],
rows: [
['Value 1', 'Value 2']
]
},
{
bordered: true
}
)
const datatableInstance = new mdb.Datatable(
document.getElementById('my-datatable'),
{
columns: [
{ label: 'Column 1', width: 100, fixed: true, sort: false },
{ label: 'Column 2'}
],
rows: [
['Value 1', 'Value 2']
]
},
{
bordered: true
}
)
Via jQuery
Note: By default, MDB does not include jQuery and you have to add it to the project on your own.
$(document).ready(() => {
$('#my-datatable').datatable(
{
columns: [
{ label: 'Column 1', width: 100, fixed: true, sort: false },
{ label: 'Column 2'}
],
rows: [
['Value 1', 'Value 2']
]
},
{
bordered: true
}
)
// Calling .update() with the jQuery interface:
$('#my-datatable').datatable('update', { rows: [...], columns: [...]}, { bordered: true, loading: false })
});
Options
Options can be passed via data attributes or JavaScript. For data attributes, append the option name to
data-mdb-
, as in data-mdb-all-text=""
.
Name | Type | Default | Description |
---|---|---|---|
allText
|
String | 'All' |
Changes text for All in the pagination select |
bordered
|
Boolean | false |
Adds borders to a datatable |
borderless
|
Boolean | false |
Removes all borders from a datatable |
borderColor
|
String | null | null |
Changes a border color to one of main colors |
color |
String | null | null |
Adds a color class to a datatable (f.e 'bg-dark') |
defaultValue
|
String | '-' |
This string will be used as a placeholder if a row doesn't have a defined value for a column |
edit |
Boolean | false |
Enables edit mode |
entries
|
Number | String | 10 |
Number of visible entries (pagination) |
entriesOptions
|
Array | [10, 25, 50, 200] |
Options available to choose from in a pagination select (rows per page). Array with the available options may contain numbers and 'All' to display all entries on single page. |
fixedHeader
|
Boolean | false |
When it's set to true, the table's header will remain visible while scrolling |
forceSort
|
Boolean | false |
When it's set to true, the table's sort will toggle between two options: ascending and descending. The initial state will not be one of the options. |
fullPagination
|
Boolean | false |
Displays additional buttons for the first and last pages |
hover |
Boolean | false |
Changes the background color of a hovered row |
loading
|
Boolean | false |
Sets the loading mode - disables interactions and displays a loader |
loaderClass
|
String | 'bg-primary' |
The class name for a loader (loading mode) |
loadingMessage
|
String | 'Loading results...' |
A message displayed while loading data |
maxWidth
|
Number | String | null | null |
Sets a maximum width of a datatable - can be either a string ('10%') or a number of pixels. |
maxHeight
|
Number | String | null | null |
Sets a maximum height of a datatable - can be either a string ('10%') or a number of pixels. |
selectable
|
Boolean | false |
Enables selecting rows with checkboxes |
multi |
Boolean | false |
Allows selecting multiple rows (selectable mode) |
noFoundMessage
|
String | 'No matching results found' |
A message displayed when a table is empty |
pagination
|
Boolean | true |
Shows/hides the pagination panel |
sm |
Boolean | false |
Decreases a row's paddings |
striped
|
Boolean | false |
Slightly changes the background's color in every other row |
rowsText
|
String | 'Rows per page:' |
A text indicating a number of rows per page |
ofText
|
String | 'of' |
A message displayed as pagination description |
clickableRows
|
Boolean | false |
Makes rows clickable |
sortField
|
String | null | null |
Sorts given field on init. To use it via data attributes additionally data-mdb-field attribute needs to be added to column th element. e.g. <th data-mdb-field="age">Age</th>
|
sortOrder
|
String | 'asc' |
Defines an order in which initial sorting will sort. Use 'asc' for ascending order, and 'desc' for descending order (works only when data is injected with JS) |
Options (column)
Name | Type | Default | Description |
---|---|---|---|
label |
String | '' |
A displayed header of a column |
field |
String | '' |
A field's name - will be used as a key for values in rows |
fixed |
Boolean | String | false |
When set to true , makes a column stick on the left while scrolling.
Changing its value to right will do the same on the other side. For this
option to work, you need to define width as well.
|
width |
Number | null | null |
A column's width in pixels |
sort |
Boolean | true |
Enables/disables sorting for this column |
format(cell, value) |
Function | null | null |
Function runs for each cell, taking the DOM node & cell's value as its parameters |
Methods
Name | Description | Example |
---|---|---|
update |
Updates and rerenders datatable. |
myDatatable.update(data: Object, options: Object)
|
setActivePage |
Sets a specific page of entries. Page count starts from 0 . |
myDatatable.setActivePage(index)
|
search |
Filters rows so there are only those containing the searched phrase. |
myDatatable.search(phrase: String, column: String|Array (optional))
|
dispose
|
Removes the component's instance. |
myDatatable.dispose()
|
getInstance
|
Static method which allows you to get the datatable instance associated to a DOM element. |
Datatable.getInstance(datatableEl)
|
getOrCreateInstance
|
Static method which returns the datatable instance associated to a DOM element or create a new one in case it wasn't initialized. |
Datatable.getOrCreateInstance(datatableEl)
|
const datatableEl = document.getElementById('my-datatable')
const datatableInstance = Datatable.getInstance(datatableEl);
datatableInstance.dispose()
const datatableEl = document.getElementById('my-datatable')
const datatableInstance = mdb.Datatable.getInstance(datatableEl);
datatableInstance.dispose()
Events
Name | Description |
---|---|
update.mdb.datatable
|
This event is triggered in an editable mode when a user updates values. You can access the
updated data inside a listener's handler with
event.rows and event.columns fields.
|
rowSelected.mdb.datatable
|
This event is triggered when a user selects rows using checkboxes. You can access information about selected rows through the following properties of the emitted event:
selectedRows: Array , selectedIndexes: Array ,
allSelected: Boolean
|
render.mdb.datatable
|
This event is triggered after the component renders/updates rows. |
rowClicked.mdb.datatable
|
This event is triggered after clicking on a row. |
const datatable = document.getElementById('my-datatable');
datatable.addEventListener('rowSelected.mdb.datatable', (e) => {
console.log(e.selectedRows, e.selectedIndexes, e.allSelected)
})
CSS variables
// .datatable
--#{$prefix}datatable-color: #{$datatable-color};
--#{$prefix}datatable-border-color: #{$datatable-border-color};
--#{$prefix}datatable-striped-color: #{$datatable-striped-color};
--#{$prefix}datatable-accent-bg: #{$datatable-accent-bg};
--#{$prefix}datatable-hover-color: #{$datatable-hover-color};
--#{$prefix}datatable-hover-bg: #{$datatable-hover-bg};
--#{$prefix}datatable-muted-color: #{$datatable-muted-color};
--#{$prefix}datatable-active-color: #{$datatable-active-color};
--#{$prefix}datatable-font-size: #{$datatable-font-size};
--#{$prefix}datatable-background-color: #{$datatable-background-color};
--#{$prefix}datatable-table-th-td-max-width: #{$datatable-table-th-td-max-width};
--#{$prefix}datatable-table-th-td-padding-y: #{$datatable-table-th-td-padding-y};
--#{$prefix}datatable-table-th-td-padding-x: #{$datatable-table-th-td-padding-x};
--#{$prefix}datatable-thead-tr-border-width: #{$datatable-thead-tr-border-width};
--#{$prefix}datatable-thead-th-font-weight: #{$datatable-thead-th-font-weight};
--#{$prefix}datatable-thead-fixed-cell-background-color: #{$datatable-thead-fixed-cell-background-color};
--#{$prefix}datatable-tbody-font-weight: #{$datatable-tbody-font-weight};
--#{$prefix}datatable-tbody-tr-transition: #{$datatable-tbody-tr-transition};
--#{$prefix}datatable-tbody-tr-last-child-height: #{$datatable-tbody-tr-last-child-height};
--#{$prefix}datatable-tbody-loader-height: #{$datatable-tbody-loader-height};
--#{$prefix}datatable-tbody-progress-animation: #{$datatable-tbody-progress-animation};
--#{$prefix}datatable-tbody-progress-width: #{$datatable-tbody-progress-width};
--#{$prefix}datatable-tbody-progress-opacity: #{$datatable-tbody-progress-opacity};
--#{$prefix}datatable-tbody-progress-border-radius: #{$datatable-tbody-progress-border-radius};
--#{$prefix}datatable-pagination-padding-y: #{$datatable-pagination-padding-y};
--#{$prefix}datatable-pagination-border-width: #{$datatable-pagination-border-width};
--#{$prefix}datatable-pagination-nav-font-size: #{$datatable-pagination-nav-font-size};
--#{$prefix}datatable-pagination-buttons-margin-left: #{$datatable-pagination-buttons-margin-left};
--#{$prefix}datatable-pagination-button-padding-x: #{$datatable-pagination-button-padding-x};
--#{$prefix}datatable-sort-icon-transition-duration: #{$datatable-sort-icon-transition-duration};
--#{$prefix}datatable-sort-icon-left: #{$datatable-sort-icon-left};
--#{$prefix}datatable-sort-icon-top: #{$datatable-sort-icon-top};
--#{$prefix}datatable-select-wrapper-font-size: #{$datatable-select-wrapper-font-size};
--#{$prefix}datatable-select-wrapper-font-weight: #{$datatable-select-wrapper-font-weight};
--#{$prefix}datatable-sm-th-td-padding-y: #{$datatable-sm-th-td-padding-y};
--#{$prefix}datatable-sm-th-td-padding-x: #{$datatable-sm-th-td-padding-x};
--#{$prefix}datatable-sm-tbody-tr-last-child-height: #{$datatable-sm-tbody-tr-last-child-height};
--#{$prefix}datatable-sm-pagination-padding: #{$datatable-sm-pagination-padding};
--#{$prefix}datatable-bordered-th-td-border-width: #{$datatable-bordered-th-td-border-width};
--#{$prefix}datatable-hover-tbody-tr-transition: #{$datatable-hover-tbody-tr-transition};
--#{$prefix}datatable-dark-select-arrow-input-color: #{$datatable-dark-select-arrow-input-color};
--#{$prefix}datatable-dark-border-color: #{$datatable-dark-border-color};
--#{$prefix}datatable-dark-check-border-color: #{$datatable-dark-check-border-color};
--#{$prefix}datatable-dark-datatable-progress-opacity: #{$datatable-dark-datatable-progress-opacity};
// &.datatable-dark
--#{$prefix}datatable-color: #{$datatable-dark-color};
--#{$prefix}datatable-border-color: #{$datatable-dark-border-color};
--#{$prefix}datatable-active-color: #{$datatable-dark-active-color};
--#{$prefix}datatable-striped-color: #{$datatable-dark-striped-color};
--#{$prefix}datatable-accent-bg: #{$datatable-dark-accent-bg};
--#{$prefix}datatable-hover-bg: #{$datatable-dark-hover-bg};
--#{$prefix}datatable-hover-color: #{$datatable-dark-hover-color};
// @each $color, $value in $theme-colors
// &.border-#{$color}
--#{$prefix}datatable-border-color: #{$value};
// &.datatable-borderless
--#{$prefix}datatable-border-color: #{transparent};
SCSS variables
$datatable-color: var(--#{$prefix}body-color);
$datatable-border-color: var(--#{$prefix}border-color);
$datatable-striped-color: var(--#{$prefix}body-color);
$datatable-accent-bg: rgba(var(--#{$prefix}emphasis-color-rgb), 0.02);
$datatable-hover-color: var(--#{$prefix}body-color);
$datatable-hover-bg: rgba(var(--#{$prefix}emphasis-color-rgb), 0.025);
$datatable-muted-color: rgba(var(--#{$prefix}emphasis-color-rgb), 0.55);
$datatable-active-color: rgba(var(--#{$prefix}emphasis-color-rgb), 0.1);
$datatable-font-size: 0.9rem;
$datatable-background-color: var(--#{$prefix}body-bg);
$datatable-table-th-td-max-width: 250px;
$datatable-table-th-td-padding-y: 1rem;
$datatable-table-th-td-padding-x: 1.4rem;
$datatable-thead-tr-border-width: 1px;
$datatable-thead-th-font-weight: 500;
$datatable-thead-fixed-cell-background-color: var(--#{$prefix}body-bg);
$datatable-tbody-font-weight: 300;
$datatable-tbody-tr-transition: all 0.3s ease-in;
$datatable-tbody-tr-last-child-height: 71px;
$datatable-tbody-loader-height: 2px;
$datatable-tbody-progress-animation: datatableProgress 3s ease-in-out;
$datatable-tbody-progress-width: 45%;
$datatable-tbody-progress-opacity: 0.5;
$datatable-tbody-progress-border-radius: 1px;
$datatable-pagination-padding-y: 0.5rem;
$datatable-pagination-border-width: 1px;
$datatable-pagination-nav-font-size: 0.9rem;
$datatable-pagination-buttons-margin-left: 2rem;
$datatable-pagination-button-padding-x: 1rem;
$datatable-sort-icon-transition-duration: 0.3s;
$datatable-sort-icon-left: 0.4rem;
$datatable-sort-icon-top: calc(50% - 0.5rem);
$datatable-select-wrapper-font-size: 0.9rem;
$datatable-select-wrapper-font-weight: 300;
$datatable-select-font-size: 1rem;
$datatable-select-line-height: 1.3;
$datatable-select-padding-top: 0.4em;
$datatable-select-padding-right: 1.2em;
$datatable-select-padding-bottom: 0.3em;
$datatable-select-padding-left: 0.6em;
$datatable-select-margin-right: 1.4rem;
$datatable-select-margin-left: 0.1rem;
$datatable-select-background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='100' height='100' fill='%23000'><polygon points='0,0 100,0 50,50'/></svg>");
$datatable-select-background-position: right 0.4em top 60%, 0 0;
$datatable-select-background-size: 0.65em auto, 100%;
$datatable-select-focus-font-weight: 500;
$datatable-select-option-color: $black;
$datatable-sm-th-td-padding-y: 0.5rem;
$datatable-sm-th-td-padding-x: 1.4rem;
$datatable-sm-tbody-tr-last-child-height: 55px;
$datatable-sm-pagination-padding: 0.2rem;
$datatable-dark-check-border-color: $white;
$datatable-dark-select-background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='100' height='100' fill='white'><polygon points='0,0 100,0 50,50'/></svg>");
$datatable-dark-datatable-progress-opacity: 0.8;
$datatable-dark-select-arrow-input-color: white;
$datatable-dark-border-color: rgb(251, 251, 251);
$datatable-dark-color: #fff;
$datatable-dark-border-color: #fff;
$datatable-dark-striped-color: white;
$datatable-dark-accent-bg: rgba(255, 255, 255, 0.05);
$datatable-dark-hover-color: white;
$datatable-dark-hover-bg: rgb(63, 63, 63);
$datatable-dark-active-color: rgba(255, 255, 255, 0.2);
$datatable-hover-tbody-tr-transition: background-color 0.2s ease-in;
$datatable-bordered-th-td-border-width: 1px;
$datatable-loading-select-background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='100' height='100' fill='grey'><polygon points='0,0 100,0 50,50'/></svg>");