FormItems 表单项
快速的数据化配置一个表单。
FormGrid,FormDesc,FormTableEditor 等表单布局组件都适用以下规则。
典型表单
使用内置数据化的表单项组件比如 agel-select
、agel-radio
、agel-checkbox
等,可快速完成一个包含各种输入表单项的基础表单。
属性 slot
指定要渲染的组件实例或组件名称,若传递的是组件名称,需要保证该组件已经全局导入。
属性 attrs
为其组件提供属性支持,使用驼峰命名法。
属性 required
将自动生成由 label 组成的必填规则。
使用 getRef
可以获取表单子组件的组件的实例对象。
点击查看代码
<template>
<ElForm :model="form.model" label-width="auto" class="demo">
<AgelFormItems ref="formLayoutRef" :items="form.items"></AgelFormItems>
</ElForm>
</template>
<script lang="tsx" setup>
import { reactive, ref } from 'vue'
import { ElMessage } from 'element-plus'
const formLayoutRef = ref()
const form = reactive({
model: {},
items: [
{
prop: 'name',
label: 'Activity name',
required: true
},
{
prop: 'zone',
label: 'Activity zone',
slot: 'agel-select',
attrs: {
options: [
{ label: 'Zone one', value: 'shanghai' },
{ label: 'Zone two', value: 'beijing' }
],
onChange: (v: string) => {
ElMessage({
message: `change ${v}`,
type: 'success'
})
}
}
},
{
prop: 'date',
label: 'Activity date',
slot: 'el-date-picker'
},
{
prop: 'delivery',
label: 'Instant delivery',
slot: 'el-switch'
},
{
prop: 'type',
label: 'Activity type',
slot: 'agel-checkbox',
attrs: {
options: ['Online activities', 'Promotion activities', 'Offline activities', 'Simple brand exposure']
}
},
{
prop: 'resources',
label: 'Resources',
slot: 'agel-radio',
attrs: { options: ['Sponsor', 'Venue'] }
},
{
prop: 'decs',
label: 'Activity Form',
attrs: { type: 'textarea' }
},
{
slot: 'ElButton',
slots: () => 'Create',
attrs: {
type: 'primary',
onClick: () => {
formLayoutRef.value?.validate()
formLayoutRef.value?.getRef('zone').focus()
}
}
}
]
})
</script>
插槽表单
属性 slot
label
可以为一个渲染函数,使用 jsx
大幅提高体验。
属性 slot
支持模板插槽,但必须 slot-
开头,否则会被识别为组件名称。
属性 slots
可以实现表单项组件的子插槽的渲染。
点击查看代码
<template>
<ElForm :model="form.model" label-width="auto" class="demo __fullwidth">
<AgelFormItems :items="form.items">
<template #slot-date>
<el-button>自定义 slot2</el-button>
</template>
</AgelFormItems>
</ElForm>
</template>
<script lang="tsx" setup>
import { reactive } from 'vue'
const form = reactive({
model: {},
items: [
{
label: () => <el-tag>自定义 label</el-tag>,
slot: () => <el-button>自定义 slot1</el-button>
},
{
label: '模板插槽',
slot: 'slot-date'
},
{
label: '组件子插槽',
slot: 'el-input',
slots: {
prepend: () => 'http://',
append: () => '.com'
}
}
]
})
</script>
联动表单
得益于 vue3 的 进步,数据化配置也可以通过 computed
简单快速的实现表单之间的联动。
点击查看代码
<template>
<ElForm :model="model" label-width="auto" class="demo">
<AgelFormItems :items="items"></AgelFormItems>
</ElForm>
</template>
<script lang="tsx" setup>
import { reactive, ref, computed } from 'vue'
const model = reactive({
grade: '很棒'
})
const options = ref<string[]>([])
const items = ref([
{
label: '打分',
prop: 'grade',
slot: 'agel-radio',
attrs: {
options: ['很棒', '很糟糕']
}
},
{
label: '分数',
prop: 'number',
loading: computed(() => options.value.length == 0),
slot: 'agel-select',
attrs: {
class:'w100',
options: computed(() => options.value)
}
},
{
label: '好评',
prop: 'good',
hidden: computed(() => model.grade == '很糟糕'),
},
{
label: '差评',
prop: 'good',
hidden: computed(() => model.grade == '很棒'),
attrs: {
disabled: computed(() => model.grade == '很糟糕'),
}
},
{
slot: 'ElButton',
slots: () => '获取分数',
attrs: {
type: 'primary',
onClick: getOption
},
}
])
function getOption() {
// 模拟接口
options.value = []
setTimeout(() => {
options.value = Array.from({ length: 10 }).map((v, i) => (i + 1) + '分')
}, 2000);
}
getOption()
</script>
动态表单
设置 modelProp
为表单项提供动态 prop,值得注意是 v-for 的 key 需指定为 index。
设置 scope
属性为 slot
渲染函数/插槽 提供作用域参数。
点击查看代码
<template>
<ElForm label-width="auto" :model="model" class="demo" inline>
<AgelFormItems
v-for="(rowData, rowIndex) in model.domains"
:items="domainsItems"
:model-prop="'domains.' + rowIndex"
:key="rowIndex"
:scope="{ rowData, rowIndex }"
>
</AgelFormItems>
<ElFormItem>
<ElButton type="primary" @click="model.domains.push({ phone: String(model.domains.length + 1) })">添加</ElButton>
</ElFormItem>
</ElForm>
</template>
<script lang="tsx" setup>
import { reactive } from 'vue'
const model = reactive({
domains: [{ phone: '1' }, { phone: '2' }]
})
const domainsItems = [
{ slot: ({ rowIndex }: any) => <b>动态表单{rowIndex + 1}</b>, class: 'w100' },
{ prop: 'phone', label: ({ rowIndex }: any) => '手机号码' + (rowIndex + 1) },
{ prop: 'email', label: '联系邮件' },
{
span: 4,
labelWidth: 0,
slot: ({ rowIndex }: any) => {
return <el-button onClick={() => model.domains.splice(rowIndex, 1)}>删除</el-button>
}
}
]
</script>
属性
属性 | 类型 | 默认值 | 说明 |
---|---|---|---|
items | ItemProps[] | - | 表单配置项 |
view-model | boolean | - | 视图模式,只渲染 value |
model-prop | string | - | 表单 model 键名 |
scope | object | - | 表单项插槽作用域参数 |
ItemProps
属性 | 类型 | 默认值 | 说明 |
---|---|---|---|
prop | string | - | model 键名,支持 'obj.xx.xx' |
label | string | RenderFunction | - | 标签文本 |
required | boolean | - | 自动生成必填规则 |
slot | string | Component | RenderFunction | ElInput | 表单项组件 |
slots | Slots | RenderFunction | - | 表单项组件的插槽 |
attrs | object | - | 表单项组件的属性 |
viewModel | boolean | - | 视图模式,只渲染 value |
viewFormat | RenderFunction | - | 视图模式的格式化工具 |
vmodel | '.trim' | '.number' | - | v-model 修饰符 |
loading | boolean | - | 是否显示加载 |
hidden | boolean | - | 是否隐藏 |
class | string | - | formitem class |
labelWidth, rules, error, showMessage, inlineMessage | ... | ElFormIten 属性 |
方法
名称 | 参数 | 说明 |
---|---|---|
getRef | prop | 获取组件实例 |
validate | (callback)=>Promise | 对整个 items 表单进行验证 |
resetFields | props | 重置表单 |
插槽
名称 | 插槽作用域 | 说明 |
---|---|---|
slot-xx | itemProps | item 组件具名插槽 |