Skip to content

Crud Table ​

z-crud component table functionality introduction. Table functionality usage is basically equivalent to z-table.

Table Usage ​

Encapsulated on z-table, table attributes can be passed directly.

<!-- 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 columns = ref([
  {
    type: 'selection',
    reserveSelection: true,
  },
  {
    label: 'Name',
    prop: 'name',
  },
  {
    prop: 'gender',
    label: 'Gender',
  },
  {
    prop: 'age',
    label: 'Age',
  },
  {
    prop: 'time',
    label: 'Date',
  },
])
const request = ref({
  searchApi: getTableData,
})
const tableData = ref([])
const pagination = ref({
  page: 1,
  pageSize: 2,
  total: 0,
})
const loading = ref(false)
const selectionData = ref<RowData[]>([])

function getTableData(params: any) {
  console.log(params, 'getTableData params')
  return new Promise((resolve) => {
    setTimeout(() => {
      const data = [
        {
          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',
        },
      ]

      resolve({
        data: {
          page: 1,
          pageSize: 2,
          total: 4,
          list: data.slice((pagination.value.page - 1) * pagination.value.pageSize, pagination.value.page * pagination.value.pageSize),
        },
      })
    }, 100)
  })
}
</script>

<template>
  <z-crud
    v-model:data="tableData"
    v-model:pagination="pagination"
    v-model:loading="loading"
    v-model:selectionData="selectionData"
    :columns="columns"
    :request="request"
    :action="false"
    row-key="id"
    stripe
  />
</template>

Table Title ​

Configure title attribute to generate table title, supports string and function types, can also use tableTitle slot for customization.

<script lang="ts" setup>
import { ref } from 'vue'

const columns = ref([
  {
    label: 'Name',
    prop: 'name',
  },
  {
    prop: 'gender',
    label: 'Gender',
  },
  {
    prop: 'age',
    label: 'Age',
  },
  {
    prop: 'time',
    label: 'Date',
  },
])
const request = ref({
  searchApi: getTableData,
})
const tableData = ref([])
const pagination = ref({
  page: 1,
  pageSize: 2,
  total: 0,
})
const loading = ref(false)

function getTableData() {
  return new Promise((resolve) => {
    setTimeout(() => {
      const data = [
        {
          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',
        },
      ]

      resolve({
        data: {
          page: 1,
          pageSize: 2,
          total: 4,
          list: data.slice((pagination.value.page - 1) * pagination.value.pageSize, pagination.value.page * pagination.value.pageSize),
        },
      })
    }, 100)
  })
}
</script>

<template>
  <z-crud
    v-model:data="tableData"
    v-model:pagination="pagination"
    v-model:loading="loading"
    :columns="columns"
    :request="request"
    :action="false"
    title="Table Title"
  />
</template>

Operation Items ​

Operation items are appended to the end of columns by default, with table header as Operation, having three operations: View, Edit, Delete.

For specific configuration of operations, please refer to Create/Edit Configuration, View Configuration, Delete Configuration documentation.

Supports dynamic control of specific operation visibility.

<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
import type { TableFormConfig } from 'ideaz-element'

interface RowData {
  id: number
  name: string
  gender: string
  age: number
  time: string
}

interface GetTableDataRes { data: { page: number, pageSize: number, list: RowData[], total: number } }

const columns = ref([
  {
    label: 'Name',
    prop: 'name',
  },
  {
    prop: 'gender',
    label: 'Gender',
  },
  {
    prop: 'age',
    label: 'Age',
  },
  {
    prop: 'time',
    label: 'Date',
  },
])
const request = ref({
  searchApi: getTableData,
})
const tableData = ref<RowData[]>([])
const pagination = ref({
  page: 1,
  pageSize: 2,
  total: 0,
})
const loading = ref(false)
const detailConfig = ref<TableFormConfig | boolean>(true)
const deleteConfig = ref<TableFormConfig | boolean>(true)
const editConfig = ref<TableFormConfig | boolean>(true)

function getTableData(params: any): Promise<GetTableDataRes> {
  console.log(params, 'getTableData params')
  return new Promise((resolve) => {
    setTimeout(() => {
      const data = [
        {
          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',
        },
      ]

      resolve({
        data: {
          page: 1,
          pageSize: 2,
          total: 4,
          list: data.slice((pagination.value.page - 1) * pagination.value.pageSize, pagination.value.page * pagination.value.pageSize),
        },
      })
    }, 100)
  })
}

function handleChangeViewVisible() {
  detailConfig.value = !detailConfig.value
}

function handleChangeDeleteVisible() {
  deleteConfig.value = !deleteConfig.value
}

function handleChangeEditVisible() {
  editConfig.value = !editConfig.value
}
</script>

<template>
  <z-crud
    v-model:data="tableData"
    v-model:pagination="pagination"
    v-model:loading="loading"
    :columns="columns"
    :request="request"
    :detail="detailConfig"
    :edit="editConfig"
    :delete="deleteConfig"
  >
    <template #toolBarLeft>
      <el-button type="primary" size="small" @click="handleChangeViewVisible">
        Toggle view button
      </el-button>
      <el-button type="primary" size="small" @click="handleChangeDeleteVisible">
        Toggle delete button
      </el-button>
      <el-button type="primary" size="small" @click="handleChangeEditVisible">
        Toggle edit button
      </el-button>
    </template>
  </z-crud>
</template>

Custom Operation Items ​

Configure action to false to disable default operation items and customize table operations.

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 {
  id: number
  name: string
  gender: string
  age: number
  time: string
}

const columns = ref([
  {
    label: 'Name',
    prop: 'name',
  },
  {
    prop: 'gender',
    label: 'Gender',
  },
  {
    prop: 'age',
    label: 'Age',
  },
  {
    prop: 'time',
    label: 'Date',
  },
  {
    type: 'button',
    label: 'Actions',
    buttons: [
      {
        label: 'View',
        link: true,
        type: 'primary',
        disabled: ({ row, column, $index }: TableColumnScopeData<RowData>) => row.name === 'Steven',
        onClick: ({ row }: TableColumnScopeData<RowData>) => console.log(row, 'row'),
      },
      {
        label: 'Delete',
        link: true,
        type: 'danger',
        disabled: ({ row, column, $index }: TableColumnScopeData<RowData>) => row.age === 18,
        onClick: ({ row }: TableColumnScopeData<RowData>) => console.log(row, 'row'),
      },
    ],
  },
])
const request = ref({
  searchApi: getTableData,
})
const tableData = ref([])
const pagination = ref({
  page: 1,
  pageSize: 2,
  total: 0,
})
const loading = ref(false)

function getTableData(params: any) {
  console.log(params, 'getTableData params')
  return new Promise((resolve) => {
    setTimeout(() => {
      const data = [
        {
          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',
        },
      ]

      resolve({
        data: {
          page: 1,
          pageSize: 2,
          total: 4,
          list: data.slice((pagination.value.page - 1) * pagination.value.pageSize, pagination.value.page * pagination.value.pageSize),
        },
      })
    }, 100)
  })
}
</script>

<template>
  <z-crud
    v-model:data="tableData"
    v-model:pagination="pagination"
    v-model:loading="loading"
    :columns="columns"
    :request="request"
    :action="false"
  />
</template>

Operation Dropdown ​

For other specific configurations, refer to z-table component

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 {
  id: number
  name: string
  gender: string
  age: number
  time: string
}

const columns = ref([
  {
    label: 'Name',
    prop: '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: 'More',
        children: [
          {
            type: 'primary',
            link: true,
            label: 'Copy',
            onClick: ({ row }: TableColumnScopeData<RowData>) => {
              console.log(row, 'copy')
            },
          },
          {
            type: 'danger',
            link: true,
            label: 'Operate',
            onClick: ({ row }: TableColumnScopeData<RowData>) => {
              console.log(row, 'operate')
            },
          },
        ],
      },
    ],
  },
])
const request = ref({
  searchApi: getTableData,
})
const tableData = ref([])
const pagination = ref({
  page: 1,
  pageSize: 2,
  total: 0,
})
const loading = ref(false)

function getTableData(params: any) {
  console.log(params, 'getTableData params')
  return new Promise((resolve) => {
    setTimeout(() => {
      const data = [
        {
          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',
        },
      ]

      resolve({
        data: {
          page: 1,
          pageSize: 2,
          total: 4,
          list: data.slice((pagination.value.page - 1) * pagination.value.pageSize, pagination.value.page * pagination.value.pageSize),
        },
      })
    }, 100)
  })
}
</script>

<template>
  <z-crud
    v-model:data="tableData"
    v-model:pagination="pagination"
    v-model:loading="loading"
    :columns="columns"
    :request="request"
    :action="false"
  />
</template>

Pagination ​

Configure pagination, supports two-way binding to implement pagination effect.

When pageSize is 0, pagination is false or pagination is not passed, pagination will not be displayed.

<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'

interface RowData {
  name: string
  gender: string
  age: number
  time: string
}

interface GetTableDataRes { result: { page: number, pageSize: number, list: RowData[], total: number } }

const loading = ref(false)
const tableData = ref<RowData[]>([])
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(params: any): Promise<GetTableDataRes> {
  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-crud
    v-model:pagination="pagination"
    v-model:data="tableData"
    v-model:loading="loading"
    :columns="columns"
    :action="false"
    @refresh="getTableData"
  />
</template>

Frontend Pagination ​

Configure pagination type as front to enable frontend pagination functionality.

[]
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'

interface RowData {
  name: string
  gender: string
  age: number
  time: string
}

interface GetTableDataRes { result: { page: number, pageSize: number, list: RowData[], total: number } }

const loading = ref(false)
const tableData = ref<RowData[]>([])
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: any): Promise<GetTableDataRes> {
  console.log(params, '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-crud
    v-model:pagination="pagination"
    v-model:data="tableData"
    v-model:loading="loading"
    :total-data="totalData"
    :columns="columns"
    :action="false"
    @refresh="getTableData"
  />
</template>

Hide Columns ​

Configure hide field in column, supports function or boolean value.

<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-crud
    v-model:data="tableData"
    :columns="columns"
    :action="false"
  />
</template>

Custom Column ​

Configure slot or render in column items to customize column content.

<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { h, ref } from 'vue'
import type { TableColumnScopeData } from 'ideaz-element'

interface RowData {
  id: number
  name: string
  gender: string
  age: number
  time: string
}

const columns = ref([
  {
    label: 'Name',
    slot: 'name',
    form: {
      component: 'input',
      label: 'Name',
      field: 'name',
    },
  },
  {
    slot: 'gender',
    label: 'Gender',
    form: {
      component: 'select',
      label: 'Gender',
      field: 'gender',
    },
  },
  {
    render: ({ row }: TableColumnScopeData<RowData>) => h('span', row.age),
    label: 'Age',
    form: {
      component: 'input',
      label: 'Age',
      field: 'age',
    },
  },
  {
    prop: 'time',
    label: 'Date',
  },
])
const request = ref({
  searchApi: getTableData,
  deleteApi: commonApi,
  submitApi: commonApi,
})
const tableData = ref([])
const pagination = ref({
  page: 1,
  pageSize: 2,
  total: 0,
})
const loading = ref(false)
const formData = ref({})

const options = {
  gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}

function getTableData(params: any) {
  console.log(params, 'getTableData params')
  return new Promise((resolve) => {
    setTimeout(() => {
      const data = [
        {
          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',
        },
      ]

      resolve({
        data: {
          page: 1,
          pageSize: 2,
          total: 4,
          list: data.slice((pagination.value.page - 1) * pagination.value.pageSize, pagination.value.page * pagination.value.pageSize),
        },
      })
    }, 100)
  })
}

function commonApi(params: any) {
  console.log(params, 'commonApi params')
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve({
        msg: 'success',
        code: 200,
      })
    }, 100)
  })
}
</script>

<template>
  <z-crud
    v-model:formData="formData"
    v-model:data="tableData"
    v-model:pagination="pagination"
    v-model:loading="loading"
    :options="options"
    :columns="columns"
    :request="request"
  >
    <template #name>
      sdf
    </template>
    <template #gender>
      asdf
    </template>
  </z-crud>
</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', 'Name tooltip'),
  },
  {
    prop: 'gender',
    label: 'Gender',
    tooltip: 'Gender tooltip',
  },
  {
    prop: 'age',
    label: 'Age',
  },
  {
    prop: 'time',
    label: 'Date',
  },
])
</script>

<template>
  <z-crud
    v-model:data="tableData"
    :columns="columns"
    :action="false"
  />
</template>

Column Types ​

Configure type in column to implement table column types, supports expand, radio, selection, input, select.

TIP

When type is sort, type is radio or cross-page selection checkbox is needed, it needs to be used with rowKey (default id).

<script lang="ts" setup>
import { ref } from 'vue'

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([
  {
    type: 'sort',
  },
  {
    type: 'expand',
  },
  {
    type: 'index',
  },
  {
    type: 'radio',
  },
  {
    type: 'selection',
    reserveSelection: true,
  },
  {
    component: 'input',
    prop: 'name',
    label: 'Name',
  },
  {
    component: 'select',
    prop: 'gender',
    label: 'Gender',
  },
  {
    prop: 'age',
    label: 'Age',
  },
  {
    prop: 'time',
    label: 'Date',
  },
])

const options = {
  gender: [
    { label: 'Male', value: '1' },
    { label: 'Female', value: '2' },
  ],
}
</script>

<template>
  <z-crud
    v-model:data="tableData"
    :columns="columns"
    :options="options"
    :action="false"
    row-key="id"
  >
    <template #expand>
      <span>Expanded content</span>
    </template>
  </z-crud>
</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-crud
    v-model:data="tableData"
    :columns="columns"
    :action="false"
  >
    <template #genderHeaderSlot="scope">
      <span>Custom gender header {{ scope.$index }}</span>
    </template>
  </z-crud>
</template>

Editable Table ​

For detailed documentation, please refer to z-table editable table content.

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-crud
    v-model:data="tableData"
    :columns="columns"
    :options="options"
    :editable="true"
    :action="false"
  />
</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 { ref } from 'vue'

interface RowData {
  id: number
  name: string
  gender: string
  age: number
  time: string
}

const searchFormData = ref({
  name: '',
})

const columns = ref([
  {
    type: 'selection',
    reserveSelection: true,
  },
  {
    label: 'Name',
    prop: 'name',
    search: {
      component: 'el-input',
    },
  },
  {
    prop: 'gender',
    label: 'Gender',
  },
  {
    prop: 'age',
    label: 'Age',
  },
  {
    prop: 'time',
    label: 'Date',
  },
])
const request = ref({
  searchApi: getTableData,
})
const tableData = ref([])
const pagination = ref({
  page: 1,
  pageSize: 2,
  total: 0,
})
const loading = ref(false)
const selectionData = ref<RowData[]>([])

function getTableData(params: any) {
  console.log(params, 'getTableData params')
  return new Promise((resolve) => {
    setTimeout(() => {
      const data = [
        {
          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',
        },
      ]

      resolve({
        data: {
          page: 1,
          pageSize: 2,
          total: 4,
          list: data.slice((pagination.value.page - 1) * pagination.value.pageSize, pagination.value.page * pagination.value.pageSize),
        },
      })
    }, 100)
  })
}
</script>

<template>
  <z-crud
    v-model:data="tableData"
    v-model:pagination="pagination"
    v-model:loading="loading"
    v-model:selectionData="selectionData"
    v-model:formData="searchFormData"
    :columns="columns"
    :request="request"
    :action="false"
    :sticky="{ parent: 'document' }"
    row-key="id"
    stripe
  />
</template>

Watermark ​

Configure watermark, supports string and object types. For object type configurable attributes, 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 formData = ref({})

const columns = ref([
  {
    prop: 'name',
    label: 'Name',
    form: {
      component: 'input',
      field: 'name',
    },
  },
  {
    prop: 'gender',
    label: 'Gender',
  },
  {
    prop: 'age',
    label: 'Age',
  },
  {
    prop: 'time',
    label: 'Date',
  },
])

const options = {
  gender: [
    { label: 'Male', value: '1' },
    { label: 'Female', value: '2' },
  ],
}
</script>

<template>
  <z-crud
    v-model:data="tableData"
    v-model:formData="formData"
    :columns="columns"
    :options="options"
    :action="false"
    watermark="watermark"
  />
</template>

Table Methods ​

z-crud 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([
  {
    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(selection: RowData[]) {
  selectionData.value = selection
  console.log(selection, 'selection data')
}

function handleClear() {
  zTableRef.value.clearSelection()
}
</script>

<template>
  <el-button @click="handleClear">
    Clear selection
  </el-button>
  <z-crud
    ref="zTableRef"
    :data="tableData"
    :columns="columns"
    :action="false"
    @radio-change="handleRadioChange"
    @selection-change="handleSelectionChange"
  />
</template>

z-crud Table Attributes ​

AttributeDescriptionTypeAccepted ValuesDefault
modelValue:dataDisplay data, supports two-way bindingarray——
modelValue:formDataQuery form data, supports two-way bindingarray——
modelValue:paginationPagination configuration, supports two-way bindingobject——
modelValue:loadingTable loading, supports two-way bindingboolean——
modelValue:selectionCheckbox selected data, supports two-way bindingarray——
columnsTable configuration itemsarray——
toolBarToolbar configurationobject / boolean——
editableEditable table configurationobject / boolean——
optionsTable internal option data sourceobject——
titleTable titlestring / function——
totalDataAll table data (effective for frontend pagination)array——
nameTable key, configuring name enables caching by defaultstring——
paginationStoragePagination data cachingboolean—false
formStorageQuery form data cachingboolean—false
formDecoratorForm backgroundobject—{ name: 'el-card' }
tableDecoratorTable backgroundobject—{ name: 'el-card' }
watermarkWatermark configurationobject (see el-watermark documentation for details)——
heightTable 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-heightTable max height. Valid values are numbers or heights in px units.string / number——
stripeWhether table is stripedboolean—false
borderWhether table has vertical bordersboolean—false
sizeTable sizestringlarge / default /small—
fitWhether column width fits contentboolean—true
show-headerWhether to show table headerboolean—true
highlight-current-rowWhether to highlight current rowboolean—false
current-row-keyKey of current row, write-only propertystring / number——
row-class-nameFunction for row className, can also use string to set fixed className for all rows.function({ row, rowIndex }) / string——
row-styleFunction for row style, can also use fixed Object to set same Style for all rows.function({ row, rowIndex }) / object——
cell-class-nameFunction for cell className, can also use string to set fixed className for all cells.function({ row, column, rowIndex, columnIndex }) / string——
cell-styleFunction for cell style, can also use fixed Object to set same Style for all cells.function({ row, column, rowIndex, columnIndex }) / object——
header-row-class-nameFunction for header row className, can also use string to set fixed className for all header rows.function({ row, rowIndex }) / string——
header-row-styleFunction for header row style, can also use fixed Object to set same Style for all header rows.function({ row, rowIndex }) / object——
header-cell-class-nameFunction for header cell className, can also use string to set fixed className for all header cells.function({ row, column, rowIndex, columnIndex }) / string——
header-cell-styleFunction for header cell style, can also use fixed Object to set same Style for all header cells.function({ row, column, rowIndex, columnIndex }) / object——
row-keyKey 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-textText displayed when data is empty, can also be set through #empty slotstring—No Data
default-expand-allWhether to expand all rows by default, effective when Table contains expandable rows or is tree tableboolean—false
expand-row-keysSet 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-sortDefault sort column prop and order. Its prop property specifies default sort column, order specifies default sort orderobject(order: 'ascending' 'descending')'descending')
tooltip-effecteffect of overflow tooltipstringdark / lightdark
tooltip-optionsOptions for overflow tooltip, see tooltip component belowobjectsee tooltipobject
show-summaryWhether to show summary row at table footerboolean—false
sum-textText for first column of summary rowstring—Sum
summary-methodCustom summary calculation methodfunction({ columns, data })——
span-methodMethod for merging rows or columnsfunction({ row, column, rowIndex, columnIndex })——
select-on-indeterminateBehavior when clicking header checkbox when only some rows are selected in multi-select table. If true, select all rows; if false, deselect all rowsboolean—true
indentIndentation of tree nodes when displaying tree datanumber—16
lazyWhether to lazy load child node databoolean——
loadFunction for loading child node data, effective when lazy is truefunction(row, treeNode, resolve)——
tree-propsConfiguration options for rendering nested dataobject—{ hasChildren: 'hasChildren', children: 'children' }
table-layoutLayout method for table cells, rows and columnsstringfixed / autofixed
scrollbar-always-onAlways show scrollbarboolean—false
show-overflow-tooltipWhether to hide extra content and show them in Tooltip when cell content overflows. This will affect all columns.boolean / object—See tooltip-options
flexibleEnsure minimum size of main axis to not exceed contentboolean—false

z-crud Table Events ​

Event NameDescriptionCallback Parameters
refreshEvent triggered when pagingpagination
radio-changeEvent triggered when user manually checks Radio of data rowrow
selectEvent triggered when user manually checks Checkbox of data rowselection, row
select-allEvent triggered when user manually checks select all Checkboxselection
selection-changeEvent triggered when selection changesselection
cell-mouse-enterEvent triggered when cell hover entersrow, column, cell, event
cell-mouse-leaveEvent triggered when cell hover leavesrow, column, cell, event
cell-clickEvent triggered when a cell is clickedrow, column, cell, event
cell-dblclickEvent triggered when a cell is double clickedrow, column, cell, event
cell-contextmenuEvent triggered when a cell is right clickedrow, column, cell, event
row-clickEvent triggered when a row is clickedrow, column, event
row-contextmenuEvent triggered when a row is right clickedrow, column, event
row-dblclickEvent triggered when a row is double clickedrow, column, event
header-clickEvent triggered when a column header is clickedcolumn, event
header-contextmenuEvent triggered when a column header is right clickedcolumn, event
sort-changeEvent triggered when table sort conditions change{ column, prop, order }
filter-changeColumn key, if you need to use filter-change event, this attribute is needed to identify which column's filter conditionfilters
current-changeEvent triggered when table's current row changes, if you want to highlight current row, please enable table's highlight-current-row attributecurrentRow, oldCurrentRow
header-dragendEvent triggered when dragging header changes column widthnewWidth, oldWidth, column, event
expand-changeEvent 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)

z-crud Table Methods ​

Method NameDescriptionParameters
getTableDataGet table data method—
clearSelectionClear selection for multi-select table or single-select table—
getSelectionRowsReturn currently selected rows
toggleRowSelectionToggle selection state of a row for multi-select table, can directly set selection state with second parameterrow, selected
toggleAllSelectionToggle select all and deselect all for multi-select table—
toggleRowExpansionToggle row expansion for expandable table or tree table. Use second parameter to directly set expansion staterow, expanded
setCurrentRowSet a row as selected for single-select table, call without parameters to cancel current selectionrow
clearSortClear sort conditions, data will restore to unsorted state—
clearFilterPass array of columnKey to clear filter conditions for specified columns. Clear all filters if no parameterscolumnKeys
doLayoutRe-layout Table. You may need to call this method when table visibility changes to get correct layout—
sortSort table manually. prop parameter specifies sort column, order specifies sort order.prop: string, order: string
scrollToScroll to specific coordinates(options: ScrollToOptions | number, yCoord?: number)
setScrollTopSet vertical scroll positiontop
setScrollLeftSet horizontal scroll positionleft

z-crud Slots ​

Slot NameDescriptionSubtags
appendContent inserted after the last row of table. If table has summary row, this slot will be above summary row.—
emptyCustom content when data is empty—
tableTopTop slot—
tableBottomBottom slot—
toolBarTopToolbar top slot—
toolBarBottomToolbar bottom slot—
toolBarRightToolbar right slot—
toolBarLeftToolbar left slot—
tableTitleTable title slot—
paginationTopPagination top slot—
paginationBottomPagination bottom slot—
paginationLeftPagination left slot—
paginationRightPagination right slot—
formTopForm top slot—
formBottomForm bottom slot—
crudMiddleMiddle content slot—

columns Attributes ​

AttributeDescriptionTypeAccepted ValuesDefault
typeColumn type.stringselection / index / expand/ radio / button—
componentColumn component type.stringinput / select / checkbox / radio / any locally or globally registered component—
indexIf type=index is set, you can customize the index by passing the index attributenumber / function(index)——
labelDisplay title (recommended to configure)string / (scope) => VNode——
formForm configurationobject——
addAdd form configurationobject / boolean——
editEdit form configurationobject / boolean——
searchSearch form configurationobject / boolean——
detailDetail form configurationobject / boolean——
buttonsButton configurationarray——
optionsOption component data sourcearray——
tooltipColumn tooltipstring / () => VNode——
column-keyColumn key, if you need to use filter-change event, this attribute is needed to identify which column's filter conditionstring——
propField name corresponding to column content, can also use property attributestring——
widthColumn widthstring / number——
min-widthColumn minimum width, difference with width is that width is fixed, min-width will distribute remaining width proportionally to columns with min-width setstring / number——
fixedWhether column is fixed on left or right side. true means fixed on left sidestring / booleantrue / 'left' / 'right'—
render-headerFunction for rendering column title Label areafunction({ column, $index })——
sortableWhether column is sortable, if set to 'custom', it means user wants remote sorting, need to listen to Table's sort-change eventboolean / stringcustomfalse
sort-methodSpecify which property to sort by, only effective when sortable is set to true. Should return a Number like Array.sortfunction(a, b)——
sort-bySpecify which property to sort by, only effective when sortable is true and sort-method is not set. If sort-by is array, sort by 1st property first, if equal, sort by 2nd, and so onfunction(row, index) / string / array——
sort-ordersRotation order of sorting strategies used when sorting data, only effective when sortable is true. Need to pass an array, as user clicks table header, column will sort according to array elements in orderarrayArray elements need to be one of: ascending for ascending, descending for descending, null for original order['ascending', 'descending', null]
resizableWhether column width can be changed by dragging (need to set border attribute to true on el-table)boolean—true
formatterFunction for formatting contentfunction(row, column, cellValue, index)——
show-overflow-tooltipWhether to show tooltip when content is too long and hiddenboolean / object—See table's tooltip-options
alignAlignmentstringleft / center / rightleft
header-alignHeader alignment, if not set, use table's alignmentstringleft / center / right—
class-nameColumn classNamestring——
label-class-nameCustom class name for current column titlestring——
selectableOnly effective for type=selection columns, type is Function, Function return value determines whether this row's CheckBox can be checkedfunction(row, index)——
reserve-selectionWhether to reserve selection after data refresh, only effective for type=selection columns, note that you need to specify row-key for this feature to work.boolean—false
filtersData filter options, array format, each element in array needs text and value properties. Each element in array needs text and value properties.Array<{text: string, value: string}>——
filter-placementFilter popup positioningstringSame as Tooltip's placement attribute—
filter-multipleWhether data filter options allow multiple selectionboolean—true
filter-methodMethod for data filtering, if it's multi-select filter, it will execute multiple times for each data, will show if any execution returns true.function(value, row, column)——
filtered-valueSelected data filter items, may be needed if you need to customize table header filter rendering.array——
Event NameDescriptionCallback Parameters
refreshEvent triggered when pagingpagination
radio-changeEvent triggered when user manually checks Radio of data rowrow
selectEvent triggered when user manually checks Checkbox of data rowselection, row
select-allEvent triggered when user manually checks select all Checkboxselection
selection-changeEvent triggered when selection changesselection
cell-mouse-enterEvent triggered when cell hover entersrow, column, cell, event
cell-mouse-leaveEvent triggered when cell hover leavesrow, column, cell, event
cell-clickEvent triggered when a cell is clickedrow, column, cell, event
cell-dblclickEvent triggered when a cell is double clickedrow, column, cell, event
cell-contextmenuEvent triggered when a cell is right clickedrow, column, cell, event
row-clickEvent triggered when a row is clickedrow, column, event
row-contextmenuEvent triggered when a row is right clickedrow, column, event
row-dblclickEvent triggered when a row is double clickedrow, column, event
header-clickEvent triggered when a column header is clickedcolumn, event
header-contextmenuEvent triggered when a column header is right clickedcolumn, event
sort-changeEvent triggered when table sort conditions change{ column, prop, order }
filter-changeColumn key, if you need to use filter-change event, this attribute is needed to identify which column's filter conditionfilters
current-changeEvent triggered when table's current row changes, if you want to highlight current row, please enable table's highlight-current-row attributecurrentRow, oldCurrentRow
header-dragendEvent triggered when dragging header changes column widthnewWidth, oldWidth, column, event
expand-changeEvent 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)

z-crud Table Methods ​

Method NameDescriptionParameters
getTableDataGet table data method—
clearSelectionClear selection for multi-select table or single-select table—
getSelectionRowsReturn currently selected rows
toggleRowSelectionToggle selection state of a row for multi-select table, can directly set selection state with second parameterrow, selected
toggleAllSelectionToggle select all and deselect all for multi-select table—
toggleRowExpansionToggle row expansion for expandable table or tree table. Use second parameter to directly set expansion staterow, expanded
setCurrentRowSet a row as selected for single-select table, call without parameters to cancel current selectionrow
clearSortClear sort conditions, data will restore to unsorted state—
clearFilterPass array of columnKey to clear filter conditions for specified columns. Clear all filters if no parameterscolumnKeys
doLayoutRe-layout Table. You may need to call this method when table visibility changes to get correct layout—
sortSort table manually. prop parameter specifies sort column, order specifies sort order.prop: string, order: string
scrollToScroll to specific coordinates(options: ScrollToOptions | number, yCoord?: number)
setScrollTopSet vertical scroll positiontop
setScrollLeftSet horizontal scroll positionleft

z-crud Slots ​

Slot NameDescriptionSubtags
appendContent inserted after the last row of table. If table has summary row, this slot will be above summary row.—
emptyCustom content when data is empty—
tableTopTop slot—
tableBottomBottom slot—
toolBarTopToolbar top slot—
toolBarBottomToolbar bottom slot—
toolBarRightToolbar right slot—
toolBarLeftToolbar left slot—
tableTitleTable title slot—
paginationTopPagination top slot—
paginationBottomPagination bottom slot—
paginationLeftPagination left slot—
paginationRightPagination right slot—
formTopForm top slot—
formBottomForm bottom slot—
crudMiddleMiddle content slot—

button type dropdown Attributes ​

AttributeDescriptionTypeAccepted ValuesDefault
referenceReference textstring / (scope) => VNode—More
onCommandEvent callback triggered when menu item is clicked(command) => void——
typeMenu button type, same as Button component, only effective when split-button is true.string——
sizeMenu size, also affects trigger button when split-button is true.stringlarge / default / smalldefault
max-heightMaximum height of menustring / number——
split-buttonWhether dropdown trigger element is presented as button groupboolean—false
disabledWhether disabledboolean—false
placementMenu popup positionstringtop/top-start/top-end/bottom/bottom-start/bottom-endbottom
triggerBehavior to trigger dropdownstringhover / click /contextmenuhover
hide-on-clickWhether to hide menu after clicking menu itemboolean—true
show-timeoutDelay before showing dropdown menu, only effective when trigger is hovernumber—250
hide-timeoutDelay before hiding dropdown menu (only effective when trigger is hover)number—150
roleARIA attribute for dropdown menu. You might want to change this to "navigation" based on specific scenariosstring—'menu'
tabindextabindex for Dropdown componentnumber—0
popper-classCustom class name for popperstring——
popper-optionspopper.js parametersObjectSee popper.js documentation{modifiers: [{name: 'computeStyles',options: {gpuAcceleration: false}}]}
teleportedWhether to insert dropdown list to body elementboolean—true
AttributeDescriptionTypeAccepted ValuesDefault
disabledWhether disabledboolean / ({ row, $index, column }) => boolean—false
onClickDropdown item click({ row, $index, column }) => void——
dividedWhether to show dividerboolean—false
iconCustom iconstring / Component——

toolBar Attributes ​

AttributeDescriptionTypeAccepted ValuesDefault
excludeTable item label collection not shown in toolbararray——
unCheckDefault unchecked label collectionarray——
refreshWhether refresh feature is displayedboolean—true
densityWhether density feature is displayedboolean—true
fullScreenWhether fullscreen feature is displayedboolean—true
settingWhether column setting feature is displayedboolean—true

Released under the MIT License.