Table & DataTable
Table styles plain tables (striped, hover, bordered, compact, color tables). DataTable is the full component: sort, search, paging, selection, responsive columns, inline edit and server mode — all texts translated.
Simple table
Simple table
vue
<ThlTable striped hover>
<thead><tr><th>#</th><th>Name</th><th>Role</th><th>Office</th></tr></thead>
<tbody><tr v-for="e in rows" :key="e.id"><td>{{ e.id }}</td><td>{{ e.name }}</td><td>{{ e.role }}</td><td>{{ e.office }}</td></tr></tbody>
</ThlTable>tsx
<SimpleTable striped hover>
<thead>…</thead><tbody>…</tbody>
</SimpleTable>html
<table thlTable striped hover>
<thead>…</thead><tbody>…</tbody>
</table>DataTable
DataTable
vue
<div><p v-if="selected.length">Selected: {{ selected.map((r) => r.name).join(', ') }}</p>
<ThlDataTable :data="employees" :columns="columns" row-key="id" selectable striped :page-size="5" @selection-change="(r) => (selected = r)">
<template #cell-name="{ row }"><div class="thl-flex" style="flex-wrap:nowrap"><ThlAvatar :src="row.avatar" size="xs" />{{ row.name }}</div></template>
<template #cell-joined="{ row }">{{ d(row.joined) }}</template>
<template #cell-salary="{ row }">{{ n(row.salary, { style: 'currency', currency: 'USD' }) }}</template>
</ThlDataTable></div>tsx
<DataTable data={employees} rowKey="id" selectable striped pageSize={5} onSelectionChange={setSelected}
columns={[
{ key: 'name', title: t('pages.contact.name'), sortable: true,
render: (e) => <><Avatar src={e.avatar} size="xs" />{e.name}</> },
{ key: 'office', title: 'Office', sortable: true, hideBelow: 1024 },
{ key: 'salary', title: 'Salary', sortable: true, align: 'right',
render: (e) => t.n(e.salary, { style: 'currency', currency: 'USD' }) },
]} />html
<thl-data-table [data]="employees" [columns]="columns" rowKey="id" selectable [striped]="true" [pageSize]="5"
(selectionChange)="selected.set($event)">
<ng-template thlCell="name" let-row><thl-avatar [src]="row.avatar" size="xs" />{{ row.name }}</ng-template>
<ng-template thlCell="salary" let-row>{{ i18n.n(row.salary, { style: 'currency', currency: 'USD' }) }}</ng-template>
</thl-data-table>Columns
| Field | Type | Description |
|---|---|---|
key | string | Field name (and cell slot name cell-{key} / thlCell="{key}") |
title | string / node | Header |
value | (row) => unknown | Accessor for sort/search (defaults to row[key]) |
sortable | boolean | Click header to sort asc → desc → none |
compare | (a, b) => number | Custom sort |
searchable | boolean | Include in global search (default true) |
align | 'left' | 'center' | 'right' | |
width | string | number | |
hideBelow | number (px) | Responsive column hiding |
editable | boolean | Inline edit → cell-edit event |
render | React only | Cell renderer |
Server-side mode
Set manual and total, then load data on query-change ({ page, pageSize, sort, search }):
vue
<ThlDataTable manual :total="total" :data="rows" :columns="cols" :loading="loading" @query-change="load" />API
Table
<ThlTable> · import { ThlTable } from '@thl-ui/vue'
| Prop | Type | Default |
|---|---|---|
striped | boolean | — |
hover | boolean | — |
bordered | any | — |
compact | boolean | — |
color | string | — |
full | string | — |
Slots: default
DataTable
<ThlDataTable> · import { ThlDataTable } from '@thl-ui/vue'
| Prop | Type | Default |
|---|---|---|
data* | array | — |
columns* | array | — |
rowKey | any | — |
pageSize | number | — |
paginate | boolean | true |
searchable | boolean | true |
selectable | boolean | — |
striped | boolean | — |
hover | boolean | — |
bordered | boolean | — |
color | string | — |
stack | boolean | — |
compact | boolean | — |
emptyText | string | — |
manual | boolean | — |
total | number | — |
loading | boolean | — |
Events: selection-changecell-editquery-change
Slots: toolbarcell-{key}