Vue-good-table
A simple, clean data table for VueJS with essential features like sorting, column filtering, pagination etc
Did vue-good-table just save you a bunch of time? Use some of them extra minutes to spread the joy!
Upgrade Guide
Hey there! coming from 1.x? find the upgrade guide here
Basic Table
Table with grouped rows and column filters
Recipes
Some example recipes for inspiration vue-good-table Recipes
Table of contents
- Getting Started
- Configuration
- Theme
- Advanced Customization
- Authors
- License
Getting Started
Installing
Install with npm:
npm install --save vue-good-table
Import into project:
import Vue from 'vue';
import VueGoodTable from 'vue-good-table';
// import the styles
import 'vue-good-table/dist/vue-good-table.css'
Vue.use(VueGoodTable);
Example Usage
<template>
<div>
<vue-good-table
:columns="columns"
:rows="rows"
:search-options="{
enabled: true,
}"
:pagination-options="{
enabled: true,
perPage: 5,
}"
styleClass="vgt-table striped bordered"/>
</div>
</template>
<script>
export default {
name: 'my-component',
data(){
return {
columns: [
{
label: 'Name',
field: 'name',
filterOptions: {
enabled: true,
},
},
{
label: 'Age',
field: 'age',
type: 'number',
},
{
label: 'Created On',
field: 'createdAt',
type: 'date',
dateInputFormat: 'YYYY-MM-DD',
dateOutputFormat: 'MMM Do YY',
},
{
label: 'Percent',
field: 'score',
type: 'percentage',
},
],
rows: [
{ id:1, name:"John", age: 20, createdAt: '201-10-31:9: 35 am',score: 0.03343 },
{ id:2, name:"Jane", age: 24, createdAt: '2011-10-31', score: 0.03343 },
{ id:3, name:"Susan", age: 16, createdAt: '2011-10-30', score: 0.03343 },
{ id:4, name:"Chris", age: 55, createdAt: '2011-10-11', score: 0.03343 },
{ id:5, name:"Dan", age: 40, createdAt: '2011-10-21', score: 0.03343 },
{ id:6, name:"John", age: 20, createdAt: '2011-10-31', score: 0.03343 },
{ id:7, name:"Jane", age: 24, createdAt: '20111031' },
{ id:8, name:"Susan", age: 16, createdAt: '2013-10-31', score: 0.03343 },
],
};
},
};
</script>
This should result in the screenshot seen above
Configuration
Component Options
Table
These options relate to the table as a whole
Array
columns Array containing objects that describe table columns. The column object itself can contain many configurable properties.
[
{
label: 'Name',
field: 'name',
filterable: true,
}
//...
]
Array
rows Array containing row objects. Each row object contains data that will be displayed in the table row.
[
{
id:1,
name:"John",
age:20
},
//...
]
for grouped rows, you need a nested format. Refer to Grouped Rows for an example.
Boolean (default: false)
rtl Enable Right-To-Left layout for the table
<vue-good-table
:columns="columns"
:rows="rows"
:rtl="true">
</vue-good-table>
Boolean (default: false)
lineNumbers Show line number for each row
<vue-good-table
:columns="columns"
:rows="rows"
:lineNumbers="true">
</vue-good-table>
Sort Options
Set of options related to table sorting
<vue-good-table
:columns="columns"
:rows="rows"
:sort-options="{
enabled: true,
initialSortBy: {field: 'name', type: 'asc'}
}">
</vue-good-table>
Boolean (default: true)
sortOptions.enabled Enable/disable sorting on table as a whole.
<vue-good-table
:columns="columns"
:rows="rows"
:sort-options="{
enabled: true,
}">
</vue-good-table>
Object
sortOptions.initialSortBy Allows specifying a default sort for the table on wakeup
<vue-good-table
:columns="columns"
:rows="rows"
:sort-options="{
enabled: true,
initialSortBy: {field: 'name', type: 'asc'}
}">
</vue-good-table>
// in data
defaultSort: {
field: 'name',
type: 'asc' //asc or desc (default: 'asc')
}
Pagination Options
A set of options that are related to table pagination. Each of these are optional and reasonable defaults will be used if you leave off the property.
<vue-good-table
:columns="columns"
:rows="rows"
:paginationOptions="{
enabled: true,
perPage: 5,
position: 'top',
perPageDropdown: [3, 7, 9],
dropdownAllowAll: false,
setCurrentPage: 2,
nextLabel: 'next',
prevLabel: 'prev',
rowsPerPageLabel: 'Rows per page',
ofLabel: 'of',
allLabel: 'All',
}">
</vue-good-table>
Options explained below
Boolean (default: false)
paginationOptions.enabled Enable Pagination for table. By default the paginator is created at the bottom of the table.
<vue-good-table
:columns="columns"
:rows="rows"
:paginationOptions="{
enabled: true
}">
</vue-good-table>
String (default: 'bottom')
paginationOptions.position Add pagination on 'top'
, 'bottom'
, or 'both'
(top and bottom) of the table (default position is bottom)
<vue-good-table
:columns="columns"
:rows="rows"
:paginationOptions="{
enabled: true,
position: 'both'
}">
</vue-good-table>
Integer (default: 10)
paginationOptions.perPage Number of rows to show per page
<vue-good-table
:columns="columns"
:rows="rows"
:paginationOptions="{
enabled: true,
perPage: 5
}">
</vue-good-table>
Array (default: [10,20,30,40,50])
paginationOptions.perPageDropdown Customize the dropdown options for the amount of items per page
<vue-good-table
:columns="columns"
:rows="rows"
:paginationOptions="{
enabled: true,
perPageDropdown: [3, 7, 9]
}">
</vue-good-table>
Boolean (default: true)
paginationOptions.dropdownAllowAll enables/disables 'All' in the per page dropdown.
<vue-good-table
:columns="columns"
:rows="rows"
:paginationOptions="{
enabled: true,
perPageDropdown: [3, 7, 9],
dropdownAllowAll: false,
}">
</vue-good-table>
Number
paginationOptions.setCurrentPage set current page programmatically.
There's no validation for number of pages so please be careful using this.
<vue-good-table
:columns="columns"
:rows="rows"
:paginationOptions="{
enabled: true,
setCurrentPage: 2,
}">
</vue-good-table>
pagination label/text options
you can change one or more of the texts shown on pagination by overriding the labels in the following way:
<vue-good-table
:columns="columns"
:rows="rows"
:paginationOptions="{
enabled: true,
nextLabel: 'next',
prevLabel: 'prev',
rowsPerPageLabel: 'Rows per page',
ofLabel: 'of',
allLabel: 'All',
}">
</vue-good-table>
Search Options
Set of search related options. These options pertain to the global table search.
<vue-good-table
:columns="columns"
:rows="rows"
:searchOptions="{
enabled: true,
trigger: 'enter',
searchFn: mySearchFn,
placeholder: 'Search this table',
externalQuery: searchQuery
}">
</vue-good-table>
Search options explained below
Boolean (default: false)
searchOptions.enabled Allows a single search input for the whole table
Note: enabling this option disables column filters
<vue-good-table
:columns="columns"
:rows="rows"
:searchOptions="{
enabled: true
}">
</vue-good-table>
String (default: '')
searchOptions.trigger Allows you to specify if you want search to trigger on 'enter' event of the input. By default table searches on key-up.
<vue-good-table
:columns="columns"
:rows="rows"
:searchOptions="{
enabled: true,
trigger: 'enter'
}">
</vue-good-table>
Function
searchOptions.searchFn Allows you to specify your own search function for the global search
<vue-good-table
:columns="columns"
:rows="rows"
:searchOptions="{
enabled: true,
searchFn: myFunc
}">
</vue-good-table>
// in js
methods: {
myFunc(row, col, cellValue, searchTerm){
return cellValue === 'my value';
},
}
String (default: 'Search Table')
searchOptions.placeholder Text for global search input place holder
<vue-good-table
:columns="columns"
:rows="rows"
:searchOptions="{
enabled: true,
placeholder: 'Search this table',
}">
</vue-good-table>
String
searchOptions.externalQuery If you want to use your own input for searching the table, you can use this property
<input type="text" v-model="searchTerm" >
<vue-good-table
:columns="columns"
:rows="rows"
:searchOptions="{
enabled: true,
externalQuery: searchTerm
}">
</vue-good-table>
// and in data
data(){
return {
searchTerm: '',
// rows, columns etc...
};
}
Checkbox Table
Creating table with selectable rows (checkboxes) is easier than ever.
Object
selectOptions Object containing select options
<vue-good-table
@on-select-all="allSelected"
@on-row-click="rowSelected"
:columns="columns"
:rows="rows"
:select-options="{
enabled: true,
selectionInfoClass: 'custom-class',
selectionText: 'rows selected',
clearSelectionText: 'clear',
}">
you can also programmatically get selected rows at any time by putting a ref
on the table and then doing
this.$refs['my-table'].selectedRows;
Check out a working example for details
Grouped Row Options
Sometimes you have a hierarchy in table and you want to group rows under subheadings, vue-good-table allows you to do that as well. Following properties relate to row grouping
Object
groupOptions Object containing group related options.
<vue-good-table
:columns="columns"
:rows="rows"
:group-options="{
enabled: true,
headerPosition: 'bottom'
}">
rows are formatted differently for grouped tables, refer to Grouped Rows section.
Style/Theme
Style options for table
String (default: 'vgt-table bordered')
styleClass Allows applying your own classes to table. Other in-built classes: condensed, striped, bordered
<vue-good-table
:columns="columns"
:rows="rows"
styleClass="vgt-table bordered striped">
</vue-good-table>
String or Function
rowStyleClass Allows providing custom styles for rows. It can be a string: 'my-class' or a function.
<vue-good-table
:columns="columns"
:rows="rows"
:rowStyleClass="myStyleFn">
</vue-good-table>
// in methods
myStyleFn(row){
// if row has something return a specific class
if(row.fancy) {
return 'fancy-class';
}
return '';
}
String
theme Allows using other themes. Currently there is one other theme - 'nocturnal'
<vue-good-table
:columns="columns"
:rows="rows"
theme="nocturnal">
</vue-good-table>
Column Options
Each column objects can contain the following configuration options:
String
label Text to put on column header.
columns: [
{
label: 'name'
},
// ...
]
String
field Row object property that this column corresponds to. This can be:
- String
eg: 'name'
- simple row property name - String
eg: 'location.lat'
- nested row property name. lets say if the row had a property 'location' which was an object containing 'lat' and 'lon' - Function - a function that returns a value to be displayed based on the row object
columns: [
{
label: 'name',
field: this.fealdFn,
},
// ...
]
// in methods
fieldFn(rowObj) {
return rowObj.name;
}
String
type type of column. default: 'text'. This determines the formatting for the column and filter behavior as well. Possible values:
- number - right aligned
- decimal - right aligned, 2 decimal places
- percentage - expects a decimal like 0.03 and formats it as 3.00%
- date - expects a string representation of date eg
'20170530'
. You should also specify dateInputFormat and dateOutputFormat
columns: [
{
label: 'joined On',
field: 'createdAt',
type: 'date',
dateInputFormat: 'YYYY-MM-DD', // expects 2018-03-16
dateOutputFormat: 'MMM Do YYYY', // outputs Mar 16th 2018
},
// ...
]
String
dateInputFormat provide the format to parse date string
String
dateOutputFormat provide the format for output date
Boolean
sortable enable/disable sorting on columns. This property is higher priority than global sortable property
columns: [
{
label: 'name',
field: 'user_name',
sortable: false,
},
// ...
]
Function
sortFn custom sort function. If you want to supply your own sort function you can use this property.
// in data
column: [
{
label: 'Name',
field: 'name',
sortable: true,
sortFn: this.sortFn,
}
//...
],
// in methods
methods: {
sortFn(x, y, col, rowX, rowY) {
// x - row1 value for column
// y - row2 value for column
// col - column being sorted
// rowX - row object for row1
// rowY - row object for row2
return (x < y ? -1 : (x > y ? 1 : 0));
}
}
Function
formatFn Allows for custom format of values, function(value)
, should return the formatted value to display.
// in data
column: [
{
label: 'Salary',
field: 'salary',
sortable: true,
formatFn: this.formatFn,
}
//...
],
// in methods
formatFn: function(value) {
return '$' + value;
}
Boolean
html indicates whether this column will require html rendering.
The preferred way of creating columns that have html is by using slots
// in data
column: [
{
label: 'Action',
field: 'btn',
html: true,
}
//...
],
rows: [
{
btn: '<button>My Action</button>',
// ...
}
]
Number
width provide a width value for this column
columns: [
{
label: 'name',
field: 'user_name',
width: '50px',
},
// ...
]
Boolean
hidden hide a column
columns: [
{
label: 'name',
field: 'user_name',
hidden: true,
},
// ...
]
String
thClass provide custom class(es) to the table header
columns: [
{
label: 'name',
field: 'user_name',
thClass: 'custom-th-class',
},
// ...
]
String
tdClass provide custom class(es) to the table cells
columns: [
{
label: 'name',
field: 'user_name',
tdClass: 'text-center',
},
// ...
]
Boolean (default: false)
globalSearchDisabled if true, this column will be ignored by the global search
columns: [
{
label: 'name',
field: 'user_name',
globalSearchDisabled: true,
},
// ...
]
Object
filterOptions A collection of filter specific properties. You can find more about these properties in column filter options section
columns: [
{
label: 'name',
field: 'user_name',
filterOptions: {
enabled: true, // enable filter for this column
placeholder: 'Filter This Thing', // placeholder for filter input
filterValue: 'Jane', // initial populated value for this filter
filterDropdownItems: [], // dropdown (with selected values) instead of text input
filterFn: this.columnFilterFn, //custom filter function that
},
},
// ...
]
Column filter option in-depth
Some filterOption properties need a little more explanation
Array of strings or Array of objects
filterDropdownItems allows creating a dropdown for filter as opposed to an input
//array
filterDropdownItems: ['Blue', 'Red', 'Yellow']
//or
filterDropdownItems: [
{ value: 'n', text: 'Inactive' },
{ value: 'y', text: 'Active' },
{ value: 'c', text: 'Check' }
],
Function
filterFn Custom filter, function of two variables: function(data, filterString)
, should return true if data matches the filterString, otherwise false
filterFn: function(data, filterString) {
var x = parseInt(filterString)
return data >= x - 5 && data <= x + 5;
}
// would create a filter matching numbers within 5 of the provided value
Table Events
@on-row-click
event emitted on table row click
<vue-good-table
:columns="columns"
:rows="rows"
@on-row-click="onRowClick">
methods: {
onRowClick(params) {
// params.row - row object
// params.pageIndex - index of this row on the current page.
// params.selected - if selection is enabled this argument
// indicates selected or not
}
}
@on-cell-click
event emitted on table cell click
<vue-good-table
:columns="columns"
:rows="rows"
@on-cell-click="onCellClick">
methods: {
onCellClick(params) {
// params.row - row object
// params.column - column object
// params.rowIndex - index of this row on the current page.
}
}
@on-row-mouseenter
event emitted on row mouseenter
<vue-good-table
:columns="columns"
:rows="rows"
@on-row-mouseenter="onRowMouseover">
methods: {
onRowMouseover(params) {
// params.row - row object
// params.pageIndex - index of this row on the current page.
}
}
@on-row-mouseleave
event emitted on table row mouseleave
<vue-good-table
:columns="columns"
:rows="rows"
@on-row-mouseleave="onRowMouseleave">
methods: {
onRowMouseleave(row, pageIndex) {
// row - row object
// pageIndex - index of this row on the current page.
}
}
@on-search
event emitted on global search (when global search is enabled)
<vue-good-table
:columns="columns"
:rows="rows"
@on-search="onSearch">
methods: {
onSearch(params) {
// params.searchTerm - term being searched for
// params.rowCount - number of rows that match search
}
}
@on-page-change
event emitted on pagination page change (when pagination is enabled)
<vue-good-table
:columns="columns"
:rows="rows"
@on-page-change="onPageChange">
methods: {
onPageChange(params) {
// params.currentPage - current page that pagination is at
// params.currentPerPage - number of items per page
// params.total - total number of items in the table
}
}
@on-per-page-change
event emitted on per page dropdown change (when pagination is enabled)
<vue-good-table
:columns="columns"
:rows="rows"
@on-per-page-change="onPageChange">
methods: {
onPageChange(params) {
// params.currentPage - current page that pagination is at
// params.currentPerPage - number of items per page
// params.total - total number of items in the table
}
}
@on-sort-change
event emitted on sort change
<vue-good-table
:columns="columns"
:rows="rows"
@on-sort-change="onSortChange">
methods: {
onSortChange(params) {
// params.sortType - ascending or descending
// params.columnIndex - index of column being sorted
}
}
@on-select-all
event emitted when all is selected (only emitted for checkbox tables)
<vue-good-table
:columns="columns"
:rows="rows"
@on-select-all="onSelectAll">
methods: {
onSelectAll(params) {
// params.selected - whether the select-all checkbox is checked or unchecked
// params.selectedRows - all rows that are selected (this page)
}
}
@on-column-filter
event emitted when column is filtered (only emitted for remote mode)
<vue-good-table
:columns="columns"
:rows="rows"
@on-column-filter="onColumnFilter">
methods: {
onColumnFilter(params) {
// params.columnFilters - filter values for each column in the following format:
// {field1: 'filterTerm', field3: 'filterTerm2')
}
}
Style Options
Vue-good-table allows providing your own css classes for the table via styleClass option but it also has in-built classes that you can make use of
.vgt-table
.vgt-table .stripped
.vgt-table .condensed
Theme
Vue-good-table currently comes in two themes
default
theme='nocturnal'
nocturnal
Advanced Customization
Custom row template
vue-good-table also supports dynamic td templates where you dictate how to display the cells. Example:
<vue-good-table
:columns="columns"
:rows="rows">
<template slot="table-row" slot-scope="props">
<span v-if="props.column.field == 'age'">
age: {{props.row.age}}
</span>
<span v-else>
{{props.formattedRow[props.column.field]}}
</span>
</template>
</vue-good-table>
Note:
- The original row object can be accessed via
props.row
- The currently displayed table row index can be accessed via
props.index
. - The original row index can be accessed via
props.row.originalIndex
. You can then access the original row object by usingrows[props.row.originalIndex]
. - The column object can be accessed via
props.column
- You can access the formatted row data (for example - formatted date) via
props.formattedRow
Custom column headers
Sometimes you might want to use custom column formatting. You can do that in the following way
<vue-good-table
:columns="columns"
:rows="rows">
<template slot="table-column" slot-scope="props">
<span v-if="props.column.label =='Name'">
<i class="fa fa-address-book"></i> {{props.column.label}}
</span>
<span v-else>
{{props.column.label}}
</span>
</template>
</vue-good-table>
Grouped Rows
To create grouped rows, you need two things.
- add groupOptions to table component
<vue-good-table
:columns="columns"
:rows="rows"
:groupOptions="{
enabled: true
}">
</vue-good-table>
- make sure the rows are formatted correctly. grouped rows need to be nested with headers rows containing rows in their children property. For example:
rows: [{
mode: 'span', // span means this header will span all columns
label: 'Header Two', // this is the label that'll be used for the header
children: [
{ name: 'Chris', age: 55, createdAt: '2011-10-11', score: 0.03343 },
{ name: 'Dan', age: 40, createdAt: '2011-10-21', score: 0.03343 },
]
}]
- sometimes, you might want a summary row instead of a header row. for example if you want to show total score for your group
rows: [{
name: 'Total', // this is the label that'll be used for the header
age: undefined,
createdAt: undefined,
score: 0.3, // total score here
children: [
{ name: 'Chris', age: 55, createdAt: '2011-10-11', score: 0.03343 },
{ name: 'Dan', age: 40, createdAt: '2011-10-21', score: 0.03343 },
]
}]
- if you want the header/summary row to show up at the bottom of the group, you can specify that in the groupOptions property of the table.
<vue-good-table
:columns="columns"
:rows="rows"
:groupOptions="{
enabled: true,
headerPosition: 'bottom',
}">
</vue-good-table>
you can check out some live examples on the recipes page: vue-good-table Recipes
Table Actions Slot
If you want to add table specific actions like a print button for example, you can use the Table Actions Slot. If you have global search enabled, the action panel will show up to the right of that.
<vue-good-table
:columns="columns"
:rows="rows">
<div slot="table-actions">
This will show up on the top right of the table.
</div>
</vue-good-table>
Empty state slot
You can provide html for empty state slot as well. Example:
<vue-good-table
:columns="columns"
:rows="rows">
<div slot="emptystate">
This will show up when there are no columns
</div>
</vue-good-table>
Authors
License
This project is licensed under the MIT License - see the LICENSE.md file for details