Skip to content

An easy to use data table for vuejs with advanced customizations including sorting, column filtering, pagination, grouping etc

License

Notifications You must be signed in to change notification settings

jonathan-wondereur/vue-good-table

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Vue-good-table

npm npm npm

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!

Buy Me A Coffee

Upgrade Guide

Hey there! coming from 1.x? find the upgrade guide here

Basic Table

Basic Screenshot

Table with grouped rows and column filters

Advanced Screenshot

Recipes

Some example recipes for inspiration vue-good-table Recipes

Table of contents

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

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>

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. Checkbox Screenshot

selectOptions Object

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

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. 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:

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%
  • 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 
	},
  },
  // ...
]

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 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(row, pageIndex, selected) {
    // row - row object 
    // pageIndex - index of this row on the current page.
    // 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(row, column, rowIndex) {
    // row - row object 
    // column - column object
    // 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(row, pageIndex) {
    // row - row object 
    // 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(searchTerm, rowCount) {
    // searchTerm - term being searched for
    // 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(currentPage, currentPerPage, total) {
    // currentPage - current page that pagination is at
    // currentPerPage - number of items per page
    // 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(currentPage, currentPerPage, total) {
    // currentPage - current page that pagination is at
    // currentPerPage - number of items per page
    // 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(sortType, columnIndex) {
    // sortType - ascending or descending
    // 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(selected, selectedRows) {
    // selected - whether the select-all checkbox is checked or unchecked
    // selectedRows - all rows that are selected (this page)
  }
}

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

Table Screenshot

.vgt-table .stripped

Table Bordered Striped Screenshot

.vgt-table .condensed

Table Bordered Striped Screenshot

Theme

Vue-good-table currently comes in two themes

default

nocturnal theme='nocturnal'

Nocturnal Theme Screenshot

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 using rows[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.

  1. add groupOptions to table component
<vue-good-table
  :columns="columns"
  :rows="rows"
  :groupOptions="{
  	enabled: true
  }">
</vue-good-table>
  1. 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 },
  ]
}]
  1. 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 },
  ]
}]
  1. 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

About

An easy to use data table for vuejs with advanced customizations including sorting, column filtering, pagination, grouping etc

Resources

License

Code of conduct

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Vue 64.1%
  • JavaScript 22.0%
  • CSS 13.6%
  • HTML 0.3%