Comprehensive Usage
Example: simplify operations in a CRUD list.
This version may contain more code, including types, styles, and pagination handling. Adjust as needed in real projects.
With naive ui table
Nai Form Table Test
No Data
vue
<template>
<n-card>
<template #header>
<div class="title">Nai Form Table Test</div>
<div class="search">
<NaiDynamicForm :items="searchFormItems" ref="searchDynamicFormRef" preset="grid"/>
<div class="searchBtn">
<n-button type="info" size="small" @click="doSearch">Search</n-button>
<n-button size="small" @click="doReset">Reset</n-button>
</div>
</div>
<div class="controlBtn">
<n-button type="success" size="small" @click="addItem">Add</n-button>
</div>
</template>
<n-data-table
:scroll-x="800"
:single-line="false"
:columns="columns"
:data="pagedData"
:loading="tableLoading"
/>
<template #footer>
<div class="pagination">
<n-pagination v-model:page="pageModal.pageNo"
v-model:page-size="pageModal.pageSize"
:item-count="tableData.length">
<template #prefix="{ itemCount }">
Total {{ itemCount }}
</template>
</n-pagination>
</div>
</template>
</n-card>
<div class="update">
<n-modal v-model:show="showModal" :title="referId==='-1'?'add Item':'update Item'" preset="card" draggable
:style="{width:'70%'}">
<NaiDynamicForm :items="handleFormItems" ref="handleDynamicFormRef"/>
<template #footer>
<div class="fControlBtn">
<n-button size="small" @click="formCancel">Cancel</n-button>
<n-button type="info" size="small" @click="formSubmit">Submit</n-button>
</div>
</template>
</n-modal>
</div>
</template>
<script setup lang="ts">
import {type DataTableColumns, NSpace} from 'naive-ui'
import {NButton, NTag, useMessage} from 'naive-ui'
import {computed, h, nextTick, onMounted, reactive, ref} from 'vue'
import {NaiDynamicForm, type naiDynamicFormRef, renderInput, renderSelect} from "dynamicformdjx/naiveUi";
import {useDyForm, useReactiveForm} from "dynamicformdjx";
const message = useMessage()
interface RowData {
key: number
name: string
age: number
address: string
tags: string[]
}
type PageModal = {
pageSize: number
pageNo: number
}
const data = [
{
key: 0,
name: 'John Brown',
age: 12,
address: 'New York No. 1 Lake Park',
tags: ['nice', 'developer']
},
{
key: 1,
name: 'Jim Green',
age: 42,
address: 'London No. 1 Lake Park',
tags: ['wow']
},
{
key: 2,
name: 'Joe Black',
age: 32,
address: 'Sidney No. 1 Lake Park',
tags: ['cool', 'teacher']
}
]
const tagsSelection = data.flatMap(it => it.tags.map(it => ({label: it, value: it})))
const columns: DataTableColumns<RowData> = [
{
title: 'Name',
key: 'name'
},
{
title: 'Age',
key: 'age'
},
{
title: 'Address',
key: 'address'
},
{
title: 'Tags',
key: 'tags',
render(row) {
if (row.tags === null) return h('div', {}, '-')
const tags = row.tags.map((tagKey) => {
return h(
NTag,
{
style: {
marginRight: '6px'
},
type: 'info',
bordered: false
},
{
default: () => tagKey
}
)
})
return tags
}
},
{
title: 'Action',
key: 'actions',
fixed: 'right',
render(row) {
return h(
NSpace, {}, [
h(NButton,
{
size: 'small',
onClick: () => upItem(row)
},
{default: () => 'update'}),
h(NButton,
{
size: 'small',
type: 'error',
onClick: () => delItem(row)
},
{default: () => 'delete'})
]
)
}
}
]
const tableData = ref<RowData[]>([])
const tableLoading = ref<boolean>(false)
const showModal = ref<boolean>(false)
const referId = ref<string | number>('-1')
const pageModal = reactive<PageModal>({pageNo: 1, pageSize: 10})
const handleDynamicFormRef = ref<naiDynamicFormRef | null>(null)
const searchDynamicFormRef = ref<naiDynamicFormRef | null>(null)
const pagedData = computed(() => {
const {pageNo, pageSize} = pageModal
const start = (pageNo - 1) * pageSize
return tableData.value.slice(start, start + pageSize)
})
const searchFormItems = useReactiveForm<RowData>([
{
key: "name",
label: "Name",
value: null,
clearable: true,
render2: f => renderInput(f.value, {}, f),
span: 12
},
{
key: "age",
label: "Age",
value: null,
clearable: true,
render2: f => renderInput(f.value, {}, f),
span: 12
},
])
const handleFormItems = useReactiveForm<RowData>([
{
key: "name",
label: "Name",
value: null,
required: true,
render2: f => renderInput(f.value, {}, f),
},
{
key: "age",
label: "Age",
value: null,
clearable: true,
render2: f => renderInput(f.value, {}, f),
},
{
key: "address",
label: "Address",
value: null,
clearable: true,
type: 'textarea',
rows: 2,
render2: f => renderInput(f.value, {}, f),
},
{
key: "tags",
label: "Tags",
value: [],
clearable: true,
multiple: true,
render2: f => renderSelect(f.value, tagsSelection, {}, f),
},
])
const useHandleForm = useDyForm(handleFormItems)
const doSearch = () => {
const params = searchDynamicFormRef.value?.getResult?.() as any
message.info(JSON.stringify(params))
tableData.value = tableData.value.filter(it => it.name.includes(params.name) || it.age === parseInt(params.age))
pageModal.pageNo = 1
}
const doReset = () => {
searchDynamicFormRef.value?.reset?.()
tableData.value = data
pageModal.pageNo = 1
}
const addItem = () => {
useHandleForm.onReset()
referId.value = '-1'
nextTick(() => {
showModal.value = true
})
}
function upItem(it: RowData) {
referId.value = it.key
useHandleForm.setValues(it)
nextTick(() => {
showModal.value = true
})
}
function delItem(it: RowData) {
tableData.value = tableData.value.filter(it2 => it2.key !== it.key)
message.success('delete successful')
}
function formCancel() {
message.warning('cancel')
showModal.value = false
}
async function formSubmit() {
// const data = useHandleForm.getValues()
console.log(referId.value)
handleDynamicFormRef.value?.validator().then((v: any) => {
if (referId.value === '-1') {
tableData.value.push({...v, key: Date.now()})
message.success('Add successful')
} else {
tableData.value = tableData.value.map(it => {
if (referId.value === it.key) return v as RowData
return it
})
message.success('Update successful')
}
nextTick(() => {
showModal.value = false
// fetchData()
})
})
}
async function fetchData() {
tableLoading.value = true
const res = await new Promise((resolve, reject) => setTimeout(() => resolve(data), 1000))
tableData.value = res as RowData[]
tableLoading.value = false
}
onMounted(fetchData)
</script>
<style scoped>
.title {
text-align: center;
font-weight: bold;
font-size: 18px;
}
.search {
margin: 10px 0;
}
.pagination {
display: flex;
justify-content: center;
}
.search .searchBtn {
display: flex;
justify-content: flex-end;
gap: 10px;
}
.fControlBtn {
display: flex;
justify-content: center;
gap: 10px;
}
</style>vue
<template>
<n-card>
<template #header>
<div class="title">Nai Form Table Test</div>
<div class="search">
<NaiDynamicForm :items="searchFormItems" ref="searchDynamicFormRef" preset="grid"/>
<div class="searchBtn">
<n-button type="info" size="small" @click="doSearch">Search</n-button>
<n-button size="small" @click="doReset">Reset</n-button>
</div>
</div>
<div class="controlBtn">
<n-button type="success" size="small" @click="addItem">Add</n-button>
</div>
</template>
<n-data-table
:scroll-x="800"
:single-line="false"
:columns="columns"
:data="pagedData"
:loading="tableLoading"
/>
<template #footer>
<div class="pagination">
<n-pagination
v-model:page="pageModal.pageNo"
v-model:page-size="pageModal.pageSize"
:item-count="tableData.length"
>
<template #prefix="{ itemCount }">
Total {{ itemCount }}
</template>
</n-pagination>
</div>
</template>
</n-card>
<div class="update">
<n-modal
v-model:show="showModal"
:title="referId==='-1'?'add Item':'update Item'"
preset="card"
draggable
:style="{width:'70%'}"
>
<NaiDynamicForm :items="handleFormItems" ref="handleDynamicFormRef"/>
<template #footer>
<div class="fControlBtn">
<n-button size="small" @click="formCancel">Cancel</n-button>
<n-button type="info" size="small" @click="formSubmit">Submit</n-button>
</div>
</template>
</n-modal>
</div>
</template>
<script setup>
import {NSpace} from 'naive-ui'
import {NButton, NTag, useMessage} from 'naive-ui'
import {computed, h, nextTick, onMounted, reactive, ref} from 'vue'
import {NaiDynamicForm, renderInput, renderSelect} from "dynamicformdjx/naiveUi";
import {useDyForm, useReactiveForm} from "dynamicformdjx";
const message = useMessage()
const data = [
{
key: 0,
name: 'John Brown',
age: 12,
address: 'New York No. 1 Lake Park',
tags: ['nice', 'developer']
},
{
key: 1,
name: 'Jim Green',
age: 42,
address: 'London No. 1 Lake Park',
tags: ['wow']
},
{
key: 2,
name: 'Joe Black',
age: 32,
address: 'Sidney No. 1 Lake Park',
tags: ['cool', 'teacher']
}
]
const tagsSelection = data.flatMap(it => it.tags.map(it => ({label: it, value: it})))
const columns = [
{
title: 'Name',
key: 'name'
},
{
title: 'Age',
key: 'age'
},
{
title: 'Address',
key: 'address'
},
{
title: 'Tags',
key: 'tags',
render(row) {
if (row.tags === null) return h('div', {}, '-')
const tags = row.tags.map((tagKey) => {
return h(
NTag,
{
style: {
marginRight: '6px'
},
type: 'info',
bordered: false
},
{
default: () => tagKey
}
)
})
return tags
}
},
{
title: 'Action',
key: 'actions',
fixed: 'right',
render(row) {
return h(
NSpace, {}, [
h(NButton,
{
size: 'small',
onClick: () => upItem(row)
},
{default: () => 'update'}),
h(NButton,
{
size: 'small',
type: 'error',
onClick: () => delItem(row)
},
{default: () => 'delete'})
]
)
}
}
]
const tableData = ref([])
const tableLoading = ref(false)
const showModal = ref(false)
const referId = ref('-1')
const pageModal = reactive({pageNo: 1, pageSize: 10})
const handleDynamicFormRef = ref(null)
const searchDynamicFormRef = ref(null)
const pagedData = computed(() => {
const {pageNo, pageSize} = pageModal
const start = (pageNo - 1) * pageSize
return tableData.value.slice(start, start + pageSize)
})
const searchFormItems = useReactiveForm([
{
key: "name",
label: "Name",
value: null,
clearable: true,
render2: f => renderInput(f.value, {}, f),
span: 12
},
{
key: "age",
label: "Age",
value: null,
clearable: true,
render2: f => renderInput(f.value, {}, f),
span: 12
},
])
const handleFormItems = useReactiveForm([
{
key: "name",
label: "Name",
value: null,
required: true,
render2: f => renderInput(f.value, {}, f),
},
{
key: "age",
label: "Age",
value: null,
clearable: true,
render2: f => renderInput(f.value, {}, f),
},
{
key: "address",
label: "Address",
value: null,
clearable: true,
type: 'textarea',
rows: 2,
render2: f => renderInput(f.value, {}, f),
},
{
key: "tags",
label: "Tags",
value: [],
clearable: true,
multiple: true,
render2: f => renderSelect(f.value, tagsSelection, {}, f),
},
])
const useHandleForm = useDyForm(handleFormItems)
const doSearch = () => {
const params = searchDynamicFormRef.value?.getResult?.()
message.info(JSON.stringify(params))
tableData.value = tableData.value.filter(it => it.name.includes(params.name) || it.age === parseInt(params.age))
pageModal.pageNo = 1
}
const doReset = () => {
searchDynamicFormRef.value?.reset?.()
tableData.value = data
pageModal.pageNo = 1
}
const addItem = () => {
useHandleForm.onReset()
referId.value = '-1'
nextTick(() => {
showModal.value = true
})
}
function upItem(it) {
referId.value = it.key
useHandleForm.setValues(it)
nextTick(() => {
showModal.value = true
})
}
function delItem(it) {
tableData.value = tableData.value.filter(it2 => it2.key !== it.key)
message.success('delete successful')
}
function formCancel() {
message.warning('cancel')
showModal.value = false
}
async function formSubmit() {
// const data = useHandleForm.getValues()
console.log(referId.value)
handleDynamicFormRef.value?.validator().then((v) => {
if (referId.value === '-1') {
tableData.value.push({...v, key: Date.now()})
message.success('Add successful')
} else {
tableData.value = tableData.value.map(it => {
if (referId.value === it.key) return v
return it
})
message.success('Update successful')
}
nextTick(() => {
showModal.value = false
// fetchData()
})
})
}
async function fetchData() {
tableLoading.value = true
const res = await new Promise((resolve, reject) => setTimeout(() => resolve(data), 1000))
tableData.value = res
tableLoading.value = false
}
onMounted(fetchData)
</script>
<style scoped>
.title {
text-align: center;
font-weight: bold;
font-size: 18px;
}
.search {
margin: 10px 0;
}
.pagination {
display: flex;
justify-content: center;
}
.search .searchBtn {
display: flex;
justify-content: flex-end;
gap: 10px;
}
.fControlBtn {
display: flex;
justify-content: center;
gap: 10px;
}
</style>With element plus table
ElementPlus Form Table Test
Total 0
- 1
vue
<template>
<el-card>
<template #header>
<div class="title">ElementPlus Form Table Test</div>
<div class="search">
<EleDynamicForm :items="searchFormItems" ref="searchDynamicFormRef" preset="grid"/>
<div class="searchBtn">
<el-button type="primary" size="small" @click="doSearch">Search</el-button>
<el-button size="small" @click="doReset">Reset</el-button>
</div>
</div>
<div class="controlBtn">
<el-button type="success" size="small" @click="addItem">Add</el-button>
</div>
</template>
<div class="tableScroll">
<el-table
v-loading="tableLoading"
:data="pagedData"
border
style="min-width: 900px"
>
<el-table-column :prop="r.prop" :label="r.label" v-for="r in tableProps" :key="r.prop">
<template #scope="row">
<template v-if="r.prop!=='tags'">{{ row[r.prop] }}</template>
<template v-else>
<span v-if="!row.tags || row.tags.length === 0">-</span>
<template v-else>
<el-tag
v-for="t in row.tags"
:key="t"
class="tag"
type="info"
effect="plain"
>
{{ t }}
</el-tag>
</template>
</template>
</template>
</el-table-column>
<el-table-column label="Action" width="180" fixed="right">
<template #default="{ row }">
<el-space>
<el-button size="small" @click="upItem(row)">update</el-button>
<el-button size="small" type="danger" @click="delItem(row)">delete</el-button>
</el-space>
</template>
</el-table-column>
</el-table>
</div>
<div class="pagination">
<el-pagination
v-model:current-page="pageModal.pageNo"
v-model:page-size="pageModal.pageSize"
:total="tableData.length"
layout="total, prev, pager, next"
/>
</div>
</el-card>
<el-dialog
v-model="showModal"
:title="referId === -1 ? 'add Item' : 'update Item'"
width="70%"
draggable
>
<EleDynamicForm :items="handleFormItems" ref="handleDynamicFormRef"/>
<template #footer>
<div class="fControlBtn">
<el-button size="small" @click="formCancel">Cancel</el-button>
<el-button type="primary" size="small" @click="formSubmit">Submit</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import {computed, nextTick, onMounted, reactive, ref} from 'vue'
import {ElMessage} from 'element-plus'
import {
EleDynamicForm,
type eleDynamicFormRef,
renderInput,
renderSelect
} from 'dynamicformdjx/elementPlus'
import {useDyForm, useReactiveForm} from 'dynamicformdjx'
interface RowData {
key: number
name: string
age: number
address: string
tags: string[]
}
type PageModal = {
pageSize: number
pageNo: number
}
const pageModal = reactive<PageModal>({pageNo: 1, pageSize: 10})
const tableLoading = ref(false)
const showModal = ref(false)
const referId = ref<number | string>(-1)
const handleDynamicFormRef = ref<eleDynamicFormRef | null>(null)
const searchDynamicFormRef = ref<eleDynamicFormRef | null>(null)
const seedData: RowData[] = [
{key: 0, name: 'John Brown', age: 12, address: 'New York No. 1 Lake Park', tags: ['nice', 'developer']},
{key: 1, name: 'Jim Green', age: 42, address: 'London No. 1 Lake Park', tags: ['wow']},
{key: 2, name: 'Joe Black', age: 32, address: 'Sidney No. 1 Lake Park', tags: ['cool', 'teacher']}
]
const tableProps: { label: string, prop: keyof RowData }[] = [
{label: 'Name', prop: 'name'},
{label: 'Age', prop: 'age'},
{label: 'Address', prop: 'address'},
{label: 'Tags', prop: 'tags'},
]
const tagsSelection = seedData.flatMap(it => it.tags.map(it => ({label: it, value: it})))
const tableData = ref<RowData[]>([])
const pagedData = computed(() => {
const {pageNo, pageSize} = pageModal
const start = (pageNo - 1) * pageSize
return tableData.value.slice(start, start + pageSize)
})
const searchFormItems = useReactiveForm<RowData>([
{
key: 'name',
label: 'Name',
value: null,
clearable: true,
render2: f => renderInput(f.value, {}, f),
span: 12
},
{
key: 'age',
label: 'Age',
value: null,
clearable: true,
render2: f => renderInput(f.value, {}, f),
span: 12
}
])
const handleFormItems = useReactiveForm<RowData>([
{
key: 'name',
label: 'Name',
value: null,
required: true,
render2: f => renderInput(f.value, {}, f)
},
{
key: 'age',
label: 'Age',
value: null,
clearable: true,
render2: f => renderInput(f.value, {}, f)
},
{
key: 'address',
label: 'Address',
value: null,
clearable: true,
type: 'textarea',
rows: 2,
render2: f => renderInput(f.value, {}, f)
},
{
key: 'tags',
label: 'Tags',
value: [],
clearable: true,
multiple: true,
render2: f => renderSelect(f.value, tagsSelection, {}, f)
}
])
const useHandleForm = useDyForm(handleFormItems)
const doSearch = () => {
const params = (searchDynamicFormRef.value?.getResult?.() ?? {}) as any
ElMessage.info(JSON.stringify(params))
tableData.value = tableData.value.filter(it => it.name.includes(params.name) || it.age === parseInt(params.age))
pageModal.pageNo = 1
}
const doReset = () => {
searchDynamicFormRef.value?.reset?.()
tableData.value = seedData
pageModal.pageNo = 1
}
const addItem = () => {
useHandleForm.onReset()
referId.value = -1
nextTick(() => {
showModal.value = true
})
}
function upItem(it: RowData) {
referId.value = it.key
useHandleForm.setValues(it)
nextTick(() => {
showModal.value = true
})
}
function delItem(it: RowData) {
tableData.value = tableData.value.filter(r => r.key !== it.key)
ElMessage.success('delete successful')
}
function formCancel() {
ElMessage.warning('cancel')
showModal.value = false
}
async function formSubmit() {
handleDynamicFormRef.value?.validator().then((v: any) => {
if (referId.value === -1) {
const newRow: RowData = {...(v as any), key: Date.now()}
tableData.value = [...tableData.value, newRow]
ElMessage.success('Add successful')
} else {
tableData.value = tableData.value.map(r =>
r.key === referId.value ? ({...r, ...(v as any), key: r.key} as RowData) : r
)
ElMessage.success('Update successful')
}
nextTick(() => {
showModal.value = false
})
})
}
async function fetchData() {
tableLoading.value = true
const res = await new Promise<RowData[]>(resolve => setTimeout(() => resolve(seedData), 800))
tableData.value = [...res]
tableLoading.value = false
}
onMounted(fetchData)
</script>
<style scoped>
.title {
text-align: center;
font-weight: bold;
font-size: 18px;
}
.search {
margin: 10px 0;
}
.tableScroll{
width: 100%;
overflow-x: auto;
}
.pagination {
display: flex;
justify-content: center;
margin-top: 12px;
}
.search .searchBtn {
display: flex;
justify-content: flex-end;
gap: 10px;
}
.fControlBtn {
display: flex;
justify-content: center;
gap: 10px;
}
.tag {
margin-right: 6px;
}
</style>vue
<template>
<el-card>
<template #header>
<div class="title">ElementPlus Form Table Test</div>
<div class="search">
<EleDynamicForm :items="searchFormItems" ref="searchDynamicFormRef" preset="grid"/>
<div class="searchBtn">
<el-button type="primary" size="small" @click="doSearch">Search</el-button>
<el-button size="small" @click="doReset">Reset</el-button>
</div>
</div>
<div class="controlBtn">
<el-button type="success" size="small" @click="addItem">Add</el-button>
</div>
</template>
<div class="tableScroll">
<el-table
v-loading="tableLoading"
:data="pagedData"
border
style="min-width: 900px"
>
<el-table-column
:prop="r.prop"
:label="r.label"
v-for="r in tableProps"
:key="r.prop"
>
<template #scope="row">
<template v-if="r.prop !== 'tags'">{{ row[r.prop] }}</template>
<template v-else>
<span v-if="!row.tags || row.tags.length === 0">-</span>
<template v-else>
<el-tag
v-for="t in row.tags"
:key="t"
class="tag"
type="info"
effect="plain"
>
{{ t }}
</el-tag>
</template>
</template>
</template>
</el-table-column>
<el-table-column label="Action" width="180" fixed="right">
<template #default="{ row }">
<el-space>
<el-button size="small" @click="upItem(row)">update</el-button>
<el-button size="small" type="danger" @click="delItem(row)">delete</el-button>
</el-space>
</template>
</el-table-column>
</el-table>
</div>
<div class="pagination">
<el-pagination
v-model:current-page="pageModal.pageNo"
v-model:page-size="pageModal.pageSize"
:total="tableData.length"
layout="total, prev, pager, next"
/>
</div>
</el-card>
<el-dialog
v-model="showModal"
:title="referId === -1 ? 'add Item' : 'update Item'"
width="70%"
draggable
>
<EleDynamicForm :items="handleFormItems" ref="handleDynamicFormRef"/>
<template #footer>
<div class="fControlBtn">
<el-button size="small" @click="formCancel">Cancel</el-button>
<el-button type="primary" size="small" @click="formSubmit">Submit</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import {computed, nextTick, onMounted, reactive, ref} from 'vue'
import {ElMessage} from 'element-plus'
import {EleDynamicForm, renderInput, renderSelect} from 'dynamicformdjx/elementPlus'
import {useDyForm, useReactiveForm} from 'dynamicformdjx'
const pageModal = reactive({pageNo: 1, pageSize: 10})
const tableLoading = ref(false)
const showModal = ref(false)
const referId = ref(-1)
const handleDynamicFormRef = ref(null)
const searchDynamicFormRef = ref(null)
const seedData = [
{key: 0, name: 'John Brown', age: 12, address: 'New York No. 1 Lake Park', tags: ['nice', 'developer']},
{key: 1, name: 'Jim Green', age: 42, address: 'London No. 1 Lake Park', tags: ['wow']},
{key: 2, name: 'Joe Black', age: 32, address: 'Sidney No. 1 Lake Park', tags: ['cool', 'teacher']}
]
const tableProps = [
{label: 'Name', prop: 'name'},
{label: 'Age', prop: 'age'},
{label: 'Address', prop: 'address'},
{label: 'Tags', prop: 'tags'}
]
const tagsSelection = seedData.flatMap(it => it.tags.map(it => ({label: it, value: it})))
const tableData = ref([])
const pagedData = computed(() => {
const {pageNo, pageSize} = pageModal
const start = (pageNo - 1) * pageSize
return tableData.value.slice(start, start + pageSize)
})
const searchFormItems = useReactiveForm([
{
key: 'name',
label: 'Name',
value: null,
clearable: true,
render2: f => renderInput(f.value, {}, f),
span: 12
},
{
key: 'age',
label: 'Age',
value: null,
clearable: true,
render2: f => renderInput(f.value, {}, f),
span: 12
}
])
const handleFormItems = useReactiveForm([
{
key: 'name',
label: 'Name',
value: null,
required: true,
render2: f => renderInput(f.value, {}, f)
},
{
key: 'age',
label: 'Age',
value: null,
clearable: true,
render2: f => renderInput(f.value, {}, f)
},
{
key: 'address',
label: 'Address',
value: null,
clearable: true,
type: 'textarea',
rows: 2,
render2: f => renderInput(f.value, {}, f)
},
{
key: 'tags',
label: 'Tags',
value: [],
clearable: true,
multiple: true,
render2: f => renderSelect(f.value, tagsSelection, {}, f)
}
])
const useHandleForm = useDyForm(handleFormItems)
const doSearch = () => {
const params = searchDynamicFormRef.value?.getResult?.() ?? {}
ElMessage.info(JSON.stringify(params))
tableData.value = tableData.value.filter(it => it.name.includes(params.name) || it.age === parseInt(params.age))
pageModal.pageNo = 1
}
const doReset = () => {
searchDynamicFormRef.value?.reset?.()
tableData.value = seedData
pageModal.pageNo = 1
}
const addItem = () => {
useHandleForm.onReset()
referId.value = -1
nextTick(() => {
showModal.value = true
})
}
function upItem(it) {
referId.value = it.key
useHandleForm.setValues(it)
nextTick(() => {
showModal.value = true
})
}
function delItem(it) {
tableData.value = tableData.value.filter(r => r.key !== it.key)
ElMessage.success('delete successful')
}
function formCancel() {
ElMessage.warning('cancel')
showModal.value = false
}
async function formSubmit() {
handleDynamicFormRef.value?.validator().then((v) => {
if (referId.value === -1) {
const newRow = {...(v), key: Date.now()}
tableData.value = [...tableData.value, newRow]
ElMessage.success('Add successful')
} else {
tableData.value = tableData.value.map(r =>
r.key === referId.value ? ({...r, ...(v), key: r.key}) : r
)
ElMessage.success('Update successful')
}
nextTick(() => {
showModal.value = false
})
})
}
async function fetchData() {
tableLoading.value = true
const res = await new Promise(resolve => setTimeout(() => resolve(seedData), 800))
tableData.value = [...res]
tableLoading.value = false
}
onMounted(fetchData)
</script>
<style scoped>
.title {
text-align: center;
font-weight: bold;
font-size: 18px;
}
.search {
margin: 10px 0;
}
.tableScroll {
width: 100%;
overflow-x: auto;
}
.pagination {
display: flex;
justify-content: center;
margin-top: 12px;
}
.search .searchBtn {
display: flex;
justify-content: flex-end;
gap: 10px;
}
.fControlBtn {
display: flex;
justify-content: center;
gap: 10px;
}
.tag {
margin-right: 6px;
}
</style>TIP
The example above shows how to use it in a simple create/read/update/delete workflow. A reusable fixed-layout UI component will be provided later to further simplify the template code, moving the data-driven logic into setup