"Love using @bhplugin/vue3-datatable? Don't forget to Star it on GitHub and help others discover it!"
The @bhplugin/vue3-datatable now offers support for Server Side Rendering. Please check the "isServerMode" prop to enable this feature.

Installation

NPM

npm install @bhplugin/vue3-datatable --save

Yarn

yarn add @bhplugin/vue3-datatable

Bower

bower install @bhplugin/vue3-datatable --save

Include

Component

import Vue3Datatable from '@bhplugin/vue3-datatable'

CSS

import '@bhplugin/vue3-datatable/dist/style.css'

TypeScript Types (optional)

import type { IColumnDefinition, IColumnType, IFilterCondition, IServerChangeResponse, ISortChangeResponse, IDataTableProps } from '@bhplugin/vue3-datatable'

Props

PropsTypeDefaultDescription
columns (required)array[]table columns Column Props
rows (required)array[]table rows
isServerModebooleanfalseset true if you need server side pagination.
totalRowsnumber0 total number of rows.
totalRows required when isServerMode is true.
skinstring"bh-table-striped bh-table-hover" custom class for skin
bh-table-striped - for stripe row
bh-table-hover - for hover row
bh-table-bordered - for bordered row
bh-table-compact - for compact table
loadingbooleanfalseenable loader
hasCheckboxbooleanfalseenable checkbox
searchstring""enable global search
pagenumber1current page
pageSizenumber10number of rows per page
pageSizeOptionsarray[10, 20, 30, 50, 100]pagesize options
showPageSizebooleantrueenable pagesize options
rowClassarray, function""custom row class
cellClassarray, function""custom cell class
sortablebooleanfalseenable sorting
sortColumnstring""initial sort column field name
sortDirection'asc' | 'desc'"asc"initial sort direction
columnFilterbooleanfalseenable individual column filter
columnFilterLangrecords<string,string>null columns filters translation (ex: {no_filter: 'Aucun', contain: 'Contiens', not_contain: 'Ne contiens pas', equal: 'Egale', not_equal: 'Différent', start_with: 'Commence par', end_with: 'Termine par', greater_than: 'Supérieur à', greater_than_equal: 'Sup. ou égale à', less_than: 'Inférieur à', less_than_equal: 'Inf. ou égale à', is_null: 'Est null', is_not_null: 'Non null', all: 'Tous', true: 'Vrai', false: 'Faux'} )
paginationbooleantrueenable pagination
showNumbersbooleantrueenable numbers pagination
showNumbersCountnumber5show numbers of count in pagination
showFirstPagebooleantrueenable first page in pagination
showLastPagebooleantrueenable last page in pagination
paginationInfostring"Showing {0} to {1} of {2} entries"custom pagination info
noDataContentstringNo data availablecustom no data message
skeletonRowCountnumber10number of skeleton rows rendered while loading
stickyHeaderbooleanfalseenable fixed header
heightstring500pxonly will be used when stickyHeader enabled
stickyFirstColumnbooleanfalseenable fixed first column
cloneHeaderInFooterbooleanfalseenable clone header in footer
selectRowOnClickbooleanfalsetoggle row selection when clicking anywhere on the row (not just the checkbox)

Columns options

PropsTypeDefaultDescription
isUniquebooleanfalsedb column is primary key or not
fieldstring""db column name
titlestring""display column name
valuestring""filter value if filter enabled
conditionIFilterCondition"contain" default condition for column filter (contain, not_contain, equal, not_equal, start_with, end_with, greater_than, greater_than_equal, less_than, less_than_equal, is_null, is_not_null)
type'string' | 'date' | 'number' | 'bool'"string"column data type — determines filter conditions and sort behavior
widthstring""custom width of column
minWidthstring""custom minimum width of column
maxWidthstring""custom maximum width of column
hidebooleanfalseshow/hide column
filterbooleantrueenable column filter
searchbooleantrueenabled global search
sortbooleantrueenable sorting
htmlbooleanfalsewhether the column content contains raw HTML
cellRenderer(row) => string | stringcustom cell renderer — function returning an HTML string (rendered via v-html), or a static HTML string. For complex rendering, prefer named slots.
headerClassstring""custom header cell class
cellClassstring""custom cell class

Events

NamePayloadDescription
changeServerIServerChangeResponsefires only in server mode — aggregate event with full state (page, pagesize, sort, search, column filters, change_type)
sortChangeISortChangeResponsewill trigger when sorting changed
searchChangestringwill trigger when search changed
pageChangenumberfires only when user clicks pagination buttons. Silent on programmatic resets (filter/search/pagesize change).
pageSizeChangenumberwill trigger when pagesize changed
rowSelectArray<Record<string, unknown>>will trigger when row selected using checkbox (only from user interactions)
filterChangeIColumnDefinition[]will trigger when column filter changed
rowClickRecord<string, unknown>will trigger when row clicked
rowDBClickRecord<string, unknown>will trigger when row double clicked
resetfires when reset() method is called. Only event emitted during reset — all other events (searchChange, pageSizeChange, etc.) are suppressed.

Methods

NameDescription
resetwill reset all options like selected rows, filter, search, currennt page etc
getFilteredRowswill returns all filtered rows
getVisibleRowswill returns all visible rows
getColumnFilterswill return all column filters
getSelectedRowswill returns all selected rows
clearSelectedRowswill unselect all selected rows
selectRow(index)will select row with the given index (non-existent row will be ignored)
unselectRow(index)will unselect row with the given index (non-existent row will be ignored)
isRowSelected(index)will return true if the row with given index is selected

Slots

Custom cell rendering (named by column field)

<template #id="data">
  <strong>{{ data.value.id }}</strong>
</template>

<template #name="data">
  <strong>{{ data.value.name }}</strong>
</template>

<template #email="data">
  <strong>{{ data.value.email }}</strong>
</template>

Custom pagination arrows

<template #firstArrow>First</template>
<template #previousArrow>Prev</template>
<template #nextArrow>Next</template>
<template #lastArrow>Last</template>

Custom empty state

<template #noData>
  <div class="p-4 text-gray-500">No records found</div>
</template>

Usage

Basic

<template>
  <vue3-datatable :rows="rows" :columns="cols">
  </vue3-datatable>
</template>

<script setup lang="ts">
  import { ref } from "vue";
  import Vue3Datatable from "@bhplugin/vue3-datatable";
  import "@bhplugin/vue3-datatable/dist/style.css";

  const cols =
    ref([
      { field: "id", title: "ID", width: "90px", filter: false },
      { field: "name", title: "Name" },
      { field: "username", title: "Username" },
      { field: "email", title: "Email" },
      { field: "phone", title: "Phone" },
      { field: "date", title: "Date", type: "date" },
      { field: "active", title: "Active", type: "bool" },
      { field: "age", title: "Age", type: "number" },
      {
        field: "address.city",
        title: "Address",
        search: true,
        cellRenderer: (item: any) => {
          return (
            item &&
            item.address?.street +
              ", " +
              item.address?.suite +
              "<br/><strong>" +
              item.address?.city +
              "</strong>" +
              "<br/><strong>" +
              "lat: " +
              item.address?.geo?.lat +
              "&nbsp;&nbsp; lng: " +
              item.address?.geo?.lng +
              "</strong>"
          );
        },
      },
      { field: "company.name", title: "Company" },
    ]) || [];

  const rows = ref([
    {
      id: 1,
      name: "Leanne Graham",
      username: "Bret",
      email: "Sincere@april.biz",
      address: {
        street: "Kulas Light",
        suite: "Apt. 556",
        city: "Gwenborough",
        zipcode: "92998-3874",
        geo: {
          lat: "-37.3159",
          lng: "81.1496",
        },
      },
      phone: "1-770-736-8031 x56442",
      website: "hildegard.org",
      company: {
        name: "Romaguera-Crona",
        catchPhrase: "Multi-layered client-server neural-net",
        bs: "harness real-time e-markets",
      },
      date: "Tue Sep 27 2022 22:19:57",
      active: true,
      age: 10,
    },
    ...
  ]);
</script>

License

@bhplugin/vue3-datatable is open-sourced software licensed under the [MIT license]

Our other plugins

Angular Datatable - @bhplugin/ng-datatable

Support

Buy Me A Coffee