# Datatable
Enzyme UI tables consist of two components: Cell
and DatatTable
. Cell
is responsible for what its name stands for -
it's a simple cell of table that is used as either <td>
or <th>
and contains single data point information,
whereas DataTable
is more complex component that handles all the cells and the functionality and styling of the actual table.
# Simple Usage
Datatables are highly customizable. The most simple way to use DataTable
is to provide component with data
prop
which should be an Array of Arrays (rows x columns). It is also recommended to provide headers
prop with Array of Strings
which will be placed inside <thead>
as <th>
elements.
Name
|
Surname
|
Age
|
Email
|
---|---|---|---|
John | Manager | 43 | john@doe.com |
Maryl | Piper | 56 | maryl@doe.com |
Lucy | Martin | 29 | lucy@doe.com |
Vinnie | Parker | 71 | vinnie@doe.com |
Alex | Maxwell | 66 | alex@doe.com |
<DataTable :data="dataTable1" :headers="dataTableHeaders1"/>
<script>
export default {
data(){
return {
dataTable1:[
['John', 'Manager', 43, 'john@doe.com'],
['Maryl', 'Piper', 56, 'maryl@doe.com'],
['Lucy', 'Martin', 29, 'lucy@doe.com'],
['Vinnie', 'Parker', 71, 'vinnie@doe.com'],
['Alex', 'Maxwell', 66, 'alex@doe.com'],
],
dataTableHeaders1:['Name', 'Surname', 'Age', 'Email'],
};
},
}
</script>
# Filter buttons
DataTable
supports data ordering. Simply use showFilterButtons
prop to display built in sorting buttons inside table headings.
Name
|
Surname
|
Age
|
Email
|
---|---|---|---|
John | Manager | 43 | john@doe.com |
Maryl | Piper | 56 | maryl@doe.com |
Lucy | Martin | 29 | lucy@doe.com |
Vinnie | Parker | 71 | vinnie@doe.com |
Alex | Maxwell | 66 | alex@doe.com |
<DataTable :data="dataTable1" :headers="dataTableHeaders1" show-filter-buttons/>
<script>
export default {
data(){
return {
dataTable1:[
['John', 'Manager', 43, 'john@doe.com'],
['Maryl', 'Piper', 56, 'maryl@doe.com'],
['Lucy', 'Martin', 29, 'lucy@doe.com'],
['Vinnie', 'Parker', 71, 'vinnie@doe.com'],
['Alex', 'Maxwell', 66, 'alex@doe.com'],
],
dataTableHeaders1:['Name', 'Surname', 'Age', 'Email'],
};
},
}
</script>
If you want to override default filter buttons you will need to implement table header by yourself. To do this use header
slot which exposes these slot props:
- sortAsc
function
which acceptsheader
value as input, whereheader
is an item fromheaders
prop array which is bound toDataTable
. When called, providedheader
column data will be sorted in ascending order. If you call the function second time - sorting will be removed. - sortDesc
function
which acceptsheader
value as input, whereheader
is an item fromheaders
prop array which is bound toDataTable
. When called, providedheader
column data will be sorted in descending order. If you call the function second time - sorting will be removed. - sortNone
function
which acceptsheader
value as input, whereheader
is an item fromheaders
prop array which is bound toDataTable
. When called - it removes sorting for providedheader
column. - sortedHeaders
object
of currently sorted headers as keys andasc
ordesc
strings as values.
Important
Please note that if you implement header functionality by yourself, you still must provide headers
prop to DataTable
, otherwise
sorting will not work correctly.
Name
↑
↓
|
Surname
↑
↓
|
Age
↑
↓
|
Email
↑
↓
|
---|---|---|---|
John | Manager | 43 | john@doe.com |
Maryl | Piper | 56 | maryl@doe.com |
Lucy | Martin | 29 | lucy@doe.com |
Vinnie | Parker | 71 | vinnie@doe.com |
Alex | Maxwell | 66 | alex@doe.com |
<DataTable :data="dataTable1" :headers="dataTableHeaders1" show-filter-buttons>
<template v-slot:header="{sortAsc, sortDesc, sortNone, sortedHeaders}">
<Cell
is-header
class="bg-default text-white"
v-for="header in dataTableHeaders1">
<span>
{{header}}
</span>
<span
@click="sortAsc(header)"
:class="[sortedHeaders[header] === 'asc'?'text-white':'color-gray-600', 'cursor-pointer']">
↑
</span>
<span
@click="sortDesc(header)"
:class="[sortedHeaders[header] === 'desc'?'text-white':'color-gray-600', 'cursor-pointer']">
↓
</span>
</Cell>
</template>
</DataTable>
<script>
export default {
data(){
return {
dataTable1:[
['John', 'Manager', 43, 'john@doe.com'],
['Maryl', 'Piper', 56, 'maryl@doe.com'],
['Lucy', 'Martin', 29, 'lucy@doe.com'],
['Vinnie', 'Parker', 71, 'vinnie@doe.com'],
['Alex', 'Maxwell', 66, 'alex@doe.com'],
],
dataTableHeaders1:['Name', 'Surname', 'Age', 'Email'],
};
},
}
</script>
# Searching in table
You can provide searchKeyword
prop in order to filter and search for data inside DataTable
. Simply bind same variable to your preferred
source of input and searchKeyword
and data inside the table will be filtered based on value of searchKeyword
Name
|
Surname
|
Age
|
Email
|
---|---|---|---|
John | Manager | 43 | john@doe.com |
Maryl | Piper | 56 | maryl@doe.com |
Lucy | Martin | 29 | lucy@doe.com |
Vinnie | Parker | 71 | vinnie@doe.com |
Alex | Maxwell | 66 | alex@doe.com |
<Input v-model="searchKeywordVariable" label="Enter your search keyword" class="mt-5" />
<DataTable :search-keyword="searchKeywordVariable" :data="dataTable1" :headers="dataTableHeaders1" show-filter-buttons />
# Advanced tables
You might want to build more advanced tables, maybe have some special content for specific table column. In such cases
it is worth to note that you can use default
slot and build table content by yourself. The default
slot is used in v-for
loop
to build each table row and receives these slot props:
- row - this is an
Array
or row items fromdata
, you would use this to run anotherv-for
loop to build theCell
s. - rowKey - this is an actual index of
row
item fromdata
Array. - rowKeyViewport - this is the index of row in currently displayed data.
You can also utilize pagination by using perPage
prop to set how many rows the table should display, currentPage
to
calculate which page of data should be shown based on perPage
. You could attach variables to these props and other components like
Select
or Input
to control how many rows per page are show, and use Pagination
to show pagination.
Name
|
Email
|
Phone
|
Website
|
Status
|
Income
| |
---|---|---|---|---|---|---|
Myrtis Abernathy | nienow.dedrick@walsh.com | 748-753-1935 | johnston.com |
Ongoing
| $13462 | |
Kaycee Hill | isabelle.barton@prosacco.net | (350) 610-7314 | schinner.info |
Closed
| $7475 | |
Hans Renner | cruz76@gmail.com | (702) 444-9314 | torphy.biz |
Ongoing
| $23970 | |
Kayla Hackett | jeramie.ferry@gmail.com | (391) 452-3093 x56058 | marvin.biz |
Closed
| $22482 | |
Dr. Desiree Sporer I | macejkovic.eugene@gmail.com | 867-659-7813 x663 | sipes.com |
Closed
| $17537 | |
Isom Swaniawski | charlotte00@lindgren.info | +1-996-225-5804 | lubowitz.com |
Ongoing
| $12458 | |
Maximilian Hamill | thessel@botsford.com | 708-636-3806 x1998 | labadie.org |
Ongoing
| $1082 | |
Magdalen Gulgowski | chills@kutch.info | 813-987-5942 x7453 | miller.net |
Closed
| $19323 | |
Lenore Hoeger | antoinette.schaefer@yahoo.com | 1-637-467-8365 | conn.com |
Ongoing
| $9441 | |
Rashawn Lockman | rosalind06@schuppe.com | 1-743-838-7810 | spinka.com |
Lead
| $21814 |
Rows per page
<Card body-classes="">
<template v-slot:header>
<div class="d-flex align-items-center justify-content-between">
<span>Data Tables</span>
<Input v-model="dataTableSearch" size="sm" placeholder="Filter table data" class="mb-0 w-25"/>
</div>
</template>
<div>
<DataTable class="table-bordered" show-filter-buttons :data="dataTable" :headers="dataTableHeaders"
:search-keyword="dataTableSearch" :per-page="dataTablePerPage" :current-page="dataTablePage">
<template v-slot:default="{row, rowKey, rowKeyViewport}">
<Cell
v-for="(cellData, key) in row"
:cell-classes="[
// Center
['selected', 'status'].indexOf(key.toString().toLowerCase()) !== -1?'d-flex justify-content-center':'',
]"
:class="[
{'bg-info-light':dataTable[rowKey].Selected===true},
]">
<Badge v-if="key.toString().toLowerCase() === 'status' || key === 4" pill :type="getPillByStatus(cellData)">
{{cellData}}
</Badge>
<Checkbox v-else-if="key.toString().toLowerCase() === 'selected'"
v-model="dataTable[rowKey].Selected"></Checkbox>
<span v-else>{{cellData}}</span>
</Cell>
</template>
</DataTable>
</div>
<div class="d-flex flex-wrap pt-3 pb-4 align-items-end mx-4 justify-content-end">
<div class="mr-sm-4 mb-sm-0 mb-3">
<p class="mb-2 small">Rows per page</p>
<Select :data="[5, 10, 15, 25, 100]" :selected="dataTablePerPage"
@change="dataTablePerPage = $event,dataTablePage = 1"></Select>
</div>
<div>
<Pagination v-model="dataTablePage" :pages="Math.ceil(dataTable.length/dataTablePerPage)">
<template v-slot:next>
Next
</template>
<template v-slot:previous>
Prev
</template>
</Pagination>
</div>
</div>
</Card>
Note
You can use null
as header array item when you don't want to display anything in specific header column.
Name
|
Surname
|
Age
|
Email
|
---|---|---|---|
John | Manager | 43 | john@doe.com |
Maryl | Piper | 56 | maryl@doe.com |
Lucy | Martin | 29 | lucy@doe.com |
Vinnie | Parker | 71 | vinnie@doe.com |
Alex | Maxwell | 66 | alex@doe.com |
# Props
name | default | description | required | type |
---|---|---|---|---|
data | Array of Array (rows x cols) data points that will be rendered as table rows. Array elements can be of any type, they will be provided as scoped slot prop in row slot. | true | Array | |
headers | Array of strings (can be other types too) that will be used to display headers. Will be provided as slot prop for header slot. | false | Array | |
perPage | 15 | Number of rows per page | false | 0 |
showAll | false | If set to true, showSize, currentPage and other pagination props will be ignored and all table rows will be displayed | false | Boolean |
currentPage | 1 | Current page that should be displayed | false | Number |
searchKeyword | If searchKeyword is provided - table rows will be filtered based on provided value. If value is available in any of row elements - row will be shown, otherwise - hidden | false | String | |
showFilterButtons | false | If set to true - table head rows will show ordering buttons. Default is false. | false | Boolean |