@bhplugin/vue3-datatable
v3.0.0
Published
Vue3 Datatable - fully customizable & easy to use datatable library
Maintainers
Readme
@bhplugin/vue3-datatable
A zero-dependency Vue 3 datatable component with client/server-side pagination, sorting, filtering, row selection, and custom cell rendering.
Example
Install
NPM
npm install @bhplugin/vue3-datatable --saveYarn
yarn add @bhplugin/vue3-datatableUsage
<template>
<vue3-datatable :rows="rows" :columns="cols" :sortable="true" :columnFilter="true"> </vue3-datatable>
</template>
<script setup lang="ts">
import { ref } from "vue";
import Vue3Datatable from "@bhplugin/vue3-datatable";
import type { IColumnDefinition } from "@bhplugin/vue3-datatable";
import "@bhplugin/vue3-datatable/dist/style.css";
const cols = ref<IColumnDefinition[]>([
{ field: "id", title: "ID", isUnique: true, type: "number", filter: false },
{ field: "name", title: "Name" },
{ field: "email", title: "Email" },
{ field: "age", title: "Age", type: "number" },
{ field: "dob", title: "Date of Birth", type: "date" },
{ field: "isActive", title: "Active", type: "bool" },
{ field: "address.city", title: "City" },
]);
const rows = ref<Array<Record<string, unknown>>>([
{ id: 1, name: "John Doe", email: "[email protected]", age: 28, dob: "1997-05-15", isActive: true, address: { city: "New York" } },
{ id: 2, name: "Jane Smith", email: "[email protected]", age: 34, dob: "1991-11-22", isActive: false, address: { city: "London" } },
// ...
]);
</script>Props
| Prop | Type | Default | Description |
| ----------------------- | :------------------------ | ----------------------------------- | ---------------------------------------------------------------------------------------------------- |
| columns (required) | IColumnDefinition[] | [] | Table column definitions |
| rows (required) | Record[] | [] | Table row data |
| isServerMode | boolean | false | Enable server-side mode (disables client-side sort/filter/pagination) |
| totalRows | number | 0 | Total row count (required in server mode) |
| skin | string | "bh-table-striped bh-table-hover" | Table skin classes: bh-table-striped, bh-table-hover, bh-table-bordered, bh-table-compact |
| loading | boolean | false | Show loading overlay/skeleton |
| hasCheckbox | boolean | false | Show checkbox column for row selection |
| search | string | "" | Global search string |
| page | number | 1 | Current page (1-based) |
| pageSize | number | 10 | Rows per page |
| pageSizeOptions | number[] | [10, 20, 30, 50, 100] | Page size dropdown options |
| showPageSize | boolean | true | Show page size dropdown |
| rowClass | string \| Function | "" | Custom row class (string or (row) => string) |
| cellClass | string \| Function | "" | Custom cell class (string or (row) => string) |
| sortable | boolean | false | Enable column sorting |
| sortColumn | string | "" | Initial sort column field |
| sortDirection | 'asc' \| 'desc' | "asc" | Initial sort direction |
| columnFilter | boolean | false | Enable per-column filter inputs |
| columnFilterLang | Record<string, string> | null | i18n labels for filter conditions (see below) |
| pagination | boolean | true | Show pagination |
| showNumbers | boolean | true | Show page number buttons |
| showNumbersCount | number | 5 | Max visible page number buttons |
| showFirstPage | boolean | true | Show first page button |
| showLastPage | boolean | true | Show last page button |
| paginationInfo | string | "Showing {0} to {1} of {2} entries" | Pagination info template ({0} = start, {1} = end, {2} = total) |
| noDataContent | string | "No data available" | Empty state text |
| skeletonRowCount | number | 10 | Number of skeleton rows while loading |
| stickyHeader | boolean | false | Sticky table header |
| height | string | "500px" | Scrollable height (only with stickyHeader) |
| stickyFirstColumn | boolean | false | Sticky first column |
| cloneHeaderInFooter | boolean | false | Clone header as footer row |
| selectRowOnClick | boolean | false | Toggle row selection on row click |
columnFilterLang keys
{
no_filter: 'No filter',
contain: 'Contain', not_contain: 'Not contain',
equal: 'Equal', not_equal: 'Not equal',
start_with: 'Starts with', end_with: 'Ends with',
greater_than: 'Greater than', greater_than_equal: 'Greater than or equal',
less_than: 'Less than', less_than_equal: 'Less than or equal',
is_null: 'Is null', is_not_null: 'Not null',
all: 'All', true: 'True', false: 'False' // boolean column filter labels
}Column Definition
| Prop | Type | Default | Description |
| ---------------- | :----------------- | ----------- | ------------------------------------------------------------------ |
| isUnique | boolean | false | Mark as unique row identifier (used for selection keys) |
| field | string | "" | Data field path (supports dot notation: address.city) |
| title | string | "" | Column header text |
| value | string | "" | Initial filter value |
| condition | IFilterCondition | "" | Default filter condition (contain for string, equal for number/date, empty for bool) |
| type | string | "string" | Column type: string, number, date, bool |
| width | string | "" | Column width (e.g., "200px") |
| minWidth | string | "" | Minimum column width |
| maxWidth | string | "" | Maximum column width |
| hide | boolean | false | Hide column from rendering |
| filter | boolean | true | Enable column filter |
| search | boolean | true | Include in global search |
| sort | boolean | true | Enable sorting |
| html | boolean | false | Column contains raw HTML |
| cellRenderer | Function | - | Custom cell renderer: (row) => '<strong>html</strong>' (sanitized automatically) |
| headerClass | string | "" | Custom header cell class |
| cellClass | string | "" | Custom body cell class |
Events
| Event | Payload | Description |
| ------------------ | :----------------------- | ------------------------------------------------------------------------------------------- |
| changeServer | IServerChangeResponse | Server mode only — aggregate event with full state (page, sort, search, filters, change_type) |
| pageChange | number | User clicked pagination button (silent on programmatic resets) |
| pageSizeChange | number | Page size dropdown changed |
| sortChange | ISortChangeResponse | Column sort applied (does NOT reset page) |
| filterChange | IColumnDefinition[] | Column filter value or condition changed |
| searchChange | string | Global search prop changed |
| rowSelect | Record[] | Row selection changed (user interaction only) |
| rowClick | Record | Row single click |
| rowDBClick | Record | Row double click |
| reset | - | reset() called — only event during reset, all others suppressed |
Event rules
- Sort does not reset page
- Filter/search/pagesize resets to page 1 but only emits the specific event (not
pageChange) pageChangefires only from explicit user pagination clicks- During reset, only
reset(+changeServerin server mode) emits — all other events suppressed
Methods
| Method | Description | | ------------------------ | ---------------------------------------------------- | | reset() | Reset all state (selection, filters, search, sort, page) | | getFilteredRows() | Returns all filtered rows | | getVisibleRows() | Returns current page visible rows | | getColumnFilters() | Returns column definitions with current filter state | | getSelectedRows() | Returns all selected rows | | clearSelectedRows() | Deselect all rows | | selectRow(index) | Select row by index | | unselectRow(index) | Deselect row by index | | isRowSelected(index) | Check if row is selected |
Slots
Custom cell rendering (named by column field)
<vue3-datatable :rows="rows" :columns="cols">
<template #name="{ value }">
<strong>{{ value.name }}</strong>
</template>
</vue3-datatable>Pagination arrow slots
<template #firstArrow> « </template>
<template #previousArrow> ‹ </template>
<template #nextArrow> › </template>
<template #lastArrow> » </template>Empty state slot
<template #noData>
<div>No records found.</div>
</template>Server Mode Example
<vue3-datatable
:rows="rows"
:columns="cols"
:loading="loading"
:totalRows="totalRows"
:isServerMode="true"
:pageSize="10"
:sortable="true"
:columnFilter="true"
@page-change="onPageChange"
@page-size-change="onPageSizeChange"
@sort-change="onSortChange"
@filter-change="onFilterChange"
@search-change="onSearchChange"
/>Changelogs
License
@bhplugin/vue3-datatable is open-sourced software licensed under the MIT license.
