Table
Generate tables through configuration, with built-in features more suitable for middle and back-end business.
TIP
Some attributes are configured by default inside z-table, for example: align is set to center
Basic Usage
Configure column to generate table items. el-table related attributes are passed directly on the z-table component, el-table-column attributes are configured in column.
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
interface RowData {
name: string
gender: string
age: number
time: string
}
const loading = ref(false)
const tableData = ref<RowData[]>([])
const columns = ref([
{
prop: 'name',
label: 'Name',
},
{
prop: 'gender',
label: 'Gender',
},
{
prop: 'age',
label: 'Age',
},
{
prop: 'time',
label: 'Date',
},
])
const pagination = ref({
page: 1,
pageSize: 2,
total: 0,
})
function mockApi(params: { page: number, pageSize: number }): Promise<{ result: { page: number, pageSize: number, total: number, list: RowData[] } }> {
console.log(params, 'params')
return new Promise((resolve) => {
setTimeout(() => {
const dataFirstPage = [
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
]
const dataSecondPage = [
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
result: {
page: 1,
pageSize: 10,
total: 4,
list: pagination.value.page === 1 ? dataFirstPage : dataSecondPage,
},
})
}, 100)
})
}
async function getTableData() {
loading.value = true
try {
const res = await mockApi({ ...pagination.value })
tableData.value = res.result.list
pagination.value.total = res.result.total
}
catch (error) {
console.log(error)
}
loading.value = false
}
getTableData()
</script>
<template>
<z-table
v-model:pagination="pagination"
v-model:data="tableData"
:columns="columns"
:loading="loading"
@refresh="getTableData"
>
<template #expand="row">
{{ row.$index }}
</template>
</z-table>
</template>Table Title
Configure title attribute to generate table title, supports string and function types, can also use tableTitle slot for customization.
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
interface RowData {
name: string
gender: string
age: number
time: string
}
const loading = ref(false)
const tableData = ref<RowData[]>([])
const pagination = ref({
page: 1,
pageSize: 2,
total: 0,
})
const columns = ref([
{
prop: 'name',
label: 'Name',
},
{
prop: 'gender',
label: 'Gender',
},
{
prop: 'age',
label: 'Age',
},
{
prop: 'time',
label: 'Date',
},
])
function mockApi(params: { page: number, pageSize: number }): Promise<{ result: { page: number, pageSize: number, total: number, list: RowData[] } }> {
console.log(params, 'params')
return new Promise((resolve) => {
setTimeout(() => {
const dataFirstPage = [
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
]
const dataSecondPage = [
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
result: {
page: 1,
pageSize: 10,
total: 4,
list: pagination.value.page === 1 ? dataFirstPage : dataSecondPage,
},
})
}, 100)
})
}
async function getTableData() {
loading.value = true
try {
const res = await mockApi({ ...pagination.value })
tableData.value = res.result.list
pagination.value.total = res.result.total
}
catch (error) {
console.log(error)
}
loading.value = false
}
getTableData()
</script>
<template>
<z-table
v-model:pagination="pagination"
v-model:data="tableData"
:columns="columns"
:loading="loading"
title="Table Title"
@refresh="getTableData"
/>
</template>Operation Buttons
Configure operation items in column, pass button to type, configure buttons array. Button attributes can be configured directly in operation items.
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
import type { TableColumnScopeData } from 'ideaz-element'
interface RowData {
name: string
gender: string
age: number
time: string
}
const loading = ref(false)
const tableData = ref<RowData[]>([])
const pagination = ref({
page: 1,
pageSize: 2,
total: 0,
})
const columns = ref([
{
prop: 'name',
label: 'Name',
},
{
prop: 'gender',
label: 'Gender',
},
{
prop: 'age',
label: 'Age',
},
{
prop: 'time',
label: 'Date',
},
{
type: 'button',
label: 'Actions',
buttons: [
{
type: 'primary',
link: true,
label: 'Edit',
onClick: ({ row }: TableColumnScopeData<RowData>) => {
console.log(row, 'edit')
},
},
{
type: 'danger',
label: 'Delete',
onClick: ({ row }: TableColumnScopeData<RowData>) => {
console.log(row, 'delete')
},
},
],
},
])
function mockApi(params: { page: number, pageSize: number }): Promise<{ result: { page: number, pageSize: number, total: number, list: RowData[] } }> {
console.log(params, 'params')
return new Promise((resolve) => {
setTimeout(() => {
const dataFirstPage = [
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
]
const dataSecondPage = [
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
result: {
page: 1,
pageSize: 10,
total: 4,
list: pagination.value.page === 1 ? dataFirstPage : dataSecondPage,
},
})
}, 100)
})
}
async function getTableData() {
loading.value = true
try {
const res = await mockApi({ ...pagination.value })
tableData.value = res.result.list
pagination.value.total = res.result.total
}
catch (error) {
console.log(error)
}
loading.value = false
}
getTableData()
</script>
<template>
<z-table
v-model:pagination="pagination"
v-model:data="tableData"
:columns="columns"
:loading="loading"
@refresh="getTableData"
/>
</template>Operation buttons also support dynamic attributes, such as: disabled, etc. Pass a method with current row related data as parameter.
<!-- eslint-disable unused-imports/no-unused-vars -->
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
import type { TableColumnScopeData } from 'ideaz-element'
interface RowData {
name: string
gender: string
age: number
time: string
}
const loading = ref(false)
const tableData = ref<RowData[]>([])
const pagination = ref({
page: 1,
pageSize: 2,
total: 0,
})
const columns = ref([
{
prop: 'name',
label: 'Name',
},
{
prop: 'gender',
label: 'Gender',
},
{
prop: 'age',
label: 'Age',
},
{
prop: 'time',
label: 'Date',
},
{
type: 'button',
label: 'Actions',
buttons: [
{
type: 'primary',
link: true,
label: 'Edit',
disabled: ({ row, column, $index }: TableColumnScopeData<RowData>) => row.name === 'Steven',
onClick: ({ row }: TableColumnScopeData<RowData>) => {
console.log(row, 'edit')
},
},
{
type: 'danger',
link: true,
label: 'Delete',
disabled: ({ row, column, $index }: TableColumnScopeData<RowData>) => row.age === 18,
onClick: ({ row }: TableColumnScopeData<RowData>) => {
console.log(row, 'delete')
},
},
],
},
])
function mockApi(params: { page: number, pageSize: number }): Promise<{ result: { page: number, pageSize: number, total: number, list: RowData[] } }> {
console.log(params, 'params')
return new Promise((resolve) => {
setTimeout(() => {
const dataFirstPage = [
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
]
const dataSecondPage = [
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
result: {
page: 1,
pageSize: 10,
total: 4,
list: pagination.value.page === 1 ? dataFirstPage : dataSecondPage,
},
})
}, 100)
})
}
async function getTableData() {
loading.value = true
try {
const res = await mockApi({ ...pagination.value })
tableData.value = res.result.list
pagination.value.total = res.result.total
}
catch (error) {
console.log(error)
}
loading.value = false
}
getTableData()
</script>
<template>
<z-table
v-model:pagination="pagination"
v-model:data="tableData"
:columns="columns"
:loading="loading"
@refresh="getTableData"
/>
</template>Operation Dropdown
If dropdown is needed, configure type as dropdown in buttons array, configure dropdown options in children
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
import type { TableColumnScopeData } from 'ideaz-element'
interface RowData {
name: string
gender: string
age: number
time: string
}
const loading = ref(false)
const tableData = ref([
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
])
const columns = ref([
{
prop: 'name',
label: 'Name',
},
{
prop: 'gender',
label: 'Gender',
},
{
prop: 'age',
label: 'Age',
},
{
prop: 'time',
label: 'Date',
},
{
type: 'button',
label: 'Actions',
width: '200px',
buttons: [
{
type: 'primary',
link: true,
label: 'Edit',
onClick: ({ row }: TableColumnScopeData<RowData>) => {
console.log(row, 'edit')
},
},
{
type: 'danger',
link: true,
label: 'Delete',
onClick: ({ row }: TableColumnScopeData<RowData>) => {
console.log(row, 'delete')
},
},
{
type: 'dropdown',
reference: 'Delete',
children: [
{
type: 'primary',
link: true,
label: 'Copy',
onClick: ({ row }: TableColumnScopeData<RowData>) => {
console.log(row, 'copy')
},
},
{
type: 'danger',
link: true,
label: 'Actions',
onClick: ({ row }: TableColumnScopeData<RowData>) => {
console.log(row, 'operate')
},
},
],
},
],
},
])
</script>
<template>
<z-table
:data="tableData"
:loading="loading"
:columns="columns"
/>
</template>reference field configures dropdown reference text (default is More), supports function and string types.
Supports configuring el-dropdown and el-dropdown-item component attributes and methods.
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { h, ref } from 'vue'
import type { TableColumnScopeData } from 'ideaz-element'
interface RowData {
name: string
gender: string
age: number
time: string
}
const loading = ref(false)
const tableData = ref([
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
])
const columns = ref([
{
prop: 'name',
label: 'Name',
},
{
prop: 'gender',
label: 'Gender',
},
{
prop: 'age',
label: 'Age',
},
{
prop: 'time',
label: 'Date',
},
{
type: 'button',
label: 'Actions',
buttons: [
{
type: 'dropdown',
reference: 'Actions',
placement: 'top-start',
children: [
{
type: 'primary',
link: true,
label: 'Edit',
onClick: ({ row }: TableColumnScopeData<RowData>) => {
console.log(row, 'edit')
},
},
{
type: 'danger',
link: true,
label: 'Delete',
onClick: ({ row }: TableColumnScopeData<RowData>) => {
console.log(row, 'delete')
},
},
],
},
{
type: 'dropdown',
reference: () => h('span', { style: { cursor: 'pointer' } }, 'Actions2'),
placement: 'top',
onVisibleChange: (visible: boolean) => {
console.log(visible, 'visible')
},
children: [
{
type: 'primary',
link: true,
label: 'Copy',
onClick: ({ row }: TableColumnScopeData<RowData>) => {
console.log(row, 'copy')
},
},
{
type: 'danger',
link: true,
label: 'Actions',
divided: true,
onClick: ({ row }: TableColumnScopeData<RowData>) => {
console.log(row, 'operate')
},
},
],
},
],
},
])
</script>
<template>
<z-table
:data="tableData"
:loading="loading"
:columns="columns"
/>
</template>Pagination
Configure pagination, supports two-way binding to implement pagination effect. layout defaults to total, sizes, prev, pager, next, jumper, pageSizes defaults to [100, 200, 300, 400, 500], supports customization.
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
interface RowData {
name: string
gender: string
age: number
time: string
}
const loading = ref(false)
const tableData = ref<RowData[]>([])
const pagination = ref({
page: 1,
pageSize: 2,
total: 0,
layout: 'total, prev, pager, next',
})
const columns = ref([
{
prop: 'name',
label: 'Name',
},
{
prop: 'gender',
label: 'Gender',
},
{
prop: 'age',
label: 'Age',
},
{
prop: 'time',
label: 'Date',
},
])
function mockApi(params: { page: number, pageSize: number }): Promise<{ result: { page: number, pageSize: number, total: number, list: RowData[] } }> {
console.log(params, 'params')
return new Promise((resolve) => {
setTimeout(() => {
const dataFirstPage = [
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
]
const dataSecondPage = [
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
result: {
page: 1,
pageSize: 10,
total: 4,
list: pagination.value.page === 1 ? dataFirstPage : dataSecondPage,
},
})
}, 100)
})
}
async function getTableData() {
loading.value = true
try {
const res = await mockApi({ ...pagination.value })
tableData.value = res.result.list
pagination.value.total = res.result.total
}
catch (error) {
console.log(error)
}
loading.value = false
}
getTableData()
</script>
<template>
<z-table
v-model:pagination="pagination"
v-model:data="tableData"
:columns="columns"
:loading="loading"
@refresh="getTableData"
/>
</template>Configure paginationLeft, paginationRight, paginationTop, paginationBottom slots to customize pagination top, bottom, left, right content.
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
import type { Pagination } from 'ideaz-element'
const loading = ref(false)
const tableData = ref<any>([])
const pagination = ref({
page: 1,
pageSize: 2,
total: 0,
layout: 'total, sizes, prev, pager, next, jumper',
})
const columns = ref([
{
prop: 'name',
label: 'Name',
},
{
prop: 'gender',
label: 'Gender',
},
{
prop: 'age',
label: 'Age',
},
{
prop: 'time',
label: 'Date',
},
])
function mockApi(pagination: Pagination): Promise<{ result: { page: number, pageSize: number, total: number, list: any[] } }> {
return new Promise((resolve) => {
setTimeout(() => {
const dataFirstPage = [
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
]
const dataSecondPage = [
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
result: {
page: 1,
pageSize: 10,
total: 4,
list: pagination.page === 1 ? dataFirstPage : dataSecondPage,
},
})
}, 100)
})
}
async function getTableData() {
loading.value = true
try {
const res = await mockApi({ ...pagination.value })
tableData.value = res.result.list
pagination.value.total = res.result.total
}
catch (error) {
console.log(error)
}
loading.value = false
}
getTableData()
</script>
<template>
<z-table
v-model:pagination="pagination"
:data="tableData"
:loading="loading"
:columns="columns"
@refresh="getTableData"
>
<template #paginationTop>
<div class="mb-4">
<el-card>paginationTop</el-card>
</div>
</template>
<template #paginationBottom>
<div class="mb-4">
<el-card>paginationBottom</el-card>
</div>
</template>
<template #paginationLeft>
<div class="mb-4">
<el-card>paginationLeft</el-card>
</div>
</template>
<template #paginationRight>
<div class="mb-4">
<el-card>paginationRight</el-card>
</div>
</template>
</z-table>
</template>Frontend Pagination
Configure pagination type as front to enable frontend pagination functionality, pass all data to totalData field.
When pageSize is 0, pagination is false or pagination is not passed, pagination is not displayed.
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
interface RowData {
name: string
gender: string
age: number
time: string
}
const loading = ref(false)
const tableData = ref([])
const totalData = ref<RowData[]>([])
const pagination = ref({
type: 'front',
page: 1,
pageSize: 2,
total: 0,
layout: 'total, sizes, prev, pager, next, jumper',
})
const columns = ref([
{
prop: 'name',
label: 'Name',
},
{
prop: 'gender',
label: 'Gender',
},
{
prop: 'age',
label: 'Age',
},
{
prop: 'time',
label: 'Date',
},
])
function mockApi(params: { page: number, pageSize: number }): Promise<{ result: { page: number, pageSize: number, total: number, list: RowData[] } }> {
console.log(params, 'pagination front params')
return new Promise((resolve) => {
setTimeout(() => {
const data = [
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
result: {
page: 1,
pageSize: 10,
total: 4,
list: data,
},
})
}, 100)
})
}
async function getTableData() {
loading.value = true
try {
const res = await mockApi({ ...pagination.value })
totalData.value = res.result.list
pagination.value.total = res.result.total
}
catch (error) {
console.log(error)
}
loading.value = false
}
getTableData()
</script>
<template>
{{ tableData }}
<z-table
v-model:pagination="pagination"
v-model:data="tableData"
:loading="loading"
:columns="columns"
:total-data="totalData"
@refresh="getTableData"
/>
</template>Pagination Position
Configure pagination align field, supports left, center, right, defaults to right.
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
interface RowData {
name: string
gender: string
age: number
time: string
}
const loading = ref(false)
const tableData = ref<RowData[]>([])
const pagination = ref({
page: 1,
pageSize: 2,
total: 0,
layout: 'total, sizes, prev, pager, next, jumper',
align: 'center',
})
const alignOptions = [
{ label: 'left', value: 'left' },
{ label: 'center', value: 'center' },
{ label: 'right', value: 'right' },
]
const columns = ref([
{
prop: 'name',
label: 'Name',
},
{
prop: 'gender',
label: 'Gender',
},
{
prop: 'age',
label: 'Age',
},
{
prop: 'time',
label: 'Date',
},
])
function mockApi(params: { page: number, pageSize: number }): Promise<{ result: { page: number, pageSize: number, total: number, list: RowData[] } }> {
console.log(params, 'params')
return new Promise((resolve) => {
setTimeout(() => {
const dataFirstPage = [
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
]
const dataSecondPage = [
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
result: {
page: 1,
pageSize: 10,
total: 4,
list: pagination.value.page === 1 ? dataFirstPage : dataSecondPage,
},
})
}, 100)
})
}
async function getTableData() {
loading.value = true
try {
const res = await mockApi({ ...pagination.value })
tableData.value = res.result.list
pagination.value.total = res.result.total
}
catch (error) {
console.log(error)
}
loading.value = false
}
getTableData()
</script>
<template>
<z-radio v-model="pagination.align" :options="alignOptions" type="radio-button" />
<z-table
v-model:pagination="pagination"
v-model:data="tableData"
:columns="columns"
:loading="loading"
@refresh="getTableData"
/>
</template>Hide Columns
Configure hide field in column, supports function or boolean value. Function returns boolean value, true means hide, false means show.
<script lang="ts" setup>
import { ref } from 'vue'
const isHide = ref(false)
const tableData = ref([
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
])
const columns = ref([
{
prop: 'name',
label: 'Name',
hide: () => isHide.value,
},
{
prop: 'gender',
label: 'Gender',
hide: true,
},
{
prop: 'age',
label: 'Age',
},
{
prop: 'time',
label: 'Date',
},
])
function changeVisible() {
isHide.value = !isHide.value
}
</script>
<template>
<el-button @click="changeVisible">
Toggle column visibility
</el-button>
<z-table
:data="tableData"
:columns="columns"
/>
</template>Custom Column
Configure slot or render in column to implement custom column content.
<script lang="ts" setup>
import { ref } from 'vue'
import type { TableColumnScopeData } from 'ideaz-element'
interface RowData {
name: string
gender: string
age: number
time: string
}
const tableData = ref<RowData[]>([
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
])
const columns = ref([
{
prop: 'name',
label: 'Name',
render: ({ row }: TableColumnScopeData<RowData>) => h('span', row.name),
},
{
prop: 'gender',
label: 'Gender',
slot: 'gender',
},
{
prop: 'age',
label: 'Age',
},
{
prop: 'time',
label: 'Date',
},
])
</script>
<template>
<z-table
:data="tableData"
:columns="columns"
>
<template #gender="{ row }">
<el-input :model-value="row.gender" />
</template>
</z-table>
</template>Column Types
Configure type in column to implement table column types, supports expand, radio, selection, index.
Supports custom column components, configure component field, supports input, select, datepicker, switch, any locally or globally registered components.
TIP
When type is radio or cross-page selection checkbox is needed, it needs to be used with rowKey (default id).
TIP
When passing components directly to component, please use markRaw wrapper to prevent performance impact.
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { markRaw, ref } from 'vue'
import { ElInput } from 'element-plus'
import type { TableColumnScopeData } from 'ideaz-element'
interface RowData {
id: number
name: string
gender: string
age: number
time: string
}
const tableData = ref<RowData[]>([
{
id: 1,
name: 'Steven',
gender: '1',
age: 22,
time: '2020-01-01',
},
{
id: 2,
name: 'Helen',
gender: '1',
age: 12,
time: '2012-01-01',
},
{
id: 3,
name: 'Nancy',
gender: '2',
age: 18,
time: '2018-01-01',
},
{
id: 4,
name: 'Jack',
gender: '1',
age: 28,
time: '2028-01-01',
},
])
const columns = ref([
{
type: 'expand',
},
{
type: 'index',
},
{
type: 'radio',
},
{
type: 'selection',
},
{
component: 'input',
prop: 'name',
label: 'Name',
onChange: ({ row, column, $index }: TableColumnScopeData<RowData>, val: string) => {
console.log('change event', row, column, $index, val)
},
onInput: ({ row, column, $index }: TableColumnScopeData<RowData>, val: string) => {
console.log('input event', row, column, $index, val)
},
fieldProps: {
clearable: true,
},
},
{
component: 'select',
prop: 'gender',
label: 'Gender',
fieldProps: {
clearable: true,
},
onChange: ({ row, column, $index }: TableColumnScopeData<RowData>, val: string) => {
console.log('change event', row, column, $index, val)
},
},
{
prop: 'age',
label: 'Age',
component: markRaw(ElInput),
fieldProps: {
clearable: true,
},
onChange: ({ row, column, $index }: TableColumnScopeData<RowData>, val: string) => {
console.log('change event', row, column, $index, val)
},
onInput: ({ row }: TableColumnScopeData<RowData>, val: string) => {
console.log('input event', row, val)
},
},
{
prop: 'time',
label: 'Date',
},
])
const options = {
gender: [
{ label: 'Male', value: '1' },
{ label: 'Female', value: '2' },
],
}
</script>
<template>
<z-table v-model:data="tableData" :columns="columns" :options="options">
<template #expand>
<span>Expanded content</span>
</template>
</z-table>
</template>Dynamic Attributes
column custom content supports dynamic attributes. Component attributes like disabled, placeholder support passing functions (function attributes are not supported yet, such as: formatter attribute of ElInput component), parameter is current row scope data.
<!-- eslint-disable unused-imports/no-unused-vars -->
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
import type { TableColumnScopeData } from 'ideaz-element'
interface RowData {
id: number
name: string
gender: string
age: number
time: string
}
const tableData = ref([
{
id: 1,
name: 'Steven',
gender: '1',
age: 22,
time: '2020-01-01',
},
{
id: 2,
name: 'Helen',
gender: '1',
age: 12,
time: '2012-01-01',
},
{
id: 3,
name: 'Nancy',
gender: '2',
age: 18,
time: '2018-01-01',
},
{
id: 4,
name: 'Jack',
gender: '1',
age: 28,
time: '2028-01-01',
},
])
const columns = ref([
{
component: 'input',
prop: 'name',
label: 'Name',
onChange: ({ row }: TableColumnScopeData<RowData>, val: string) => {
console.log('change event', row, val)
},
onInput: ({ row }: TableColumnScopeData<RowData>, val: string) => {
console.log('input event', row, val)
},
fieldProps: {
clearable: true,
disabled: ({ row, column, $index }: TableColumnScopeData<RowData>) => {
return row.id === 1
},
},
},
{
component: 'select',
prop: 'gender',
label: 'Gender',
onChange: ({ row }: TableColumnScopeData<RowData>, val: string) => {
console.log('change event', row, val)
},
fieldProps: {
placeholder: ({ row, column, $index }: TableColumnScopeData<RowData>) => {
return `${row.name}Gender${$index}`
},
clearable: true,
},
},
{
prop: 'age',
label: 'Age',
},
{
prop: 'time',
label: 'Date',
},
])
const options = {
gender: [
{ label: 'Male', value: '1' },
{ label: 'Female', value: '2' },
],
}
</script>
<template>
<z-table v-model:data="tableData" :columns="columns" :options="options" />
</template>Custom Table Header
Configure label in column as string with slot or Slot or configure as render function to implement custom column header.
<script lang="ts" setup>
import { h, ref } from 'vue'
const tableData = ref([
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
])
const columns = ref([
{
prop: 'name',
label: () => h('span', 'Custom Header'),
},
{
prop: 'gender',
label: 'genderHeaderSlot',
},
{
prop: 'age',
label: 'Age',
},
{
prop: 'time',
label: 'Date',
},
])
</script>
<template>
<z-table
:data="tableData"
:columns="columns"
>
<template #genderHeaderSlot="scope">
<span>Gender custom header {{ scope.$index }}</span>
</template>
</z-table>
</template>Column Tooltip
Configure tooltip in column to implement table header tooltip functionality, supports function and string.
<script lang="ts" setup>
import { h, ref } from 'vue'
const tableData = ref([
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
])
const columns = ref([
{
prop: 'name',
label: 'Name',
tooltip: () => h('span', 'NameHint'),
},
{
prop: 'gender',
label: 'Gender',
tooltip: 'GenderHint',
},
{
prop: 'age',
label: 'Age',
},
{
prop: 'time',
label: 'Date',
},
])
</script>
<template>
<z-table
:data="tableData"
:columns="columns"
/>
</template>Merge Same Items
Configure table attribute mergeCells, supports separate configuration of rows or columns, supports field configuration.
interface mergeCells {
direction: 'row' | 'column' | 'both' // Merge direction: row, column, or both
props?: string[] // Fields to merge, if not passed, all columns participate in merging
}<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
interface RowData {
id: number
name: string
gender: string
age: number
time: string
}
const tableData = ref<RowData[]>([
{
id: 1,
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
id: 2,
name: 'Steven',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
id: 3,
name: 'female',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
id: 4,
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
])
const columns = ref([
{
prop: 'name',
label: 'Name',
},
{
prop: 'gender',
label: 'Gender',
},
{
prop: 'age',
label: 'Age',
},
{
prop: 'time',
label: 'Date',
},
])
</script>
<template>
<z-table
v-model:data="tableData"
:columns="columns"
:draggable="true"
:merge-cells="{
direction: 'both',
}"
border
/>
</template>Toolbar
toolBarconfiguration item, used to configure table toolbar.
When toolBar value is false, toolbar is not displayed.
If you want to configure certain features not to display, configure the four fields refresh, density, fullScreen, setting under toolBar as false.
<script lang="ts" setup>
import { ref } from 'vue'
const tableData = ref([
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
])
const columns = ref([
{
prop: 'name',
label: 'Name',
},
{
prop: 'gender',
label: 'Gender',
},
{
prop: 'age',
label: 'Age',
},
{
prop: 'time',
label: 'Date',
},
])
</script>
<template>
<z-table
:data="tableData"
:columns="columns"
:tool-bar="false"
/>
</template>toolBar supports configuring default unchecked items, configure uncheck field, value is label of column items.
<script lang="ts" setup>
import { ref } from 'vue'
const tableData = ref([
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
])
const columns = ref([
{
prop: 'name',
label: 'Name',
},
{
prop: 'gender',
label: 'Gender',
},
{
prop: 'age',
label: 'Age',
},
{
prop: 'time',
label: 'Date',
},
])
</script>
<template>
<z-table
:data="tableData"
:columns="columns"
:tool-bar="{ uncheck: ['Gender'], density: false, setting: false }"
/>
</template>toolBar supports excluding certain table items, configure exclude field, value is label of column items.
<script lang="ts" setup>
import { ref } from 'vue'
const tableData = ref([
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
])
const columns = ref([
{
prop: 'name',
label: 'Name',
},
{
prop: 'gender',
label: 'Gender',
},
{
prop: 'age',
label: 'Age',
},
{
prop: 'time',
label: 'Date',
},
])
</script>
<template>
<z-table
:data="tableData"
:columns="columns"
:tool-bar="{ exclude: ['Gender'], fullScreen: false, refresh: false }"
/>
</template>toolBar top, bottom, left, right content supports customization through toolBarTop, toolBarBottom, toolBarRight, toolBarLeft, tableTitle slot configuration.
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
interface RowData {
name: string
gender: string
age: number
time: string
}
const loading = ref(false)
const tableData = ref<RowData[]>([])
const pagination = ref({
page: 1,
pageSize: 2,
total: 0,
layout: 'total, prev, pager, next',
})
const columns = ref([
{
prop: 'name',
label: 'Name',
},
{
prop: 'gender',
label: 'Gender',
},
{
prop: 'age',
label: 'Age',
},
{
prop: 'time',
label: 'Date',
},
])
function mockApi(params: { page: number, pageSize: number }): Promise<{ result: { page: number, pageSize: number, total: number, list: RowData[] } }> {
console.log(params, 'params')
return new Promise((resolve) => {
setTimeout(() => {
const dataFirstPage = [
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
]
const dataSecondPage = [
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
result: {
page: 1,
pageSize: 10,
total: 4,
list: pagination.value.page === 1 ? dataFirstPage : dataSecondPage,
},
})
}, 100)
})
}
async function getTableData() {
loading.value = true
try {
const res = await mockApi({ ...pagination.value })
tableData.value = res.result.list
pagination.value.total = res.result.total
}
catch (error) {
console.log(error)
}
loading.value = false
}
getTableData()
</script>
<template>
<z-table
v-model:pagination="pagination"
v-model:data="tableData"
:columns="columns"
:loading="loading"
@refresh="getTableData"
>
<template #toolBarTop>
<div class="slot-demo">
toolBarTop
</div>
</template>
<template #toolBarBottom>
<div class="slot-demo">
toolBarBottom
</div>
</template>
<template #toolBarRight>
<div class="slot-demo">
toolBarRight
</div>
</template>
<template #toolBarLeft>
<div class="slot-demo">
toolBarLeft
</div>
</template>
<template #tableTitle>
<div class="slot-demo">
tableTitle
</div>
</template>
</z-table>
</template>
<style lang="scss">
.slot-demo {
padding: 10px;
border: 1px solid var(--el-card-border-color);
border-radius: var(--el-card-border-radius);
box-shadow: var(--el-box-shadow-light);
}
</style>Data Dragging
Set draggable to true to enable data dragging.
WARNING
Must configure row-key, otherwise update issues will occur.
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
interface RowData {
id: number
name: string
gender: string
age: number
time: string
}
const tableData = ref<RowData[]>([
{
id: 1,
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
id: 2,
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
id: 3,
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
id: 4,
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
])
const columns = ref([
{
type: 'sort',
label: 'Sort',
},
{
prop: 'name',
label: 'Name',
},
{
prop: 'gender',
label: 'Gender',
},
{
prop: 'age',
label: 'Age',
},
{
prop: 'time',
label: 'Date',
},
])
function handleClick() {
console.log(tableData.value, 'handleClick')
}
function handleSortEnd(data: RowData[]) {
console.log(data, 'data')
}
</script>
<template>
<el-button @click="handleClick">
click
</el-button>
<z-table
v-model:data="tableData"
:columns="columns"
:draggable="true"
row-key="id"
@drag-sort-end="handleSortEnd"
/>
</template>Supports setting slot or render to customize drag icon.
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
interface RowData {
name: string
gender: string
age: number
time: string
}
const tableData = ref<RowData[]>([
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
])
const columns = ref([
{
type: 'sort',
label: 'Sort',
},
{
prop: 'name',
label: 'Name',
},
{
prop: 'gender',
label: 'Gender',
},
{
prop: 'age',
label: 'Age',
},
{
prop: 'time',
label: 'Date',
},
])
function handleSortEnd(data: RowData[]) {
console.log(data, 'data')
}
</script>
<template>
<z-table
:data="tableData"
:columns="columns"
:draggable="true"
@drag-sort-end="handleSortEnd"
>
<template #sort>
<el-icon size="16" class="cursor-pointer">
<i-setting />
</el-icon>
</template>
</z-table>
</template>Editable Table
Set editable to true to enable table edit mode. This field supports boolean or object type, editable table type defaults to single.
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
const tableData = ref([
{
name: 'Steven',
gender: '1',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: '1',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: '2',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: '1',
age: 28,
time: '2028-01-01',
},
])
const columns = ref([
{
component: 'input',
prop: 'name',
label: 'Name',
},
{
component: 'select',
prop: 'gender',
label: 'Gender',
},
{
component: 'input',
prop: 'age',
label: 'Age',
},
{
component: 'el-date-picker',
prop: 'time',
label: 'Date',
fieldProps: {
valueFormat: 'YYYY-MM-DD',
},
},
])
const options = {
gender: [
{ label: 'Male', value: '1' },
{ label: 'Female', value: '2' },
],
}
function handleClick() {
console.log(tableData.value, 'handleClick')
}
</script>
<template>
<el-button @click="handleClick">
click
</el-button>
<z-table
v-model:data="tableData"
:columns="columns"
:options="options"
:editable="true"
/>
</template>Set editable type to multiple to enable multi-row edit mode.
Configure maxLength of editable to set maximum add quantity. Configure deleteConfirm of editable to true to enable delete confirmation.
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
const tableData = ref([
{
name: 'Steven',
gender: '1',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: '1',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: '2',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: '1',
age: 28,
time: '2028-01-01',
},
])
const columns = ref([
{
component: 'input',
prop: 'name',
label: 'Name',
},
{
component: 'select',
prop: 'gender',
label: 'Gender',
},
{
component: 'input',
prop: 'age',
label: 'Age',
},
{
component: 'el-date-picker',
prop: 'time',
label: 'Date',
fieldProps: {
valueFormat: 'YYYY-MM-DD',
},
},
])
const options = {
gender: [
{ label: 'Male', value: '1' },
{ label: 'Female', value: '2' },
],
}
function handleClick() {
console.log(tableData.value, 'handleClick')
}
</script>
<template>
<el-button @click="handleClick">
click
</el-button>
<z-table
v-model:data="tableData"
:columns="columns"
:options="options"
:editable="{ type: 'multiple', deleteConfirm: true }"
/>
</template>Configure onSave, onDelete, onEdit, onCancel of editable.
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
import type { EditableTableEventParams } from 'ideaz-element'
interface RowData {
name: string
gender: string
age: number
time: string
__isEdit?: boolean
}
const tableData = ref<RowData[]>([
{
name: 'Steven',
gender: '1',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: '1',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: '2',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: '1',
age: 28,
time: '2028-01-01',
},
])
const columns = ref([
{
component: 'input',
prop: 'name',
label: 'Name',
},
{
component: 'select',
prop: 'gender',
label: 'Gender',
},
{
component: 'input',
prop: 'age',
label: 'Age',
},
{
component: 'el-date-picker',
prop: 'time',
label: 'Date',
fieldProps: {
valueFormat: 'YYYY-MM-DD',
},
},
])
const options = {
gender: [
{ label: 'Male', value: '1' },
{ label: 'Female', value: '2' },
],
}
const editable = {
type: 'single',
maxLength: 5,
onCancel: ({ row, $index, column, formRef }: EditableTableEventParams<RowData>) => {
console.log(row, $index, column, formRef, 'row onCancel')
},
onSave: ({ row, $index, column, formRef }: EditableTableEventParams<RowData>) => {
console.log(row, $index, column, formRef, 'row onSave')
},
onDelete: ({ row, $index, column, formRef }: EditableTableEventParams<RowData>) => {
console.log(row, $index, column, formRef, 'row onDelete')
},
onEdit: ({ row, $index, column, formRef }: EditableTableEventParams<RowData>) => {
row.__isEdit = true
console.log(row, $index, column, formRef, 'row onEdit')
},
}
</script>
<template>
<z-table
v-model:data="tableData"
:columns="columns"
:options="options"
:editable="editable"
/>
</template>Supports custom operation buttons.
<script lang="ts" setup>
import type { Ref } from 'vue'
import { ref } from 'vue'
import type { DefaultButtonOperation, TableColumnScopeData } from 'ideaz-element'
interface RowData {
name: string
gender: string
age: number
time: string
__isEdit: boolean
}
const tableData = ref([
{
name: 'Steven',
gender: '1',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: '1',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: '2',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: '1',
age: 28,
time: '2028-01-01',
},
])
const columns = ref([
{
component: 'input',
prop: 'name',
label: 'Name',
},
{
component: 'select',
prop: 'gender',
label: 'Gender',
},
{
component: 'input',
prop: 'age',
label: 'Age',
},
{
component: 'el-date-picker',
prop: 'time',
label: 'Date',
fieldProps: {
valueFormat: 'YYYY-MM-DD',
},
},
{
type: 'button',
label: 'Actions',
buttons: ({ renderEdit, renderCancel, renderDelete, renderSave }: DefaultButtonOperation, tableData: Ref<RowData[]>) => {
return [
{
type: 'primary',
link: true,
label: 'Copy',
hide: ({ row }: TableColumnScopeData<RowData>) => row.__isEdit,
onClick: ({ row }: TableColumnScopeData<RowData>) => {
tableData.value.push({ ...row })
},
},
renderEdit,
renderCancel,
renderDelete,
renderSave,
]
},
},
])
const options = {
gender: [
{ label: 'Male', value: '1' },
{ label: 'Female', value: '2' },
],
}
const editable = {
type: 'single',
maxLength: 5,
}
</script>
<template>
<z-table
:data="tableData"
:columns="columns"
:options="options"
:editable="editable"
/>
</template>Sticky
Implement sticky functionality by configuring sticky attribute's top, parent (DOM element where scroll bar appears) and zIndex. top defaults to 50px, zIndex defaults to 100.
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { h, ref } from 'vue'
interface RowData {
name: string
gender: string
age: number
time: string
}
const loading = ref(false)
const tableData = ref<RowData[]>([])
const columns = ref([
{
prop: 'id',
label: 'id',
},
{
prop: 'name',
label: 'Name',
width: 300,
},
{
prop: 'gender',
label: 'Gender',
},
{
prop: 'age',
label: 'Age',
width: 300,
},
{
prop: 'time',
label: () => h('span', {}, 'customLabel'),
width: 300,
},
])
const pagination = ref({
page: 1,
pageSize: 2,
total: 0,
})
function mockApi(params: { page: number, pageSize: number }): Promise<{ result: { page: number, pageSize: number, total: number, list: RowData[] } }> {
console.log(params, 'params')
return new Promise((resolve) => {
setTimeout(() => {
const dataFirstPage = [
{
id: 1,
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
id: 2,
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
id: 3,
name: 'Mike',
gender: 'male',
age: 23,
time: '2020-01-01',
},
{
id: 4,
name: 'Jack',
gender: 'female',
age: 16,
time: '2012-01-01',
},
]
const dataSecondPage = [
{
id: 5,
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
id: 6,
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
result: {
page: 1,
pageSize: 10,
total: 4,
list: pagination.value.page === 1 ? dataFirstPage : dataSecondPage,
},
})
}, 100)
})
}
async function getTableData() {
loading.value = true
try {
const res = await mockApi({ ...pagination.value })
tableData.value = res.result.list
pagination.value.total = res.result.total
}
catch (error) {
console.log(error)
}
loading.value = false
}
getTableData()
</script>
<template>
<z-table
v-model:pagination="pagination"
v-model:data="tableData"
:columns="columns"
:loading="loading"
:sticky="{ parent: 'document' }"
@refresh="getTableData"
>
<template #expand="row">
{{ row.$index }}
</template>
</z-table>
</template>Supports customizing sticky table header style through sticky.style.
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { h, ref } from 'vue'
interface RowData {
name: string
gender: string
age: number
time: string
}
const loading = ref(false)
const tableData = ref<RowData[]>([])
const columns = ref([
{
prop: 'id',
label: 'id',
},
{
prop: 'name',
label: 'Name',
width: 300,
},
{
prop: 'gender',
label: 'Gender',
},
{
prop: 'age',
label: 'Age',
width: 300,
},
{
prop: 'time',
label: () => h('span', {}, 'customLabel'),
width: 300,
},
])
const pagination = ref({
page: 1,
pageSize: 2,
total: 0,
})
function mockApi(params: { page: number, pageSize: number }): Promise<{ result: { page: number, pageSize: number, total: number, list: RowData[] } }> {
console.log(params, 'params')
return new Promise((resolve) => {
setTimeout(() => {
const dataFirstPage = [
{
id: 1,
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
id: 2,
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
id: 3,
name: 'Mike',
gender: 'male',
age: 23,
time: '2020-01-01',
},
{
id: 4,
name: 'Jack',
gender: 'female',
age: 16,
time: '2012-01-01',
},
]
const dataSecondPage = [
{
id: 5,
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
id: 6,
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
result: {
page: 1,
pageSize: 10,
total: 4,
list: pagination.value.page === 1 ? dataFirstPage : dataSecondPage,
},
})
}, 100)
})
}
async function getTableData() {
loading.value = true
try {
const res = await mockApi({ ...pagination.value })
tableData.value = res.result.list
pagination.value.total = res.result.total
}
catch (error) {
console.log(error)
}
loading.value = false
}
getTableData()
</script>
<template>
<z-table
v-model:pagination="pagination"
v-model:data="tableData"
:columns="columns"
:loading="loading"
:sticky="{ parent: 'document', style: { border: '1px solid black' } }"
@refresh="getTableData"
>
<template #expand="row">
{{ row.$index }}
</template>
</z-table>
</template>Watermark
Configure watermark, for details refer to el-watermark configuration.
<script lang="ts" setup>
import { ref } from 'vue'
const tableData = ref([
{
name: 'Steven',
gender: '1',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: '1',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: '2',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: '1',
age: 28,
time: '2028-01-01',
},
])
const columns = ref([
{
component: 'input',
prop: 'name',
label: 'Name',
},
{
component: 'select',
prop: 'gender',
label: 'Gender',
},
{
component: 'input',
prop: 'age',
label: 'Age',
},
{
component: 'el-date-picker',
prop: 'time',
label: 'Date',
fieldProps: {
valueFormat: 'YYYY-MM-DD',
},
},
])
const options = {
gender: [
{ label: 'Male', value: '1' },
{ label: 'Female', value: '2' },
],
}
</script>
<template>
<z-table
:data="tableData"
:columns="columns"
:options="options"
watermark="Table watermark"
/>
</template>Table Methods
z-table table methods can be used according to el-table.
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
interface RowData {
id: number
name: string
gender: string
age: number
time: string
}
const zTableRef = ref()
const radioData = ref({})
const selectionData = ref<RowData[]>([])
const tableData = ref<RowData[]>([
{
id: 1,
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
id: 2,
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
id: 3,
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
id: 4,
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
])
const columns = ref([
{
type: 'radio',
},
{
type: 'selection',
},
{
prop: 'name',
label: 'Name',
},
{
prop: 'gender',
label: 'Gender',
},
{
prop: 'age',
label: 'Age',
},
{
prop: 'time',
label: 'Date',
},
])
function handleRadioChange(row: RowData) {
radioData.value = row
console.log(row, 'radio data')
}
function handleSelectionChange(data: RowData[]) {
selectionData.value = data
console.log(data, 'selection data')
}
function handleClear() {
zTableRef.value.clearSelection()
}
</script>
<template>
<el-button @click="handleClear">
Clear selection
</el-button>
<z-table
ref="zTableRef"
:data="tableData"
:columns="columns"
@radio-change="handleRadioChange"
@selection-change="handleSelectionChange"
/>
</template>z-table Attributes
| Attribute | Description | Type | Accepted Values | Default |
|---|---|---|---|---|
| modelValue:data | Display data, supports two-way binding | array | — | — |
| modelValue:pagination | Pagination configuration, supports two-way binding | object | — | — |
| loading | Table loading | boolean | — | — |
| title | Table title | string / function | — | — |
| columns | Table configuration items | array | — | — |
| toolBar | Toolbar configuration | object / boolean | — | — |
| editable | Editable table configuration | object / boolean | — | — |
| options | Table internal option data source | object | — | — |
| watermark | Watermark configuration | object (see el-watermark documentation for details) | — | — |
| sticky | Table header sticky configuration | object | — | — |
| totalData | All table data (effective for frontend pagination) | array | — | — |
| mergeCells | Table same item merge configuration | object | — | — |
| height | Table height, defaults to auto height. If height is number type, unit is px; if height is string type, this height will be set as Table's style.height value, Table height will be controlled by external styles. | string / number | — | — |
| max-height | Table max height. Valid values are numbers or heights in px units. | string / number | — | — |
| stripe | Whether table is striped | boolean | — | false |
| border | Whether table has vertical borders | boolean | — | false |
| size | Table size | string | large / default /small | — |
| fit | Whether column width fits content | boolean | — | true |
| show-header | Whether to show table header | boolean | — | true |
| highlight-current-row | Whether to highlight current row | boolean | — | false |
| current-row-key | Key of current row, write-only property | string / number | — | — |
| row-class-name | Function for row className, can also use string to set fixed className for all rows. | function({ row, rowIndex }) / string | — | — |
| row-style | Function for row style, can also use fixed Object to set same Style for all rows. | function({ row, rowIndex }) / object | — | — |
| cell-class-name | Function for cell className, can also use string to set fixed className for all cells. | function({ row, column, rowIndex, columnIndex }) / string | — | — |
| cell-style | Function for cell style, can also use fixed Object to set same Style for all cells. | function({ row, column, rowIndex, columnIndex }) / object | — | — |
| header-row-class-name | Function for header row className, can also use string to set fixed className for all header rows. | function({ row, rowIndex }) / string | — | — |
| header-row-style | Function for header row style, can also use fixed Object to set same Style for all header rows. | function({ row, rowIndex }) / object | — | — |
| header-cell-class-name | Function for header cell className, can also use string to set fixed className for all header cells. | function({ row, column, rowIndex, columnIndex }) / string | — | — |
| header-cell-style | Function for header cell style, can also use fixed Object to set same Style for all header cells. | function({ row, column, rowIndex, columnIndex }) / object | — | — |
| row-key | Key for row data, used to optimize Table rendering; required when using reserve-selection feature and displaying tree data. When type is String, supports multi-level access: user.info.id, but does not support user.info[0].id, use Function for this case. | function(row) / string | — | — |
| empty-text | Text displayed when data is empty, can also be set through #empty slot | string | — | No Data |
| default-expand-all | Whether to expand all rows by default, effective when Table contains expandable rows or is tree table | boolean | — | false |
| expand-row-keys | Set currently expanded rows through this property, requires row-key property to be set, this property is an array of keys for expanded rows. | array | — | — |
| default-sort | Default sort column prop and order. Its prop property specifies default sort column, order specifies default sort order | object | (order: 'ascending' 'descending') | 'descending') |
| tooltip-effect | effect of overflow tooltip | string | dark / light | dark |
| tooltip-options | Options for overflow tooltip, see tooltip component below | object | see tooltip | object |
| show-summary | Whether to show summary row at table footer | boolean | — | false |
| sum-text | Text for first column of summary row | string | — | Sum |
| summary-method | Custom summary calculation method | function({ columns, data }) | — | — |
| span-method | Method for merging rows or columns | function({ row, column, rowIndex, columnIndex }) | — | — |
| select-on-indeterminate | Behavior when clicking header checkbox when only some rows are selected in multi-select table. If true, select all rows; if false, deselect all rows | boolean | — | true |
| indent | Indentation of tree nodes when displaying tree data | number | — | 16 |
| lazy | Whether to lazy load child node data | boolean | — | — |
| load | Function for loading child node data, effective when lazy is true | function(row, treeNode, resolve) | — | — |
| tree-props | Configuration options for rendering nested data | object | — | { hasChildren: 'hasChildren', children: 'children' } |
| table-layout | Layout method for table cells, rows and columns | string | fixed / auto | fixed |
| scrollbar-always-on | Always show scrollbar | boolean | — | false |
| show-overflow-tooltip | Whether to hide extra content and show them in Tooltip when cell content overflows. This will affect all columns. | boolean / object | — | See tooltip-options |
| flexible | Ensure minimum size of main axis to not exceed content | boolean | — | false |
| virtual | Virtual scroll configuration, supports high-performance large data rendering | boolean / object | See virtual table documentation | false |
z-table Events
| Event Name | Description | Callback Parameters |
|---|---|---|
| refresh | Event triggered when paging | pagination |
| radio-change | Event triggered when user manually checks Radio of data row | row |
| select | Event triggered when user manually checks Checkbox of data row | selection, row |
| select-all | Event triggered when user manually checks select all Checkbox | selection |
| selection-change | Event triggered when selection changes | selection |
| cell-mouse-enter | Event triggered when cell hover enters | row, column, cell, event |
| cell-mouse-leave | Event triggered when cell hover leaves | row, column, cell, event |
| cell-click | Event triggered when a cell is clicked | row, column, cell, event |
| cell-dblclick | Event triggered when a cell is double clicked | row, column, cell, event |
| cell-contextmenu | Event triggered when a cell is right clicked | row, column, cell, event |
| row-click | Event triggered when a row is clicked | row, column, event |
| row-contextmenu | Event triggered when a row is right clicked | row, column, event |
| row-dblclick | Event triggered when a row is double clicked | row, column, event |
| header-click | Event triggered when a column header is clicked | column, event |
| header-contextmenu | Event triggered when a column header is right clicked | column, event |
| sort-change | Event triggered when table sort conditions change | { column, prop, order } |
| filter-change | Column key, if you need to use filter-change event, this attribute is needed to identify which column's filter condition | filters |
| current-change | Event triggered when table's current row changes, if you want to highlight current row, please enable table's highlight-current-row attribute | currentRow, oldCurrentRow |
| header-dragend | Event triggered when dragging header changes column width | newWidth, oldWidth, column, event |
| expand-change | Event triggered when user expands or collapses a row (when expanding rows, second parameter is expandedRows; when tree table, second parameter is expanded) | row, (expandedRows | expanded) |
Column Configuration
| Attribute | Description | Type | Default |
|---|---|---|---|
| prop | Field name | string | — |
| label | Column label | string | — |
| width | Column width | string / number | — |
| min-width | Column minimum width | string / number | — |
| fixed | Whether column is fixed | string / boolean | — |
| render-header | Custom render header function | Function | — |
| sortable | Whether column is sortable | boolean / string | false |
| sort-method | Custom sort method | Function | — |
| sort-by | Sort by which property | string / array / Function | — |
| sort-orders | Available sort orders | array | — |
| resizable | Whether column is resizable | boolean | true |
| formatter | Function for formatting cell content | Function | — |
| show-overflow-tooltip | Whether to show tooltip when content overflows | boolean / object | — |
| align | Column alignment | string | center |
| header-align | Header alignment | string | — |
| class-name | Column className | string | — |
| label-class-name | Column label className | string | — |
| selectable | Function for determining if row is selectable | Function | — |
| reserve-selection | Whether to reserve selection when data changes | boolean | false |
| filters | Array of filter options | array | — |
| filter-placement | Placement of filter popup | string | — |
| filter-multiple | Whether filter allows multiple selection | boolean | true |
| filter-method | Custom filter method | Function | — |
| filtered-value | Filter value for selected filters | array | — |
z-table Methods
| Method Name | Description | Parameters |
|---|---|---|
| clearSelection | Clear selection for multi-select table | — |
| getSelectionRows | Return currently selected rows | |
| toggleRowSelection | Toggle selection state of a row for multi-select table, can directly set selection state with second parameter | row, selected |
| toggleAllSelection | Toggle select all and deselect all for multi-select table | — |
| toggleRowExpansion | Toggle row expansion for expandable table or tree table. Use second parameter to directly set expansion state | row, expanded |
| setCurrentRow | Set a row as selected for single-select table, call without parameters to cancel current selection | row |
| clearSort | Clear sort conditions, data will restore to unsorted state | — |
| clearFilter | Pass array of columnKey to clear filter conditions for specified columns. Clear all filters if no parameters | columnKeys |
| doLayout | Re-layout Table. You may need to call this method when table visibility changes to get correct layout | — |
| sort | Sort table manually. prop parameter specifies sort column, order specifies sort order. | prop: string, order: string |
| scrollTo | Scroll to specific coordinates | (options: ScrollToOptions | number, yCoord?: number) |
| setScrollTop | Set vertical scroll position | top |
| setScrollLeft | Set horizontal scroll position | left |
z-table Slots
| Slot Name | Description | Subtags |
|---|---|---|
| append | Content inserted after the last row of table. If table has summary row, this slot will be above summary row. | — |
| empty | Custom content when data is empty | — |
| tableTop | Top slot | — |
| tableBottom | Bottom slot | — |
| toolBarTop | Toolbar top slot | — |
| toolBarBottom | Toolbar bottom slot | — |
| toolBarRight | Toolbar right slot | — |
| toolBarLeft | Toolbar left slot | — |
| tableTitle | Table title slot | — |
| paginationTop | Pagination top slot | — |
| paginationBottom | Pagination bottom slot | — |
| paginationLeft | Pagination left slot | — |
| paginationRight | Pagination right slot | — |
| footer | Virtual table footer slot, only available in virtual scroll mode | — |
pagination Attributes
| Attribute | Description | Type | Default |
|---|---|---|---|
| type | Pagination type | front / backbone | backbone |
| page | Current page | number | — |
| pageSize | Number of items per page | number | — |
| align | Pagination position | left / center / right | right |
| small | Whether to use small pagination style | boolean | true |
| background | Whether to add background color to pagination buttons | boolean | false |
| total | Total number of items | number | — |
| page-count | Total number of pages, set either total or page-count to display page numbers; use total if you need to support page-sizes changes | number | — |
| pager-count | Maximum number of page buttons. When total pages exceed this value, they will be collapsed | number | 7 |
| layout | Component layout, sub-component names separated by commas | string | prev, pager, next, jumper, ->, total |
| page-sizes | Options for page size selector | object | [10, 20, 30, 40, 50, 100] |
| popper-class | Class name for page size selector dropdown | string | '' |
| prev-text | Text for previous page button instead of icon | string | '' |
| prev-icon | Icon for previous page, higher priority than prev-text | string / Component | ArrowLeft |
| next-text | Text for next page button instead of icon | string | '' |
| next-icon | Icon for next page, lower priority than next-text | string / Component | ArrowRight |
| disabled | Whether pagination is disabled | boolean | false |
| teleported | Whether to teleport dropdown to body | boolean | true |
| hide-on-single-page | Whether to hide when there's only one page | boolean | false |
editable Attributes
| Attribute | Description | Type | Default |
|---|---|---|---|
| type | Editable table mode | single / multiple | single |
| maxLength | Maximum quantity | number | — |
| deleteConfirm | Delete confirmation | boolean | false |
| onEdit | Edit callback | ({ row, index, column, formRef }) => void | — |
| onCancel | Cancel callback | ({ row, index, column, formRef }) => void | — |
| onSave | Save callback | ({ row, index, column, formRef }) => void | — |
| onDelete | Delete callback | ({ row, index, column, formRef }) => void | — |
buttons Attributes in column
| Attribute | Description | Type | Default |
|---|---|---|---|
| type | Type | primary/ success'/ warning/ danger/ info / dropdown | — |
| label | Button text | string | — |
| children | Dropdown items when type is dropdown | array | — |
| hide | Button hide | boolean / () => boolean | — |
| onClick | Click event | ({ row, $index, column }) => void | — |
| plain | Whether button is plain | boolean | false |
| disabled | Whether button is disabled | boolean / ({ row, $index, column }) => boolean | false |
| size | Button size | default / large / small | — |
| text | Whether button is text button | boolean | false |
| bg | Whether to show background color for text button | boolean | false |
| link | Whether button is link button | boolean | false |
| round | Whether button is round | boolean | false |
| circle | Whether button is circle | boolean | false |
| loading | Whether button is in loading state | boolean | false |
| loading-icon | Custom loading icon component | string / Component | Loading |
| icon | Icon component | string / Component | — |
| autofocus | Native autofocus attribute | boolean | false |
| native-type | Native type attribute | button / submit / reset | button |
| auto-insert-space | Automatically insert space between two Chinese characters | boolean | — |
| color | Custom button color, automatically calculate hover and active colors | string | — |
| dark | Dark mode, automatically set color for dark mode | boolean | false |
| tag | Custom element tag | string / Component | button |
button type dropdown
| Attribute | Description | Type | Accepted Values | Default |
|---|---|---|---|---|
| reference | Reference text | string / (scope) => VNode | — | More |
| onCommand | Event callback triggered when menu item is clicked | (command) => void | — | — |
| type | Menu button type, same as Button component, only effective when split-button is true. | string | — | — |
| size | Menu size, also affects trigger button when split-button is true. | string | large / default / small | default |
| max-height | Maximum height of menu | string / number | — | — |
| split-button | Whether dropdown trigger element is presented as button group | boolean | — | false |
| disabled | Whether disabled | boolean | — | false |
| placement | Menu popup position | string | top/top-start/top-end/bottom/bottom-start/bottom-end | bottom |
| trigger | Behavior to trigger dropdown | string | hover / click /contextmenu | hover |
| hide-on-click | Whether to hide menu after clicking menu item | boolean | — | true |
| show-timeout | Delay before showing dropdown menu, only effective when trigger is hover | number | — | 250 |
| hide-timeout | Delay before hiding dropdown menu (only effective when trigger is hover) | number | — | 150 |
| role | ARIA attribute for dropdown menu. You might want to change this to "navigation" based on specific scenarios | string | — | 'menu' |
| tabindex | tabindex for Dropdown component | number | — | 0 |
| popper-class | Custom class name for popper | string | — | — |
| popper-options | popper.js parameters | Object | See popper.js documentation | {modifiers: [{name: 'computeStyles',options: {gpuAcceleration: false}}]} |
| teleported | Whether to insert dropdown list to body element | boolean | — | true |
dropdown children Attributes
| Attribute | Description | Type | Accepted Values | Default |
|---|---|---|---|---|
| disabled | Whether disabled | boolean / ({ row, $index, column }) => boolean | — | false |
| onClick | Dropdown item click | ({ row, $index, column }) => void | — | — |
| divided | Whether to show divider | boolean | — | false |
| icon | Custom icon | string / Component | — | — |
toolBar Attributes
| Attribute | Description | Type | Accepted Values | Default |
|---|---|---|---|---|
| exclude | Table item label collection not shown in toolbar | array | — | — |
| unCheck | Default unchecked label collection | array | — | — |
| refresh | Whether refresh feature is displayed | boolean | — | true |
| density | Whether density feature is displayed | boolean | — | true |
| fullScreen | Whether fullscreen feature is displayed | boolean | — | true |
| setting | Whether column setting feature is displayed | boolean | — | true |