tablevu
TableVu
TableVu is a Vue 3 table component with local-array and adapter-backed data loading. It supports paging, sorting, search, filtering, grouping, custom cell rendering, and OData requests.
Interactive example
The Northwind example demonstrates search, country and OData filters, paging, column interactions, and grouping by either a field or a function. To run it locally, use the commands below from this package directory. The browser needs internet access for Vue and the Northwind OData service.
npm install
npm run build
python3 -m http.server 8080
Open http://localhost:8080/example/test-northwind.html.
The npm package page renders this README as GitHub Flavored Markdown; it does not run embedded HTML or JavaScript. To offer a live demo, publish the static example/ page and dist/ bundle with GitHub Pages, then link to that hosted page here. GitHub Pages can serve static HTML, CSS, and JavaScript from a repository. See npm README documentation and GitHub Pages documentation.
Install
npm install tablevu vue
Vue is a peer dependency and must be installed by the application.
Quick start
<script setup lang="ts">
import { ref } from 'vue';
import { TableVu } from 'tablevu';
import type { TableVuExpose } from 'tablevu';
const table = ref<TableVuExpose | null>(null);
const search = ref('');
const rows = [
{ id: 1, name: 'Ada Lovelace', city: 'London' },
{ id: 2, name: 'Grace Hopper', city: 'New York' },
{ id: 3, name: 'Katherine Johnson', city: 'White Sulphur Springs' }
];
const settings = {
page: { size: 10 },
columns: [
{ name: 'id', label: 'ID', type: 'integer', width: '5rem' },
{ name: 'name', label: 'Name', searchable: true },
{ name: 'city', label: 'City' }
]
};
</script>
<template>
<input v-model="search" placeholder="Search">
<TableVu
ref="table"
:data="rows"
:settings="settings"
:search="search"
/>
</template>
Passing an array directly uses the built-in local adapter. Pass an adapter function such as odata(...) for remote data. The component requests its first page when mounted.
Component props
| Prop | Type | Description |
|---|---|---|
data |
any[] | AdapterFunction |
Local rows or an async adapter. |
settings |
TablevuSettings |
Columns and table behavior. |
group |
string | TablevuGroup |
Group configuration. settings.group is also supported. |
search |
string |
Search text. The component refreshes after a short debounce. |
filter |
any |
Adapter-specific filter value; changing it reloads data. |
command |
{ name, page? }[] |
Append a command (refresh, first, prior, next, last, or go) to trigger an action. |
rowid |
string |
Row property copied to the rendered row's rowid attribute. |
onRowClick |
(event, row) => void |
Row click callback. |
onRowDblClick |
(event, row) => void |
Row double-click callback. |
class |
string |
Additional table CSS class. |
style |
string | Record<string, string> |
Inline table style. |
The component also emits row-click and row-dbl-click, each with (event, row) arguments.
Settings
const settings = {
page: { size: 20 },
sort: [{ name: 'name', dir: 'asc' }],
searchMinChar: 2,
emptyMessage: 'No matching records',
footer: { button: { class: 'pager-button' } },
columns: [
{ name: 'name', label: 'Name', width: '16rem', resizable: true, draggable: true },
{ name: 'address.city', label: 'City', type: 'string' }
]
};
Columns
| Option | Description |
|---|---|
name |
Required field name. Dotted paths such as address.city are supported. |
label |
Header label; defaults to name. |
type |
string, number, numeric, integer, date, time, datetime, or boolean. Date/time values are formatted using the browser locale. |
align |
Cell alignment: left, center, or right. |
width |
CSS width applied to header and cells. |
style |
Inline cell style object. |
render |
(row) => VNodeChild callback for custom cell content. |
colspan |
Cell column span. |
searchable |
Set to false to exclude the column from search. |
resizable |
Set to false to disable drag resizing. |
draggable |
Set to false to disable header dragging. |
visible |
Column metadata; columns marked invisible are not currently filtered out by the renderer. |
popup |
Show a header menu with ascending and descending sort actions. |
depth, header, filter |
Additional metadata fields; filter UI is not implemented. |
Headers sort when clicked. Drag a header to reorder it; drag it outside the table to remove it from the current table instance. Drag the right edge to resize it. These interactions update the component's in-memory column state; they are not persisted automatically.
searchMinChar controls the search threshold (default 3); search runs when the input length is greater than this value. Search is debounced. For arrays, search checks configured searchable columns locally. The OData adapter builds a contains filter across searchable columns.
Grouping
Set group.value to a field name or a function of each row. content independently chooses the displayed group heading. expandAll defaults to true; class sets the group row's CSS class.
const fieldGroup = {
value: 'country',
content: 'country',
expandAll: true,
class: 'country-group'
};
const functionGroup = {
value: (row: { country: string }) => row.country.toUpperCase(),
content: (row: { country: string }) => `Country: ${row.country}`
};
The component uses the first row in each group to calculate its displayed content. Grouping is performed on the rows returned for the current page.
Adapter data hook
settings.onData(rows) can transform each page of adapter results before rendering. It must return the rows to display.
Adapters
An adapter receives paging, sort, columns, filter, and search information and returns { rows, count }:
import type { AdapterFunction } from 'tablevu';
const loadRows: AdapterFunction = async ({ pageSize, currPage, sort, cols, filter, search }) => {
// Fetch/transform rows using the received parameters.
return { rows: [], count: 0 };
};
count is the total number of rows matching the query, not just the returned page. It is used to calculate the page count. adaptArray implements local equality filters, search, sorting, and paging. Its filter is a key/value object, for example { status: 'active' }.
OData adapter
odata(options) creates an adapter that uses fetch, adds OData query parameters, and expects a JSON response with a value array and optional @odata.count.
import { odata } from 'tablevu';
const loadCustomers = odata({
url: 'https://services.odata.org/V4/Northwind/Northwind.svc/Customers',
count: true,
select: ['CustomerID', 'CompanyName', 'Country'],
expand: [{ name: 'Orders', select: ['Freight', 'ShipCountry'] }],
filter: { column: 'Country', operator: 'ne', value: 'USA' }
});
Options:
| Option | Description |
|---|---|
url |
Required collection endpoint. |
select |
$select fields. |
expand |
$expand entries with name, optional select, filter, and orderby. |
filter |
Static OData filter expression or typed Filter. |
count |
Request $count=true. |
headers |
Fetch request headers. |
credentials |
Fetch credentials mode. |
fetch |
Custom fetch implementation. |
onfetch |
Request hook; return the request to send. |
The adapter also uses the component's current page, sort, search, and filter prop to build $skip, $top, $orderby, and $filter parameters. Pass the adapter to TableVu through :data="loadCustomers".
OData filters
import type { Filter } from 'tablevu';
const filter: Filter = {
operator: 'and',
filters: [
{ column: 'Country', operator: 'in', value: ['Germany', 'France'] },
{ column: 'CompanyName', operator: 'contains', value: 'market' },
{ column: 'Orders', operator: 'any', variable: 'order',
filter: { column: 'Freight', operator: 'gt', value: 100 } }
]
};
Supported operators: eq, ne, gt, ge, lt, le, contains, startsWith, endsWith, in, between, isNull, isNotNull, and, or, not, any, all, countGt, countGe, countLt, and countLe. Use field or column for the property name; dotted paths become OData slash paths. and/or take filters; not takes one child; any/all take a nested filter and optional variable (default item). Count operators compare a collection's $count with a non-negative integer. String filters are passed through as raw OData expressions.
Filter is an OData filter type. The built-in array adapter currently supports simple equality maps rather than this OData filter tree.
Template ref methods
interface TableVuExpose {
first(): Promise<void>;
prior(): void | Promise<void>;
next(): void | Promise<void>;
last(): void | Promise<void> | undefined;
go(pageNumber: number): void | Promise<void>;
page(pageNumber: number): Promise<void>;
refresh(): Promise<void>;
sortBy(columnIndex: number, direction?: string): void | Promise<void>;
getRows(): any[];
setRows(rows: any[]): void;
}
go() validates positive integer page numbers and clamps to the known last page. page() reloads a specified page directly. getRows() returns the currently rendered page; setRows() replaces those displayed rows.
TypeScript exports
The package exports TableVu, odata, buildFilter, adaptArray, and the public types including TableVuExpose, TablevuSettings, TablevuColumn, TablevuGroup, AdapterFunction, AdapterParams, AdapterResult, Filter, FilterOperator, and ODataOptions.
Related Packages
The best Datatable for Vue.js 2.x which never sucks... with ui-kit
Version History
| Version | Released | License |
|---|---|---|
| 0.3.2 | MIT | |
| 0.3.1 | MIT | |
| 0.3.0 | MIT | |
| 0.2.22 | MIT | |
| 0.2.21 | MIT | |
| 0.2.20 | MIT | |
| 0.2.19 | MIT | |
| 0.2.18 | MIT | |
| 0.2.17 | MIT | |
| 0.2.16 | MIT | |
| 0.2.15 | MIT | |
| 0.2.14 | MIT | |
| 0.2.13 | MIT | |
| 0.2.12 | MIT | |
| 0.2.11 | MIT | |
| 0.2.10 | MIT | |
| 0.2.9 | MIT | |
| 0.2.8 | MIT | |
| 0.2.7 | MIT | |
| 0.2.6 | MIT | |
| 0.2.5 | MIT | |
| 0.2.3 | MIT | |
| 0.2.2 | MIT | |
| 0.2.1 | MIT | |
| 0.2.0 | MIT | |
| 0.1.4 | MIT | |
| 0.1.3 | MIT | |
| 0.1.2 | MIT | |
| 0.1.1 | MIT | |
| 0.1.0 | MIT |
Pre-releases (6)
| Version | Released | License |
|---|---|---|
| 0.3.0-beta.5 | MIT | |
| 0.3.0-beta.4 | MIT | |
| 0.3.0-beta-4 | MIT | |
| 0.3.0-beta.3 | MIT | |
| 0.3.0-beta.2 | MIT | |
| 0.3.0-beta.1 | MIT |