| name | el-plus-crud-form-group |
| description | Multi-section grouped form with independent validation per group, shared submit lifecycle, and dynamic group visibility |
| version | 1.0.0 |
| origin | el-plus-crud |
| tags | ["vue3","element-plus","form-group","multi-section-form","grouped-form"] |
ElPlusFormGroup — Grouped Form
ElPlusFormGroup organizes multiple ElPlusForm instances into a grouped form. Each group has its own title, column count, and formDesc. Supports dynamic group visibility (vif), cross-group joint validation, and a unified submit lifecycle. Typical scenarios: multi-section detail pages, complex edit pages, wizard-style forms.
When to Activate
- Using
<ElPlusFormGroup> component
- Writing
IFormGroupConfig configuration
- Organizing form fields into titled sections
- Needing per-group column count and visibility control
- Calling group-level validate / clear / getData / init methods
Core Concepts
IFormGroupConfig Structure
interface IFormGroupConfig {
column?: number
beforeValidate?: (data) => any
beforeRequest?: (data) => any
requestFn?: (data) => Promise
updateFn?: (data) => Promise
success?: (formBack: IFormBack) => any
successTip?: string | ((data?) => string)
tableRef?: any
group: Array<{
title?: string
formDesc: IFormDesc
column?: number
vif?: boolean | ((data?) => boolean)
fid?: string
showBtns?: boolean
maxWidth?: string
labelWidth?: string | number
}>
}
Multi-Instance Coordination
Each group creates an independent ElPlusForm instance. The FormGroup manages them through a formRefs array:
- Only the last visible group shows submit/cancel/reset buttons
- All groups share the same
modelValue object — field names must not overlap across groups
groupFormDesc collects all visible groups' formDesc for unified data processing
Validation Strategy
External beforeValidate (IFormGroupConfig level)
→ Promise.all(formRefs.map(ref => ref.validate()))
All groups are validated in parallel. If any group fails, the entire submission is rejected.
Data Merging
getData() merges all groups' form data into a single object:
function getData() {
const tempData = {}
formRefs.value.map(tempRef => Object.assign(tempData, tempRef.getData()))
return tempData
}
Dynamic Group Visibility
group: [
{ title: '基本信息', formDesc: basicDesc },
{ title: '企业信息', formDesc: companyDesc, vif: (data) => !!data.isCompany },
{ title: '附加信息', formDesc: extraDesc }
]
When vif returns false, the group is filtered out and its fields are excluded from validation and data collection.
Named Slots
Slots are indexed by group position:
<ElPlusFormGroup v-model="formData" :formGroup="formGroupConfig">
<template #title0><h3>Custom Title for Group 0</h3></template>
<template #default1><div>Extra content in Group 1</div></template>
<template #top2><div>Content above Group 2</div></template>
</ElPlusFormGroup>
Available slot names: top{index}, title{index}, default{index} for each group.
Expose Methods
const groupRef = ref()
await groupRef.value.validate()
groupRef.value.getData()
groupRef.value.clearValid()
groupRef.value.clear()
groupRef.value.init()
Code Examples
Basic Grouped Form
<ElPlusFormGroup v-model="formData" :formGroup="formGroupConfig" />
const formData = ref({})
const formGroupConfig: IFormGroupConfig = {
column: 2,
requestFn: api.saveProfile,
success: ({ callBack }) => {
ElMessage.success('保存成功')
callBack()
},
group: [
{
title: '基本信息',
formDesc: {
name: { type: 'input', label: '姓名', required: true },
phone: { type: 'input', label: '手机号', rules: 'phone' },
email: { type: 'input', label: '邮箱', rules: 'email' }
}
},
{
title: '地址信息',
formDesc: {
province: { type: 'area', label: '地区', required: true },
address: { type: 'input', label: '详细地址' }
}
},
{
title: '备注',
formDesc: {
remark: { type: 'textarea', label: '备注信息', colspan: 2 }
}
}
]
}
Dynamic Group Visibility
const formGroupConfig: IFormGroupConfig = {
column: 2,
requestFn: api.save,
group: [
{ title: '个人信息', formDesc: personalDesc },
{
title: '企业信息',
formDesc: companyDesc,
column: 3,
vif: (data) => data.userType === 'company'
},
{ title: '其他', formDesc: otherDesc }
]
}
Custom Group Title via Slots
<ElPlusFormGroup v-model="formData" :formGroup="formGroupConfig">
<template #title0>
<div style="color: #409eff; font-size: 18px; font-weight: bold;">
基本信息
</div>
</template>
<template #default1>
<el-divider />
</template>
</ElPlusFormGroup>
ref Method Usage
const groupRef = ref()
const handleSubmit = async () => {
try {
await groupRef.value.validate()
const data = groupRef.value.getData()
await api.save(data)
ElMessage.success('保存成功')
} catch (e) {
console.error('验证失败', e)
}
}
const handleReset = () => {
groupRef.value.clear()
}
Anti-Patterns
FAIL: Manually coordinate multiple separate forms
<div class="section"><h3>基本信息</h3><ElPlusForm ref="form1" :formDesc="desc1" /></div>
<div class="section"><h3>地址</h3><ElPlusForm ref="form2" :formDesc="desc2" /></div>
const submit = async () => {
await form1.value.validate()
await form2.value.validate()
const data = { ...form1.value.getData(), ...form2.value.getData() }
await api.save(data)
}
PASS: Use ElPlusFormGroup for unified management
<ElPlusFormGroup v-model="formData" :formGroup="formGroupConfig" />
FAIL: Expect per-group requestFn
group: [
{ title: 'A', formDesc: descA, requestFn: api.saveA },
{ title: 'B', formDesc: descB, requestFn: api.saveB }
]
PASS: Use unified requestFn, dispatch in beforeRequest
const formGroupConfig: IFormGroupConfig = {
requestFn: (data) => api.saveAll(data),
beforeRequest: (data) => {
return data
},
group: [...]
}
Best Practices
- Use
fid for stable group identifiers — avoid index-based keys
- Last group shows buttons by default (
showBtns: true); previous groups auto-hide buttons
- Use
title{index} slots for custom group header styles (default: left border + text)
- Ensure field names don't overlap across groups — all share the same
modelValue object
- Set
disabledTab: true to prevent Tab key from leaving the form on the last field
Related Skills
el-plus-crud-form — ElPlusFormGroup creates ElPlusForm instances per group; all formDesc config applies (direct)
el-plus-crud-config — IFormGroupConfig type definition (indirect)
el-plus-crud-validation — cross-group parallel validation mechanism (indirect)