Crud
Introduction to the view feature of the z-crud component
Basic Usage
Configure the detail field of column to configure the detail view.
<script lang="ts" setup>
import { ref } from 'vue'
const loading = ref(false)
const formData = ref({
name: '',
gender: '',
age: '',
})
const tableData = ref([])
const columns = ref([
{
prop: 'name',
label: 'Name',
search: {
component: 'input',
label: 'Name',
field: 'name',
},
detail: {
field: 'name',
label: 'Name',
},
},
{
prop: 'gender',
label: 'Gender',
search: {
component: 'select',
label: 'Gender',
field: 'gender',
},
detail: {
field: 'gender',
label: 'Gender',
},
},
{
prop: 'age',
label: 'Age',
detail: {
field: 'time',
label: 'Date',
},
search: {
component: 'input',
label: 'Age',
field: 'age',
},
},
{
prop: 'date',
label: 'Date',
},
])
const options = {
gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}
const pagination = ref({
page: 1,
pageSize: 2,
total: 4,
})
const request = ref({
searchApi: mockApi,
})
function mockApi() {
return new Promise((resolve) => {
setTimeout(() => {
const data = [
{
id: 1,
name: 'Steven',
gender: 'male',
age: 22,
date: '2020-01-01',
time: ['2020-01-01', '2020-01-02'],
},
{
id: 2,
name: 'Helen',
gender: 'male',
age: 12,
date: '2012-01-01',
time: ['2020-01-01', '2020-01-02'],
},
{
id: 3,
name: 'Nancy',
gender: 'female',
age: 18,
date: '2018-01-01',
time: ['2020-01-01', '2020-01-02'],
},
{
id: 4,
name: 'Jack',
gender: 'male',
age: 28,
date: '2028-01-01',
time: ['2020-01-01', '2020-01-02'],
},
]
resolve({
data: {
page: 1,
pageSize: 10,
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:pagination="pagination"
v-model:data="tableData"
v-model:formData="formData"
v-model:loading="loading"
:options="options"
:columns="columns"
:add="false"
:edit="false"
:delete="false"
:request="request"
/>
</template>Configure the columns of detail to configure the detail view.
<script lang="ts" setup>
import { ref } from 'vue'
const loading = ref(false)
const formData = ref({
name: '',
gender: '',
age: '',
})
const tableData = ref([])
const columns = ref([
{
prop: 'name',
label: 'Name',
},
{
prop: 'gender',
label: 'Gender',
},
{
prop: 'age',
label: 'Age',
},
{
prop: 'time',
label: 'Date',
},
])
const detailConfig = ref({
columns: [{
prop: 'name',
label: 'Name',
}, {
prop: 'gender',
label: 'Gender',
}, {
prop: 'date',
label: 'Date',
}],
})
const searchFormConfig = ref({
labelWith: '80px',
columns: [
{
component: 'input',
label: 'Name',
field: 'name',
},
{
component: 'select',
label: 'Gender',
field: 'gender',
},
{
component: 'input',
label: 'Age',
field: 'age',
},
],
})
const options = {
gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}
const pagination = ref({
page: 1,
pageSize: 2,
total: 4,
})
const request = ref({
searchApi: mockApi,
})
function mockApi() {
return new Promise((resolve) => {
setTimeout(() => {
const data = [
{
id: 1,
name: 'Steven',
gender: 'male',
age: 22,
date: '2020-01-01',
time: ['2020-01-01', '2020-01-02'],
},
{
id: 2,
name: 'Helen',
gender: 'male',
age: 12,
date: '2012-01-01',
time: ['2020-01-01', '2020-01-02'],
},
{
id: 3,
name: 'Nancy',
gender: 'female',
age: 18,
date: '2018-01-01',
time: ['2020-01-01', '2020-01-02'],
},
{
id: 4,
name: 'Jack',
gender: 'male',
age: 28,
date: '2028-01-01',
time: ['2020-01-01', '2020-01-02'],
},
]
resolve({
data: {
page: 1,
pageSize: 10,
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:pagination="pagination"
v-model:data="tableData"
v-model:formData="formData"
v-model:loading="loading"
:options="options"
:columns="columns"
:detail="detailConfig"
:search="searchFormConfig"
:add="false"
:edit="false"
:delete="false"
:request="request"
/>
</template>Configure the columns field of form to configure the detail view.
<script lang="ts" setup>
import { ref } from 'vue'
const loading = ref(false)
const formData = ref({
name: '',
gender: '',
age: '',
})
const tableData = ref([])
const columns = ref([
{
prop: 'name',
label: 'Name',
},
{
prop: 'gender',
label: 'Gender',
},
{
prop: 'age',
label: 'Age',
},
{
prop: 'date',
label: 'Date',
},
])
const searchFormConfig = ref({
labelWith: '80px',
columns: [
{
component: 'input',
label: 'Name',
field: 'name',
},
{
component: 'select',
label: 'Gender',
field: 'gender',
},
{
component: 'input',
label: 'Age',
field: 'age',
},
],
})
const options = {
gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}
const pagination = ref({
page: 1,
pageSize: 2,
total: 4,
})
const request = ref({
searchApi: mockApi,
})
const formConfig = ref({
columns: [
{
component: 'input',
field: 'name',
label: 'Name',
required: true,
},
{
component: 'select',
field: 'gender',
label: 'Gender',
},
{
component: 'el-date-picker',
field: 'time',
label: 'Date',
fieldProps: {
type: 'daterange',
startPlaceholder: 'Start date',
endPlaceholder: 'End date',
},
},
],
})
function mockApi() {
return new Promise((resolve) => {
setTimeout(() => {
const data = [
{
id: 1,
name: 'Steven',
gender: 'male',
age: 22,
date: '2020-01-01',
time: ['2020-01-01', '2020-01-02'],
},
{
id: 2,
name: 'Helen',
gender: 'male',
age: 12,
date: '2012-01-01',
time: ['2020-01-01', '2020-01-02'],
},
{
id: 3,
name: 'Nancy',
gender: 'female',
age: 18,
date: '2018-01-01',
time: ['2020-01-01', '2020-01-02'],
},
{
id: 4,
name: 'Jack',
gender: 'male',
age: 28,
date: '2028-01-01',
time: ['2020-01-01', '2020-01-02'],
},
]
resolve({
data: {
page: 1,
pageSize: 10,
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:pagination="pagination"
v-model:data="tableData"
v-model:formData="formData"
v-model:loading="loading"
:options="options"
:columns="columns"
:search="searchFormConfig"
:form="formConfig"
:delete="false"
:request="request"
/>
</template>Configure the form field of a column item to configure the detail information, but this will also configure the query, add, and edit forms at the same time. You can set search, add, and edit to false to disable them.
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
import type { EditRequestApiParams } from 'ideaz-element'
interface RowData {
id: number
name: string
gender: string
age: number
date: string
time: string[]
}
interface FormData {
name: string
gender: string
age: string
}
const loading = ref(false)
const formData = ref({
name: '',
gender: '',
age: '',
})
const tableData = ref([])
const columns = ref([
{
prop: 'name',
label: 'Name',
form: {
component: 'input',
field: 'name',
label: 'Name',
required: true,
},
},
{
prop: 'gender',
label: 'Gender',
form: {
component: 'select',
field: 'gender',
label: 'Gender',
},
},
{
prop: 'age',
label: 'Age',
form: {
component: 'el-date-picker',
field: 'time',
label: 'Date',
fieldProps: {
type: 'daterange',
startPlaceholder: 'Start date',
endPlaceholder: 'End date',
},
},
search: false,
add: false,
edit: false,
},
{
prop: 'date',
label: 'Date',
},
])
const options = {
gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}
const pagination = ref({
page: 1,
pageSize: 2,
total: 4,
})
const request = ref({
searchApi: mockApi,
addApi: commonApi,
editApi: commonApi,
})
function mockApi() {
return new Promise((resolve) => {
setTimeout(() => {
const data = [
{
id: 1,
name: 'Steven',
gender: 'male',
age: 22,
date: '2020-01-01',
time: ['2020-01-01', '2020-01-02'],
},
{
id: 2,
name: 'Helen',
gender: 'male',
age: 12,
date: '2012-01-01',
time: ['2020-01-01', '2020-01-02'],
},
{
id: 3,
name: 'Nancy',
gender: 'female',
age: 18,
date: '2018-01-01',
time: ['2020-01-01', '2020-01-02'],
},
{
id: 4,
name: 'Jack',
gender: 'male',
age: 28,
date: '2028-01-01',
time: ['2020-01-01', '2020-01-02'],
},
]
resolve({
data: {
page: 1,
pageSize: 10,
total: 4,
list: data.slice((pagination.value.page - 1) * pagination.value.pageSize, pagination.value.page * pagination.value.pageSize),
},
})
}, 100)
})
}
function commonApi(params: EditRequestApiParams<FormData, RowData>) {
console.log(params, 'commonApi params')
return new Promise((resolve) => {
setTimeout(() => {
resolve({
msg: 'success',
code: 200,
})
}, 100)
})
}
</script>
<template>
<z-crud
v-model:pagination="pagination"
v-model:data="tableData"
v-model:formData="formData"
v-model:loading="loading"
:columns="columns"
:options="options"
:delete="false"
:request="request"
/>
</template>API Configuration
By default, the detail view uses the row data. If you need to call an API, please configure request.detailApi.
<script lang="ts" setup>
import { ref } from 'vue'
const loading = ref(false)
const formData = ref({
name: '',
gender: '',
age: '',
})
const tableData = ref([])
const columns = ref([
{
prop: 'name',
label: 'Name',
search: {
component: 'input',
label: 'Name',
field: 'name',
},
detail: {
field: 'name',
label: 'Name',
},
},
{
prop: 'gender',
label: 'Gender',
search: {
component: 'select',
label: 'Gender',
field: 'gender',
},
detail: {
field: 'gender',
label: 'Gender',
},
},
{
prop: 'age',
label: 'Age',
detail: {
field: 'time',
label: 'Date',
},
search: {
component: 'input',
label: 'Age',
field: 'age',
},
},
{
prop: 'date',
label: 'Date',
},
])
const options = {
gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}
const pagination = ref({
page: 1,
pageSize: 2,
total: 4,
})
const request = ref({
searchApi: mockApi,
detailApi,
})
function mockApi() {
return new Promise((resolve) => {
setTimeout(() => {
const data = [
{
id: 1,
name: 'Steven',
gender: 'male',
age: 22,
date: '2020-01-01',
time: ['2020-01-01', '2020-01-02'],
},
{
id: 2,
name: 'Helen',
gender: 'male',
age: 12,
date: '2012-01-01',
time: ['2020-01-01', '2020-01-02'],
},
{
id: 3,
name: 'Nancy',
gender: 'female',
age: 18,
date: '2018-01-01',
time: ['2020-01-01', '2020-01-02'],
},
{
id: 4,
name: 'Jack',
gender: 'male',
age: 28,
date: '2028-01-01',
time: ['2020-01-01', '2020-01-02'],
},
]
resolve({
data: {
page: 1,
pageSize: 10,
total: 4,
list: data.slice((pagination.value.page - 1) * pagination.value.pageSize, pagination.value.page * pagination.value.pageSize),
},
})
}, 100)
})
}
function detailApi() {
return new Promise((resolve) => {
setTimeout(() => {
resolve({
data: {
id: 3,
time: '2023-01-12',
gender: 'male',
name: 'David',
},
})
}, 100)
})
}
</script>
<template>
<z-crud
v-model:pagination="pagination"
v-model:data="tableData"
v-model:formData="formData"
v-model:loading="loading"
:options="options"
:columns="columns"
:delete="false"
:add="false"
:edit="false"
:request="request"
/>
</template>Drawer Configuration
el-drawer component attributes are passed directly through drawer.
<script lang="ts" setup>
import { ref } from 'vue'
const loading = ref(false)
const formData = ref({
name: '',
gender: '',
age: '',
})
const tableData = ref([])
const columns = ref([
{
prop: 'name',
label: 'Name',
search: {
component: 'input',
label: 'Name',
field: 'name',
},
detail: {
field: 'name',
label: 'Name',
},
},
{
prop: 'gender',
label: 'Gender',
search: {
component: 'select',
label: 'Gender',
field: 'gender',
},
detail: {
field: 'gender',
label: 'Gender',
},
},
{
prop: 'age',
label: 'Age',
detail: {
field: 'time',
label: 'Date',
},
search: {
component: 'input',
label: 'Age',
field: 'age',
},
},
{
prop: 'date',
label: 'Date',
},
])
const drawer = ref({
title: 'View Details',
showClose: false,
})
const options = {
gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}
const pagination = ref({
page: 1,
pageSize: 2,
total: 4,
})
const request = ref({
searchApi: mockApi,
})
function mockApi() {
return new Promise((resolve) => {
setTimeout(() => {
const data = [
{
id: 1,
name: 'Steven',
gender: 'male',
age: 22,
date: '2020-01-01',
time: ['2020-01-01', '2020-01-02'],
},
{
id: 2,
name: 'Helen',
gender: 'male',
age: 12,
date: '2012-01-01',
time: ['2020-01-01', '2020-01-02'],
},
{
id: 3,
name: 'Nancy',
gender: 'female',
age: 18,
date: '2018-01-01',
time: ['2020-01-01', '2020-01-02'],
},
{
id: 4,
name: 'Jack',
gender: 'male',
age: 28,
date: '2028-01-01',
time: ['2020-01-01', '2020-01-02'],
},
]
resolve({
data: {
page: 1,
pageSize: 10,
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:pagination="pagination"
v-model:data="tableData"
v-model:formData="formData"
v-model:loading="loading"
:options="options"
:columns="columns"
:request="request"
:delete="false"
:add="false"
:edit="false"
:drawer="drawer"
/>
</template>Custom View
Supports using the operate-view event or passing a function to detail to customize the follow-up logic after clicking the view button.
<!-- eslint-disable unused-imports/no-unused-vars -->
<script lang="ts" setup>
import { ref } from 'vue'
import { ElMessage } from 'element-plus'
const loading = ref(false)
const formData = ref({
name: '',
gender: '',
age: '',
})
const tableData = ref([])
const columns = ref([
{
prop: 'name',
label: 'Name',
search: {
component: 'input',
label: 'Name',
field: 'name',
},
detail: {
field: 'name',
label: 'Name',
},
},
{
prop: 'gender',
label: 'Gender',
search: {
component: 'select',
label: 'Gender',
field: 'gender',
},
detail: {
field: 'gender',
label: 'Gender',
},
},
{
prop: 'age',
label: 'Age',
detail: {
field: 'time',
label: 'Date',
},
search: {
component: 'input',
label: 'Age',
field: 'age',
},
},
{
prop: 'date',
label: 'Date',
},
])
const options = {
gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}
const pagination = ref({
page: 1,
pageSize: 2,
total: 4,
})
const request = ref({
searchApi: mockApi,
})
function handleView({ row, tableRef }) {
ElMessage.success('View action triggered')
}
function mockApi() {
return new Promise((resolve) => {
setTimeout(() => {
const data = [
{
id: 1,
name: 'Steven',
gender: 'male',
age: 22,
date: '2020-01-01',
time: ['2020-01-01', '2020-01-02'],
},
{
id: 2,
name: 'Helen',
gender: 'male',
age: 12,
date: '2012-01-01',
time: ['2020-01-01', '2020-01-02'],
},
{
id: 3,
name: 'Nancy',
gender: 'female',
age: 18,
date: '2018-01-01',
time: ['2020-01-01', '2020-01-02'],
},
{
id: 4,
name: 'Jack',
gender: 'male',
age: 28,
date: '2028-01-01',
time: ['2020-01-01', '2020-01-02'],
},
]
resolve({
data: {
page: 1,
pageSize: 10,
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:pagination="pagination"
v-model:data="tableData"
v-model:formData="formData"
v-model:loading="loading"
:options="options"
:columns="columns"
:add="false"
:edit="false"
:delete="false"
:request="request"
@operate-view="handleView"
/>
</template>z-crud Detail Related Attributes
| Attribute | Description | Type | Default |
|---|---|---|---|
| detail | Detail configuration | boolean / object / ({ row, tableRef }) => void | true |
| form | Configuration for query, add, edit, and view form attributes | object | — |
| action | Whether to display action items (built-in delete, edit and other buttons) | boolean | true |
| edit | Edit configuration | boolean / object | true |
| add | Add configuration | boolean / object | true |
| delete | Delete configuration | boolean / ({ row, tableRef, getTableData }) => void / object | true |
| search | Search configuration | boolean / object | |
| drawer | Drawer configuration | object | — |
| request | API configuration | object | — |
detail Attributes
| Attribute | Description | Type | Default |
|---|---|---|---|
| columns | Form items | array | — |
| border | Whether with border | boolean | true |
| column | Number of Descriptions Item in a row | number | 1 |
| direction | Direction of arrangement | enum | horizontal |
| size | Size of the list | enum | — |
| title | Title text, displayed in the upper left | string / () => VNode | '' |
| extra | Action area text, displayed in the upper right | string / () => VNode | '' |
form Attributes
| Attribute | Description | Type | Default |
|---|---|---|---|
| rules | Form validation rules | object | — |
| columns | Form items | array | — |
| options | Data source of form options | object | — |
| colon | Colon of form item | boolean | false |
| align | Vertical alignment under flex layout | top / middle /bottom | — |
| label-position | Position of form field labels. When set to left or right, you also need to set the label-width attribute | enum | right |
| label-width | Length of the label, e.g. '50px'. Form-items that are direct children of Form inherit this value. auto can be used. | string / number | '' |
| label-suffix | Suffix of the form field label | string | '' |
| hide-required-asterisk | Whether to hide the red asterisk next to required field labels | boolean | false |
| require-asterisk-position | Position of the asterisk | left / right | left |
| show-message | Whether to display validation error messages | boolean | true |
| inline-message | Whether to display validation messages inline | boolean | false |
| status-icon | Whether to display validation result feedback icons in the input box | boolean | false |
| validate-on-rule-change | Whether to trigger a validation immediately after the rules attribute changes | boolean | true |
| size | Size used to control the components within this form | large / default / small | — |
| disabled | Whether to disable all components in this form. If set to true, it overrides internal components' disabled | boolean | false |
| scroll-to-error | Scroll to the first erroneous form item when validation fails | boolean | false |
| scroll-into-view-options | When there are failed validation results, scroll to the first failed form item | object / boolean | — |
request Attributes
| Attribute | Description | Type | Default |
|---|---|---|---|
| searchApi | Search API | (params: any) => promise | — |
| submitApi | Edit and add confirmation | ({ [key: string]: any, row: any, type: 'add' / 'edit' / 'view', formData: any }) => promise | — |
| deleteApi | Delete API | ({ [key: string]?: any, row?: any, selectionData?: any }) => promise | — |
| addApi | Add API | ({ type: 'add' / 'edit' / 'view', formData: any }) => promise | — |
| editApi | Edit API | ({ [key: string]: any, row: any, type: 'add' / 'edit' / 'view', formData: any }) => promise | — |
| detailApi | Detail API | ({ [key: string]: any, row: any }) => promise | — |
| alias | Custom data path | object | — |
| beforeData | Callback before table data API call | Function | — |
| afterData | Callback after table data API call | (res) => void | — |
| searchFunc | Override of search method | ({ params }) => any | — |
| tableData | Custom return of table data | (res) => any | — |
drawer Attributes
| Attribute | Description | Type | Default |
|---|---|---|---|
| append-to-body | Whether the Drawer itself is inserted into the body element. Nested Drawers must specify this property and set it to true | boolean | false |
| lock-scroll | Whether to lock body scrolling when Drawer appears | boolean | true |
| before-close | Callback before closing; will pause Drawer closing | Function | — |
| close-on-click-modal | Whether the Drawer can be closed by clicking the modal | boolean | true |
| close-on-press-escape | Whether the Drawer can be closed by pressing ESC | boolean | true |
| open-delay | Delay time for Drawer opening, in milliseconds | number | 0 |
| close-delay | Delay time for Drawer closing, in milliseconds | number | 0 |
| destroy-on-close | Controls whether to destroy all child elements after closing Drawer | boolean | false |
| modal | Whether a mask layer is needed | boolean | true |
| direction | Opening direction of the Drawer | enum | rtl |
| show-close | Whether to show the close button | boolean | true |
| size | Size of the Drawer window. When using number, it's in px; when using string, pass 'x%'; otherwise it will be interpreted as number | number / string | — |
| title | Title of the Drawer. Can also be passed via named slot (see below) | string | — |
| with-header | Controls whether to show the header bar. Default is true. When false, both the title attribute and title slot are ineffective | boolean | true |
| modal-class | Custom class name of the mask layer | string | — |
| z-index | Set z-index | number | — |
| header-aria-level | The aria-level attribute of the header | string | 2 |
| onOpen | Callback when Drawer opens | Function | — |
| onOpened | Callback when Drawer opening animation ends | Function | — |
| onClose | Callback when Drawer closes | Function | — |
| onClosed | Callback when Drawer closing animation ends | Function | — |
z-crud View Related Events
| Event Name | Description | Type |
|---|---|---|
| operate-view | View button event | ({ tableRef, row }) => void |