Vue 3 Easy Table
A simple and highly customizable component for creating data tables based on plugins.
Table of Contents
- Installation
- Usage
Installation
NPM
npm install vue3-easy-table --save
Usage
Register globally
First, register the full components in your app entry point (app.js
) .
import { createApp} from 'vue'
import App from './App.vue'
import EasyTable from 'vue3-easy.table'
// Import de default theme, or you can create your own custom theme
import 'vue3-easy-table/themes/default.css'
...
createApp(App)
.use(EasyTable)
.mount('#app')
Or also you can register components individually.
import { createApp} from 'vue'
import App from './App.vue'
import {
useEasyDataTable,
useEasyPaginator,
useEasySortFilter,
useEasyTotalizer
} from 'vue3-easy.table'
// Import de default theme, or you can create your own custom theme
import 'vue3-easy-table/themes/default.css'
...
createApp(App)
.use(useEasyDataTable)
.use(useEasyPaginator)
.use(useEasySortFilter)
.use(useEasyTotalizer)
.mount('#app')
Next, use it on your template
Basic Example
<template>
<div class="overflow-x-auto w-full">
<e-data-table
:headers="headers"
:items="items"
:is-loading="loading">
</e-data-table>
</div>
</template>
<script>
export default {
data() {
return {
headers: [
{ label: 'Id', key: 'id'},
{ label: 'Username', key: 'username'},
{ label: 'Full Name', key: 'fullName'},
{ label: 'Amount', key: 'amount', formatter: (value) => `$${value}` },
],
items: [
{ id: 1, username: 'Octavius Rex', fullName: 'Octavius Rex', amount: 1000 },
{ id: 2, username: 'spongebob', fullName: 'Sponge Bob Squarepants', amount: 1500 },
{ id: 3, username: 'patrickstar', fullName: 'Patrick Star', amount: 1020 },
{ id: 4, username: 'sandycheeks', fullName: 'Sandy Cheeks', amount: 800 },
{ id: 5, username: 'eugenekrabs', fullName: 'Eugene H. Krabs', amount: 950 },
{ id: 6, username: 'sheldonplankton', fullName: 'Sheldon J. Plankton', amount: 300 },
],
isLoading: false
}
}
}
</script>
<style>
</style>
Advanced Example
<template>
<div>
<e-keyword-filter v-model:filtered="filtered" :original="items"></e-keyword-filter>
<e-data-table
:headers="headers"
:items="filtered"
:is-loading="isLoading"
:current-page="currentPage"
v-model:total-items="totalItems"
:per-page="perPage"
rowStyle="link"
@row-click="showUser">
<template v-slot:header[default]="{ header }">
{{ header.label }}
<e-sort-filter :key-param="header.key" v-model:sort-by="sortBy" v-model:sort-desc="sortDesc" v-model:filtered="filtered"/>
</template>
<template v-slot:cell[username]="{ cell }">
<div class="flex items-center">
<span>{{ `${cell.item.username}` }}</span>
</div>
</template>
<template v-slot:footer[amount]="{ footer }">
<e-totalizer :key-column="footer.key" :items="filtered" :formatter="footer.formatter"/>
</template>
</e-data-table>
<div class="mt-auto">
<e-paginator v-model:current-page="currentPage" v-model:total-items="totalItems" v-model:per-page="perPage" />
</div>
</div>
</template>
<script>
export default {
data() {
return {
headers: [
{ label: 'Id', key: 'id'},
{ label: 'Username', key: 'username'},
{ label: 'Full Name', key: 'fullName'},
{ label: 'Amount', key: 'amount', formatter: (value) => `$${value}` },
],
items: [
{ id: 1, username: 'Octavius Rex', fullName: 'Octavius Rex', amount: 1000 },
{ id: 2, username: 'spongebob', fullName: 'Sponge Bob Squarepants', amount: 1500 },
{ id: 3, username: 'patrickstar', fullName: 'Patrick Star', amount: 1020 },
{ id: 4, username: 'sandycheeks', fullName: 'Sandy Cheeks', amount: 800 },
{ id: 5, username: 'eugenekrabs', fullName: 'Eugene H. Krabs', amount: 950 },
{ id: 6, username: 'sheldonplankton', fullName: 'Sheldon J. Plankton', amount: 300 },
],
filtered: [],
isLoading: false,
perPage: 3,
totalItems: 0,
currentPage: 1,
sortBy: 'username',
sortDesc: false,
}
},
methods: {
showUser(user) {
alert(user.fullName)
}
}
}
</script>
<style>
</style>
Translation
This feature is still under development and there are still translations to be made, you can configure the language that will be displayed by certain components, to use the component translation you must import the translation file and configure it in the entry point of your application..
import { createApp } from 'vue'
import App from './App.vue'
import EasyTable from 'vue3-easy.table'
// Import de default theme, or you can create your own custom theme
import 'vue3-easy-table/themes/default.css'
import es from 'vue3-easy-table/src/lang/es'
changeLang(es)
...
createApp(App)
.use(EasyTable)
.mount('#app')
Configuring the components
Vue3 Easy Table includes components that offer a large number of properties for your configuration.
Data Table
The data table is the main component that displays a table with the data that it receives by parameter.
Data Table Props
headers
Sets an object that allows you to configure the table headers.
type:Array
required:true
/*
* You can configure each header individually.
* label: The label to be displayed in the column header
* username: The name of the item's parameter
* formatter: Optionally you can include a function that formats the value that is passed to the cell
* width: Optinally you can indicate the width of the column on a string, ex: '20%', '50px', '2.5rem'
* aligment: Optionally you can indicate de column aligment on a string, ex: 'left', 'center', 'right'
*/
[
{ label: 'Id', key: 'id', width: '20px'},
{ label: 'Userbaname', key: 'username'},
{ label: 'Full Name', key: 'fullName'},
{ label: 'Amount', key: 'amount', formatter: (value) => `$${value}`, aligment: 'right' },
]
row-style
Specify a function that returns a string with the name of the class to apply depending on what is evaluated within the function, the item of the row is passed as the first parameter of the function.
type: Function
default: (item) => ''
const rowStyle = (item) => item.isDeleted ? 'item-deleted-class' : ''
items
It is the collection of data that wjjkill be iterated in the table.
type: Array
required: true
[
{ id: 1, username: 'Octavius Rex', fullName: 'Octavius Rex', amount: 1000 },
{ id: 2, username: 'spongebob', fullName: 'Sponge Bob Squarepants', amount: 1500 },
{ id: 3, username: 'patrickstar', fullName: 'Patrick Star', amount: 1020 },
{ id: 4, username: 'sandycheeks', fullName: 'Sandy Cheeks', amount: 800 },
{ id: 5, username: 'eugenekrabs', fullName: 'Eugene H. Krabs', amount: 950 },
{ id: 6, username: 'sheldonplankton', fullName: 'Sheldon J. Plankton', amount: 300 },
]
is-loading
Allows you to specify if the table is in loading state or not.
type: Boolean
default: false
isLoading: true
current-page
Indicates the current page number where the pagination is located.
type: Number
default: 1
currentPage: 5 // Show de items in the page 5
per-page
Indicates the number of pages to be displayed in the table.
type: Number
default: 15
perPage: 15
empty-label
The text that will appear in the table when it is empty and there is no slot already applied.
type: String
default: Empty
emptyLabel: 'Empty Table'
Data Table Events
@row-clicked
The event is fired when a row is clicked.
Data Table Slots
You can customize the content within the headers, cells, feet, through the slots.
To refer to a specific slot you can use the syntax:
v-slot:header[headerKey]
v-slot:cell[headerKey]
v-slot:footer[headerKey]
Without wanting to set a slot for everyone you can use the default slot that will be mounted by default
v-slot:header[default]
v-slot:cell[default]
v-slot:footer[default]
You can customize the message that appears when the table is empty with the slot v-slot:cell[empty]
.
v-slot:cell[default]
<!-- Header template -->
<template v-slot:header[default]="{ header }">
{{ header.label }}
<e-sort-filter :key-param="header.key" v-model:sort-by="sortBy" v-model:sort-desc="sortDesc" v-model:items="items"/>
</template>
<!-- Cell template -->
<template v-slot:cell[username]="{ cell }">
<div class="flex items-center">
<span>{{ `${cell.item.username}` }}</span>
</div>
</template>
<!-- Emtpy template -->
<template v-slot:cell[empty]>
<div class="flex items-center">
<span>Empty table</span>
</div>
</template>
<!-- Footer template -->
<template v-slot:footer[amount]="{ footer }">
<e-totalizer :key-column="footer.key" :items="items" :formatter="footer.formatter"/>
</template>
Data Table Theming
You can fully customize the plugin with the classes it includes.
.et-container {
width: 100%;
border-style: solid;
border-width: 1px;
border-radius: .8rem;
border-color: #191919;
overflow: hidden;
}
.et-container .et-table {
position: relative;
width: 100%;
border-collapse: collapse;
}
.et-container .et-table.loading {
opacity: 50%;
}
.et-container .et-table-header {
position: sticky;
top: 0;
background-color: #e4e3e5;
}
.et-container .et-table-header-container {
display: flex;
padding: 0.2rem 1rem;
height: 100%;
justify-content: center;
align-items: center;
padding: .2rem 2rem;
}
.et-container .et-table-cell {
font-size: 1rem;
text-align: center;
}
.et-container .et-table-body-row.et-table-row-link {
cursor: pointer;
}
.et-container .et-table-body-row.et-table-row-link:hover {
background-color: #b5b5b5;
box-shadow: 0 0 0 0 #333333;
transition: all .3s ease;
}
.et-container .et-table-cell-container {
display: flex;
padding: 1rem 2rem;
}
Keyword Filter
Plugin that allows you to filter the items by a keyword.
Keyword Filter Props
filtered
It must be an empty array that the filter will use as temporary, keep in mind that the collection is not modified instead a copy of the original collection is created.
type: Array
required: true
filtered: []
original
It is the original collection to which the filter is applied.
type: Array
required: true
[
{ id: 1, username: 'Octavius Rex', fullName: 'Octavius Rex', amount: 1000 },
{ id: 2, username: 'spongebob', fullName: 'Sponge Bob Squarepants', amount: 1500 },
{ id: 3, username: 'patrickstar', fullName: 'Patrick Star', amount: 1020 },
]
placeholder
The text to display in the placeholder.
type: String
default: Search
placeholder: 'Search item'
Keyword Filter Theming
You can fully customize the plugin with the classes it includes.
.et-keyword {
padding: .5rem;
}
.et-keyword .et-keyword-input
{
padding: .5rem;
border-radius: .5rem;
border: none;
}
Sort Filter
Plugin that allows you to sort the items within the array by a given key in ascending or descending order.
Sort Filter Props
filtered
Collection of data that the filter will sort, keep in mind that the filter will modify the original collection.
type: Array
required: true
[
{ id: 1, username: 'Octavius Rex', fullName: 'Octavius Rex', amount: 1000 },
{ id: 2, username: 'spongebob', fullName: 'Sponge Bob Squarepants', amount: 1500 },
{ id: 3, username: 'patrickstar', fullName: 'Patrick Star', amount: 1020 },
]
header
The column header, the filter will look for the meta.isSortable parameter to verify if the column can apply the filter or not, to deactivate the filter in a specific column the value must be false.
type: Object
required: false
/* In the headers object */
[
{ label: 'Id', key: 'id', width: '20px', meta: { isSortable: false }},
...
]
key-param
The key of the current column on which the plugin will act.
type: String
required: true
keyParam: 'username'
sort-by
The key of the column by which the plugin should sort.
type: String
required: true
sortBy: 'username'
sort-desc
Direction in which the items should be ordered.
type: Boolean
required: true
sortDesc: true
Sort Filter Slots
You can customize the content of the component such as the ordering buttons in ascending, descending order or when the filter is not applied in that column.
v-slot:neutral-button
v-slot:desc-button
v-slot:desc-button
<!-- Neutral Button template -->
<template #neutral-button>
<fa-icon icon="sort"/>
</template>
<!-- Desc Button template -->
<template #desc-button>
<fa-icon icon="sort-down"/>
</template>
<!-- Asc Button template -->
<template #asc-button>
<fa-icon icon="sort-up"/>
</template>
Sort Filter Theming
You can fully customize the plugin with the classes it includes.
.et-sorter
{
display: flex;
justify-content: center;
margin-left: 1rem;
margin: 0.2rem 1rem;
border-radius: .3rem;
transition: all .3s ease;
border: none;
padding: .2rem .5rem;
}
.et-sorter:hover,
.et-sorter:active
{
background-color: #b5b5b5;
}
.et-sorter.neutral
{
width: 100%;
color: #333333;
}
Paginator
Plugin that allows you to control the pagination of a table.
Paginator Props
current-page
Indicates the current page that the component should show as marked.
type: Number
default: 1
currentPage: 1
total-items
The total number of items in the data collection, this data is used so that the plugin can calculate the number of pages.
type: Number
required: true
totalItems: 150
per-page
The number of items displayed per page, the plugin uses this data to calculate the number of pages.
type: Number
required: true
perPage: 15
offset
The maximum number of pages to be displayed.
type: Boolean
default: 5
offset: 5
Paginator Slots
You can customize the paging content such as the forward, backward or go to the page buttons through the slots that it includes.
v-slot:prev
v-slot:page
v-slot:next
<!-- Prev Button template -->
<template #prev>
<fa-icon icon="angle-left"/>
</template>
<!-- Page Button template -->
<template #page="{ page }">
<span>{{ page }}</span>
</template>
<!-- Next Button template -->
<template #next>
<fa-icon icon="angle-right"/>
</template>
Paginator Theming
You can fully customize the plugin with the classes it includes.
.et-paginator
{
display: flex;
flex-direction: row-reverse;
}
.et-paginator .et-paginator-container
{
display: flex;
margin: 1rem auto;
border-width: 1px;
border-style: solid;
border-color:#333333;
border-radius: .3rem;
overflow: hidden;
}
.et-paginator .nav-button
{
padding: .2rem 1rem;
border-right: 1px solid #333333;
outline: none;
background-color: transparent;
}
.et-paginator .nav-button.pre
{
padding: .2rme 1rem;
border-right: 1px solid #333333;
outline: none
}
.et-paginator .nav-button.next
{
border: none;
}
.et-paginator .nav-button:hover {
background-color: #b5b5b5;
}
.et-paginator .nav-button.active {
background-color: #05308c;
color: white;
border: 1px solid #05308c;
}
Totalizer
Complement that calculates the total, of a column, keep in mind that if there are other filters applied, all the filtered items will be added.
Totalizer Props
key-column
The key of the column to be totaled.
type: String
required: true
keyColumn: 'amount'
items
The filtered data collection.
type: Array
required: true
[
{ id: 1, username: 'Octavius Rex', fullName: 'Octavius Rex', amount: 1000 },
{ id: 2, username: 'spongebob', fullName: 'Sponge Bob Squarepants', amount: 1500 },
{ id: 3, username: 'patrickstar', fullName: 'Patrick Star', amount: 1020 },
]
formatter
The formatting function that will be applied to the footer.
type: Function
required: false
formatter: (value) => value.toLowerCase()
Totalizer Theming
You can fully customize the plugin with the classes it includes.
.et-totalizer {
font-weight: bold;
text-align: center;
}
Page Number
Add-in that displays table information such as total number of records, current page, and number of pages in the table..
Page Number Props
current-page
Indicates the current page that the component should show.
type: Number
default: 1
currentPage: 1
total-items
The total number of items in the data collection, this data is used so that the plugin can calculate the number of pages.
type: Number
required: true
totalItems: 150
per-page
The number of items displayed per page, the plugin uses this data to calculate the number of pages.
type: Number
required: true
perPage: 15
Page Number Theming
You can fully customize the plugin with the classes it includes.
.et-page-number { /* Wrapper */ }
.et-totalizer .et-total-items { /* Label that show de total items */ }
.et-totalizer .et-pipe-separator { /* Separator caracter */ }
.et-totalizer .et-current-page { /* Label that show de current page */ }
.et-totalizer .et-page-separator { /* Separator page normally "of" */ }
.et-totalizer .et-total-pages { /* Label that show de total pages */ }