Table
Basic Usage
The simplest way to create a table is by defining the row-key
, columns
, and data
props. The row-key
prop represents a unique identifier for each data item. The columns
prop is used to define the columns of the table, and the data
prop is used to pass the data that the table should display.
If you want to customize the content of a cell, you can define the content and then pass it to the appropriate slot. The key
attribute of the columns
prop represents the slot name for the corresponding cell slot.
View Source
<script setup lang="ts">
import { UniTable } from "unify-ui";
import useFetchData from "./useFetchData";
const { data } = useFetchData();
const columns: InstanceType<typeof UniTable>["$props"]["columns"] = [
{
title: "Title",
key: "title",
width: 150,
},
{
title: "Author",
key: "author",
},
];
</script>
<template>
<UniTable row-key="id" :columns="columns" :data="data">
<template #author="{ record }"> Author is {{ record.author }} </template>
</UniTable>
</template>
Fixed Columns
The table supports fixed columns. For keeping the left columns fixed in the table, you can set the fixed
attribute of the columns
prop to left
. Similarly, to keep the right columns fixed in the table, you can set the fixed
attribute of the columns
prop to right
.
View Source
<script setup lang="ts">
import { UniTable } from "unify-ui";
import useFetchData from "./useFetchData";
const { data } = useFetchData();
const columns: InstanceType<typeof UniTable>["$props"]["columns"] = [
{
title: "Title",
key: "title",
fixed: "left",
width: 150,
},
{
title: "Author",
key: "author",
width: 150,
},
{
title: "Post",
key: "post",
width: 600,
},
{
title: "Actions",
key: "actions",
fixed: "right",
width: 100,
},
];
</script>
<template>
<UniTable row-key="id" class="container" :columns="columns" :data="data">
<template #actions>Delete</template>
</UniTable>
</template>
<style scoped>
.container {
width: 100%;
height: 500px;
}
</style>
Selection
The rows in the table can be selected by using the selection
prop. The selection
prop is an object that contains the following properties:
type
: the type of selection, which can be eithersingle
ormultiple
disabledCondition
: a function that determine whether a row can be selected.
You can use the v-model:selectedRowKeys
to get the selected row keys.
Additionally, there are two events that you can use to listen to changes in selection:
select
: emitted when a row is selectedselect-all
: emitted when all rows are selected
Single Selection
If you want to ensure that only one row can be selected at a time, set the type
attribute of the selection
prop to single
.
View Source
<script setup lang="ts">
import { reactive } from "vue";
import { UniTable } from "unify-ui";
import useFetchData from "./useFetchData";
const { data } = useFetchData();
const state = reactive({
selectedRowKeys: new Set<string>(),
});
const columns: InstanceType<typeof UniTable>["$props"]["columns"] = [
{
title: "Title",
key: "title",
width: 150,
},
{
title: "Author",
key: "author",
width: 150,
},
{
title: "Post",
key: "post",
width: 500,
},
];
function disabledCondition(record: any) {
return record.id === 1;
}
</script>
<template>
<UniTable
v-model:selected-row-keys="state.selectedRowKeys"
row-key="id"
class="container"
:columns="columns"
:data="data"
:selection="{ type: 'single', disabledCondition }"
>
</UniTable>
</template>
<style scoped>
.container {
width: 100%;
height: 500px;
}
</style>
Multiple Selection
If you want to allow multiple rows to be selected in the table simultaneously, you can set the type
attribute of the selection
prop to multiple
.
View Source
<script setup lang="ts">
import { watch, reactive } from "vue";
import { UniTable, UniButton } from "unify-ui";
import useFetchData from "./useFetchData";
const { data } = useFetchData();
const columns: InstanceType<typeof UniTable>["$props"]["columns"] = [
{
title: "Title",
key: "title",
width: 150,
},
{
title: "Author",
key: "author",
width: 150,
},
{
title: "Post",
key: "post",
width: 500,
},
];
function disabledCondition(record: any) {
return record.id === 1;
}
const state = reactive({
selectedRowKeys: new Set<string>(),
selectedRows: new Map<string, any>(),
});
watch(
() => [...state.selectedRowKeys],
(value) => {
console.log("🚀 ~ file: MultipleSelection.vue:47 ~ watch ~ value:", value);
}
);
function handleChangeSelectionRows(params: { selected: boolean; records: any[] }) {
params.records.forEach((item) => {
if (params.selected) {
state.selectedRows.set(item.id, item);
} else {
state.selectedRows.delete(item.id);
}
});
}
function handleSelection(params: { selected: boolean; rowKey: string | number; record: any }) {
handleChangeSelectionRows({
selected: params.selected,
records: [params.record],
});
}
function handleSelectAll(params: { selected: boolean; rowKeys: (string | number)[]; records: any[] }) {
handleChangeSelectionRows({
selected: params.selected,
records: params.records,
});
}
function handleClearSelection() {
state.selectedRowKeys.clear();
}
</script>
<template>
<UniButton class="button" type="soft" @click="handleClearSelection"> Clear selectedRowKeys </UniButton>
<UniTable
v-model:selected-row-keys="state.selectedRowKeys"
row-key="id"
class="container"
:columns="columns"
:data="data"
:selection="{ type: 'multiple', disabledCondition }"
@select="handleSelection"
@select-all="handleSelectAll"
>
</UniTable>
</template>
<style scoped>
.button {
margin-bottom: 20px;
}
.container {
width: 100%;
height: 500px;
}
</style>
Expandable Row
The rowExpand
prop can be used to mark a row expandabled. The rowExpand
prop is an object that contains the following properties:
expandCondition
: a function that determine whether a row can be expanded.showExpandRowDefault
: whether to show expand row by default.
Additionally, you must define the content of the expanded row and pass it to the slot named rowExpand
.
View Source
<script setup lang="ts">
import { UniTable } from "unify-ui";
import useFetchData from "./useFetchData";
const { data } = useFetchData();
const columns: InstanceType<typeof UniTable>["$props"]["columns"] = [
{
title: "Title",
key: "title",
width: 200,
},
{
title: "Author",
key: "author",
},
];
const rowExpand: InstanceType<typeof UniTable>["$props"]["rowExpand"] = {
expandCondition: (row) => row.description as boolean,
showExpandRowDefault: false,
};
</script>
<template>
<UniTable row-key="id" :columns="columns" :data="data" :row-expand="rowExpand">
<template #rowExpand="{ record }">
{{ `Expand row: ${record.description}` }}
</template>
</UniTable>
</template>
Custom Header
Sometimes, you may want to customize the content of a column header cell. In this case, when you define a column with column.key
as author
, you can pass the custom content to the slot named header-author
.
View Source
<script setup lang="ts">
import { UniTable } from "unify-ui";
import useFetchData from "./useFetchData";
const { data } = useFetchData();
const columns: InstanceType<typeof UniTable>["$props"]["columns"] = [
{
title: "Title",
key: "title",
width: 200,
},
{
title: "Author",
key: "author",
},
];
</script>
<template>
<UniTable row-key="id" :columns="columns" :data="data">
<template #title="{ record }"> title: {{ record.userId }} </template>
<template #header-title>
<span class="customer-header-text">This is custom title!</span>
</template>
</UniTable>
</template>
<style scoped>
.customer-header-text {
color: red;
}
</style>
No Data
View Source
<script setup lang="ts">
import { UniTable } from "unify-ui";
const columns: InstanceType<typeof UniTable>["$props"]["columns"] = [
{
title: "Title",
key: "title",
width: 120,
},
{
title: "Author",
key: "author",
width: 200,
},
{
title: "Post",
key: "post",
},
];
</script>
<template>
<div :style="{ marginBottom: '50px' }">
<UniTable row-key="id" :columns="columns" :data="[]"> </UniTable>
</div>
<UniTable row-key="id" :columns="columns" :data="[]">
<template #empty>
<div class="placeholder">
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 512 512">
<path
fill="currentColor"
d="M256 16C123.452 16 16 123.452 16 256s107.452 240 240 240s240-107.452 240-240S388.548 16 256 16Zm147.078 387.078a207.253 207.253 0 1 1 44.589-66.125a207.332 207.332 0 0 1-44.589 66.125Z"
/>
<path
fill="currentColor"
d="M168 320h176v32H168zm42.63-91.958l-24.042-21.371l21.37-24.041l-23.916-21.26l-21.371 24.042l-24.041-21.37l-21.26 23.916l24.042 21.371l-21.37 24.041l23.916 21.26l21.371-24.042l24.041 21.37l21.26-23.916zm173.328-45.412l-23.916-21.26l-21.371 24.042l-24.041-21.37l-21.26 23.916l24.042 21.371l-21.37 24.041l23.916 21.26l21.371-24.042l24.041 21.37l21.26-23.916l-24.042-21.371l21.37-24.041z"
/>
</svg>
<span>Customize empty data placeholder</span>
</div>
</template>
</UniTable>
</template>
<style scoped>
.placeholder {
display: flex;
flex-direction: column;
padding: 20px;
align-items: center;
color: rgba(0, 0, 0, 0.3);
}
</style>
Sort
To enable the table column sort feature, set the column.sortable
property. The default shot types are ascending
and descending
. If you only want to sort in one direction, set the column.sortType
property to either ['ascending']
or ['descending']
.
When the sort event is triggered, the columnKey
and order
(sort type) of the current sort state are provided. You can use this information to request data from the server.
View Source
<script setup lang="ts">
import { ref } from "vue";
import { UniTable } from "unify-ui";
import useFetchData from "./useFetchData";
const { data } = useFetchData();
type TableType = InstanceType<typeof UniTable>;
const sort = ref<TableType["sort"]>(null);
const columns: TableType["$props"]["columns"] = [
{
title: "id",
key: "id",
sortable: true,
sortType: ["descending"],
},
{
title: "Title",
key: "title",
sortable: true,
sortType: ["ascending", "descending"],
width: 200,
},
{
title: "Author",
key: "author",
sortable: true,
sortType: ["ascending"],
width: 200,
},
];
function handleSortChange(
params: {
columnKey: string;
order: "ascending" | "descending";
} | null
) {
console.log("params:", params);
}
</script>
<template>
<UniTable v-model:sort="sort" row-key="id" :columns="columns" :data="data" @sort-change="handleSortChange">
<template #userId="{ record }"> 用户标识:{{ record.userId }} </template>
</UniTable>
</template>
Text Ellipsis
View Source
<script setup lang="ts">
import { UniTable } from "unify-ui";
import useFetchData from "./useFetchData";
const { data } = useFetchData();
const columns: InstanceType<typeof UniTable>["$props"]["columns"] = [
{
title: "Title",
key: "title",
width: 150,
},
{
title: "Author",
key: "author",
width: 150,
ellipsis: true,
},
{
title: "Post",
key: "post",
ellipsis: true,
},
];
</script>
<template>
<UniTable row-key="id" :columns="columns" :data="data"> </UniTable>
</template>
Column Resize
To enable table column resizing, use v-model:column
to bind the reactive column definition. Set the column.resizable
property to indicate which columns should be resizable. When a column's width is changed, the column.width
property will be updated.
View Source
<script setup lang="ts">
import { ref, type Ref } from "vue";
import { UniTable } from "unify-ui";
import useFetchData from "./useFetchData";
const { data } = useFetchData();
const columns: Ref<InstanceType<typeof UniTable>["$props"]["columns"]> = ref([
{
title: "Title",
key: "title",
fixed: "left",
width: 150,
resizeable: true,
},
{
title: "Author",
key: "author",
width: 150,
resizeable: true,
},
{
title: "Post",
key: "post",
width: 600,
resizeable: true,
},
{
title: "Actions",
key: "actions",
fixed: "right",
width: 100,
},
]);
</script>
<template>
<UniTable row-key="id" class="container" v-model:columns="columns" :data="data">
<template #actions>Delete</template>
</UniTable>
</template>
<style scoped>
.container {
width: 100%;
height: 500px;
}
</style>
API
Table Props
export type Record = any;
export type Key = string | number;
export type SortType = "ascending" | "descending";
export interface TableProps {
columns: Column[];
/** Table data */
data: Record[];
/** Enabled row can be expandable */
rowExpand?: {
expandCondition: (record: Record) => boolean;
showExpandRowDefault?: boolean;
};
/** Row's unique key */
rowKey: Key;
/** The set of selected row keys */
selectedRowKeys?: Set<Key>;
/** Config of row selection */
selection?: {
type: "multiple" | "single";
disabledCondition?: (record: Record) => boolean;
};
/** Whether to show foot */
showFoot?: boolean;
/** Config of row sort */
sort?: {
columnKey: Key;
order: SortType;
} | null;
/** Class name of Table body row */
tbodyCellClass?: string;
/** Class name of table body row cell */
tbodyRowClass?: string | ((record: Record) => string);
}
columns
interface Column {
/**
* If the text content in a cell exceeds the available space, it can be clipped and
* replaced with an ellipsis to indicate truncation
*/
ellipsis?: boolean;
/** `left` or `right`. To set Column to fixed left or right of the table */
fixed?: "left" | "right";
/** Column key */
key: string;
/** To set Column to be Sortable */
sortable?: boolean;
/** The column sort type. Array need to be one of the following:`ascending` or `descending`. */
sortType?: SortType[];
/** Column title */
title: string;
/** Column width. When a column is fixed, it is necessary to provide the 'width' property */
width?: number;
/**
* Minimum width of the column
* @default 200
*/
minWidth?: number;
/** Whether the column is resizable */
resizable?: boolean;
}
Event
export type SortType = "ascending" | "descending";
interface TableEmits {
(e: "update:selectedRowKeys", selectedRowKeys: Set<Key>): void;
(e: "update:sort", params: { columnKey: Key; order: SortType } | null): void;
/** Emits the "select" event when a row is selected or deselected. */
(e: "select", params: { selected: boolean; rowKey: Key; record: Record }): void;
/** Emits the "selectAll" event when all rows are selected or deselected. */
(e: "selectAll", params: { selected: boolean; rowKeys: Key[]; records: Record[] }): void;
/** Emits the "sortChange" event when the column sort order changes */
(e: "sortChange", params: { columnKey: Key; order: SortType } | null): void;
}