Vue table component for rendering server-side data.
- Server-side data
- Searchable columns
- Sortable columns
- Filterable columns
- Drag and drop for reordering the tables' rows
- Store modules
- Persist the state to local storage
# NPM
npm install @kriptiko/vue-table
# Yarn
yarn add @kriptiko/vue-table
import Vue from 'vue'
import VueTable from '@kriptiko/vue-table'
Prop | Type | Default | Description |
---|---|---|---|
actions | Object | { classes: "", slots: [] } | The actions' slots names. See the Actions API for more info. |
checkable | Object | { display: false, attribute: null } | Show/hide checkboxes for bulk operations. See the Checkable API for more info. |
columns | Array | [] | The table columns. See the Columns API for more info. |
data-key | String | 'data' | The path to the data in the server's JSON response. |
locale | String | en | Sets the locale. Supported values: en, es, fr, pt. |
meta-key | String | null | The path to the pagination meta in the server's JSON response. |
paginate | Boolean | true | Paginates the records and enables the pages links. |
per-page | Number | 20 | Number of items displayed per page. |
orderable | Boolean | false | When set to true, the rows can be reorder by dragging them. |
row-class | String or Function | '' | The row CSS classes. It can be a String or a callback Function. |
sorting | Array | [] | The columns' sorting directions. See the Sorting API for more info. |
table-class | String | 'table table-striped' | The CSS classes of the table. |
uri | String | null | Data source URI |
For injecting HTML before the table, you can use the header
slot. See the following example:
<vue-table v-bind="options" :items.sync="items" ref="vueTable">
<template v-slot:header>
<div class="mb-4 text-right">
<button class="btn btn-outline-secondary btn-sm mr-1" @click="importItems()">
<i class="fas fa-file-import mr-1"></i> Import
</button>
<button class="btn btn-outline-secondary btn-sm" @click="exportItems($refs.vueTable.selectedItems)">
<i class="fas fa-file-export mr-1"></i> Export
</button>
</div>
</template>
...
Property | Type | Default | Description |
---|---|---|---|
classes | String | "" | The CSS classes that will be assigned to the row cell. |
slots | Array | [] | An array containing the names for the slots. |
data(){
return {
actions: {
classes: "text-right align-middle",
slots: [
"edit",
"delete"
]
}
};
}
<vue-table :actions="actions">
<template v-slot:action-edit="slotProps">
<a class="btn btn-sm btn-info"
:href="`${options.uri}/${slotProps.item.id}/edit`"
>
<i class="fas fa-pencil-alt"></i>
</a>
</template>
<template v-slot:action-delete="slotProps">
<a class="btn btn-sm btn-danger" href="#" @click.prevent="handleItemDeleted(slotProps.item)">
<i class="fas fa-trash-alt"></i>
</a>
</template>
</vue-table>
Property | Type | Default | Description |
---|---|---|---|
headerClasses | String | null | The CSS classes that will be assigned to the table headers. |
name | String | "" | The column's attribute name. |
slotName | String | "" | The name of the slot to be rendered. |
rowClasses | String | "" | The CSS classes that will be assigned to the table rows. |
searchable | Boolean | false | Determines whether the column is searchable. |
sortable | Boolean | false | Determines whether the column is sortable. |
title | String | "" | The column's header title. |
visible | Boolean | true | Determines whether the column is visible. |
render() | function | false | Callback for transforming the column's data. |
Property | Type | Description |
---|---|---|
column | String | The name of the column to be sorted. Must be an existing column. |
direction | String | The sorting direction. Allowed values: 'asc' or 'desc'. |
You can set a default sorting for your table's columns by passing a prop containing an array of objects with the names of the columns and respective sorting directions. Here's an example:
sorting: [
{
column: "name",
direction: "asc"
},
{
column: "created_at",
direction: "desc"
}
],
Whenever you sort a column, the current sorting information will be attached to the request. For the previous example, this is how the payload will look like:
sorting[0][column]: name
sorting[0][direction]: asc
sorting[1][column]: name
sorting[1][direction]: created_at
Property | Type | Description |
---|---|---|
display | Boolean | Determines whether the checkboxes are displayed or not. |
attribute | String | The item's attribute to be stored on the selectedItems array |
checkable: {
display: true,
attribute: "id"
},
If you need to filter a column, you can use the v-filter-column
directive.
<template>
<select v-filter-column="'city'">
...
</select>
</template>
<script>
import { filterColumn, VueTable } from '@kriptiko/vue-table';
export default {
components: {
VueTable
},
directives: {
filterColumn
}
}
</sc
This directive will sync your selector with the city
column.
Here's an example of the data that will be attached to the request when you select an option:
filters[0][column]: name
filters[0][values][0]: Ada Stark
It also works with selectors with the multiple
attribute. In these cases, the request will look like this:
filters[0][column]: city
filters[0][values][0]: Abbottton
filters[0][values][1]: Benborough
This will append the data to the request in order to search for the selected value in the column with the name city
. Check the Columns API for more info.
In addition to triggering a request to the server, the directive is also responsible for storing the current value of the selector in local storage. Thus, when the page loads, the option gets automatically selected.
Let's say you're fetching data for your selector from an external API and you need the selection to be triggered after the options have been loaded.
In that case, you can use the vueTable.optionsLoaded
event as follows:
// Get the cities from an external API.
<template>
<vue-table v-bind="options" :items.sync="items">
<template v-slot:filters>
<div class="col-md-3">
<select class="custom-select" v-filter-column="'city.id'" ref="cityFilter">
<option value="">Cities</option>
<option v-for="city in filters.cities" :value="city.id" :key="city.id">
{{ city.name }}
</option>
</select>
</div>
</template>
</vue-table>
</template>
<script>
import { filterColumn, VueTable } from '@kriptiko/vue-table';
export default {
name: 'App',
components: {
VueTable
},
directives: { filterColumn },
data() {
return {
items: [],
filters: {
cities: [],
},
options: {},
};
},
methods: {
/**
* Get the cities from an external API.
*/
getCitiesOptions: function () {
const axios = require('axios');
axios.get('https://api.sandbox.codetech.pt/api/cities')
.then(response => {
new Promise((resolve) => {
this.filters.cities = response.data.data;
resolve();
})
.then(() => {
this.$refs.cityFilter.dispatchEvent(new Event('vueTable.optionsLoaded'));
});
});
}
},
mounted() {
this.getCitiesOptions();
}
};
</script>
You can make use of the filters slot for placing your selectors inline with the search bar. See this example:
<vue-table>
<template v-slot:filters>
<div class="col-md-3">
<select class="form-control" v-filter-column="'city'">
<option>Cities</option>
<option value="Abbottton">Abbottton</option>
<option value="Camrenland">Camrenland</option>
<option value="Delfinamouth">Delfinamouth</option>
<option value="East Benborough">East Benborough</option>
<option value="Feeneymouth">Feeneymouth</option>
<option value="Sipesburgh">Sipesburgh</option>
</select>
</div>
</template>
</vue-table>
kriptiko/vue-table is open-sourced software licensed under the MIT license.
Kriptiko is a Creative Studio specialized in web development based in Matosinhos, Portugal.