Package Exports
- vue-good-table
- vue-good-table/dist/vue-good-table.css
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (vue-good-table) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
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!
Follow the project progress live
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
- Themes
- Advanced Customization
- Authors
- License
Getting Started
Installing
Install with npm:
npm install --save vue-good-tableImport 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
columns Array
Array containing objects that describe table columns. The column object itself can contain many configurable properties.
[
{
label: 'Name',
field: 'name',
filterable: true,
}
//...
]rows Array
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.
rtl Boolean (default: false)
Enable Right-To-Left layout for the table
<vue-good-table
:columns="columns"
:rows="rows"
:rtl="true">
</vue-good-table>lineNumbers Boolean (default: false)
Show line number for each row
<vue-good-table
:columns="columns"
:rows="rows"
:lineNumbers="true">
</vue-good-table>mode String
Set mode=remote to allow sorting/filtering etc to be powered by server side instead of client side. Setting mode to remote, expects the following workflow:
- pagination, sort, filter, search will emit Table Events (loading div appears)
- setup handlers for each event
- in the handler call backend endpoints with the table params
- update rows object with the returned response ( the loading div will disappear once you update the rows object)
<vue-good-table
:columns="columns"
:rows="rows"
mode="remote">
</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>sortOptions.enabled Boolean (default: true)
Enable/disable sorting on table as a whole.
<vue-good-table
:columns="columns"
:rows="rows"
:sort-options="{
enabled: true,
}">
</vue-good-table>sortOptions.initialSortBy Object
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
paginationOptions.enabled Boolean (default: false)
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>paginationOptions.position String (default: 'bottom')
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>paginationOptions.perPage Integer (default: 10)
Number of rows to show per page
<vue-good-table
:columns="columns"
:rows="rows"
:paginationOptions="{
enabled: true,
perPage: 5
}">
</vue-good-table>paginationOptions.perPageDropdown Array (default: [10,20,30,40,50])
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>paginationOptions.dropdownAllowAll Boolean (default: true)
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>paginationOptions.setCurrentPage Number
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
searchOptions.enabled Boolean (default: false)
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>searchOptions.trigger String (default: '')
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>searchOptions.searchFn Function
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';
},
}searchOptions.placeholder String (default: 'Search Table')
Text for global search input place holder
<vue-good-table
:columns="columns"
:rows="rows"
:searchOptions="{
enabled: true,
placeholder: 'Search this table',
}">
</vue-good-table>searchOptions.externalQuery String
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.

selectOptions Object
Object containing select options
<vue-good-table
@on-select-all="allSelected"
@on-row-click="rowSelected"
:columns="columns"
:rows="rows"
:selectOptions="{
enabled: true,
selectOnCheckboxOnly: true, // only select when checkbox is clicked instead of the row
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
groupOptions Object
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
styleClass String (default: 'vgt-table bordered')
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>rowStyleClass String or Function
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 '';
}theme String
Allows using other themes. Included themes:
<vue-good-table
:columns="columns"
:rows="rows"
theme="nocturnal">
</vue-good-table>Column Options
Each column objects can contain the following configuration options:
label String
Text to put on column header.
columns: [
{
label: 'name'
},
// ...
]field String
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;
}type String
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%
- boolean - right aligned
- 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
},
// ...
]dateInputFormat String
provide the format to parse date string
dateOutputFormat String
provide the format for output date
sortable Boolean
enable/disable sorting on columns. This property is higher priority than global sortable property
columns: [
{
label: 'name',
field: 'user_name',
sortable: false,
},
// ...
]sortFn Function
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));
}
}formatFn Function
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;
}html Boolean
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>',
// ...
}
]width Number
provide a width value for this column
columns: [
{
label: 'name',
field: 'user_name',
width: '50px',
},
// ...
]hidden Boolean
hide a column
columns: [
{
label: 'name',
field: 'user_name',
hidden: true,
},
// ...
]thClass String
provide custom class(es) to the table header
columns: [
{
label: 'name',
field: 'user_name',
thClass: 'custom-th-class',
},
// ...
]tdClass String
provide custom class(es) to the table cells
columns: [
{
label: 'name',
field: 'user_name',
tdClass: 'text-center',
},
// ...
]globalSearchDisabled Boolean (default: false)
if true, this column will be ignored by the global search
columns: [
{
label: 'name',
field: 'user_name',
globalSearchDisabled: true,
},
// ...
]filterOptions Object
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
trigger: 'enter', //only trigger on enter not on keyup
},
},
// ...
]Column filter option in-depth
Some filterOption properties need a little more explanation
filterDropdownItems Array of strings or Array of objects
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' }
],filterFn Function
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 valueTable 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
// params.event - click event
}
}@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.
// params.event - click event
}
}@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

Themes
default
nocturnal theme='nocturnal'

black-rhino theme='black-rhino'

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
