Form 配置表单
该组件是基于el-form封装的组件,提供配置表单功能
注意
注意:0.0.27版本之后,如果是用reactive定义,使用@update:model-value="Object.assign(form, $event)"配合来监听数据变化,如果是ref定义,可以直接使用v-model
基础用法
配置表单示例
查看代码
vue
<template>
<div>
<gi-card title="配置表单示例" bordered>
<template #extra>
<el-switch v-model="disabled" active-text="禁用"></el-switch>
<el-radio-group v-model="labelPosition" size="small">
<el-radio-button label="左侧" value="left" />
<el-radio-button label="右侧" value="right" />
<el-radio-button label="顶部" value="top" />
</el-radio-group>
</template>
<gi-form ref="GiFormRef" :model-value="form" :columns="columns" :disabled="disabled" label-width="auto"
:label-position="labelPosition" :grid-item-props="{
span: { xs: 24, sm: 24, md: 24, lg: 12, xl: 12, xxl: 12 },
}" @update:model-value="Object.assign(form, $event)">
<template #customSlot="{ item }">
{{ form.status }}-----------{{ item.field }}
</template>
<template #customSlot2>
<el-alert title="Success alert" type="success" effect="dark" />
<el-alert title="Info alert" type="info" effect="dark" />
<el-alert title="Warning alert" type="warning" effect="dark" />
<el-alert title="Error alert" type="error" effect="dark" />
</template>
<template #btns>
<el-space>
<el-button @click="reset">重置</el-button>
<el-button type="primary" @click="submit"> 提交 </el-button>
</el-space>
</template>
</gi-form>
</gi-card>
</div>
</template>
<script lang="ts" setup>
import type { FormColumnItem, FormInstance } from 'gi-component'
import { ElMessage, ElTag } from 'element-plus'
import { computed, h, reactive, ref } from 'vue'
import { treeData } from './data'
const GiFormRef = ref<FormInstance | null>()
const disabled = ref(false)
const labelPosition = ref<any>('right')
const form = reactive({
name: '',
age: 18,
sex: '1',
address: '北京',
desc: '我是一个描述',
date: '2021-01-01',
datetime: '',
time: '12:00:00',
status: false,
star: 3,
radio: '吃饭',
remark: '',
inputTag: ['音乐', '电影'],
color: '#0077F7',
startTime: '',
endTime: '',
inputSearchId: '',
inputSearchName: ''
})
const columns = computed(() => {
return [
{
type: 'title',
label: '基本信息',
field: 'title-base'
},
{
type: 'input',
label: '姓名',
field: 'name',
required: true,
extra: '指标单位',
props: {
// 如果需要用到组件事件,直接在事件名前面拼接上on即可,例如input事件就写成onInput
// 其他事件同理,例如focus事件就写成onFocus,blur事件就写成onBlur,
onInput: () => {
ElMessage.success('输入了内容')
}
}
},
{
type: 'input',
label: '手机号',
field: 'phone',
required: true,
tip: '国内手机号',
formItemProps: { style: { alignItems: 'baseline' } },
slots: {
prepend: '+86'
}
},
{
type: 'select',
label: '性别',
field: 'sex',
props: {
options: [
{ label: '男', value: '1' },
{ label: '女', value: '2' }
]
}
},
{
type: 'input-number',
label: '数量',
field: 'num',
extra: () => h(ElTag, { type: 'danger' }, () => '个')
},
{
type: 'switch',
label: '启动',
labelRender: () => h('span', { style: { color: 'red' } }, '启动'),
field: 'status'
},
{
type: 'slider',
label: '滑块',
field: 'slider',
hide: () => form.status === true
},
{
type: 'title',
label: '其他信息',
field: 'title-other'
},
{
type: 'rate',
label: '评分',
field: 'star'
},
{
type: 'date-picker',
label: '日期',
field: 'date'
},
{
type: 'date-picker',
label: '日期时间',
field: 'datetime',
props: {
type: 'datetime'
}
},
{
type: 'checkbox-group',
label: '复选框',
field: 'checkbox',
props: {
options: [
{ label: '吃饭', value: '吃饭' },
{ label: '睡觉', value: '睡觉' },
{ label: '打豆豆', value: '打豆豆' }
]
}
},
{
type: 'radio-group',
label: '单选框',
field: 'radio',
props: {
options: [
{ label: '吃饭', value: '吃饭' },
{ label: '睡觉', value: '睡觉' },
{ label: '打豆豆', value: '打豆豆' }
]
}
},
{
type: 'tree-select',
label: '树形选择',
field: 'treeSelect',
tip: '这里是树形选择提示语',
props: {
data: treeData
},
formItemProps: { style: { alignItems: 'baseline' } }
},
{
type: 'input-tag',
label: '标签输入',
field: 'inputTag'
},
{
type: 'input-search',
label: '选择输入',
field: 'inputSearchId',
fieldName: 'inputSearchName',
props: {
onSearch: () => {
ElMessage.success('点击了搜索')
form.inputSearchId = '111,222,333'
form.inputSearchName = 'aaa,bbb,ccc'
},
onClear: () => {
ElMessage.success('点击了清除')
form.inputSearchId = ''
form.inputSearchName = ''
}
}
},
{
type: 'color-picker',
label: '颜色选择',
field: 'color'
},
{
type: 'cascader',
label: '级联',
field: 'cascader',
props: {
options: treeData
}
},
{
type: 'slot',
label: '插槽',
field: 'customSlot',
tip: '这里使用了自定义插槽'
},
{
type: 'slot',
label: '',
field: 'customSlot2',
span: 24,
formItemProps: { labelWidth: 0, class: 'hide-label' },
tip: '暂满宽度的插槽示例'
},
{
type: 'textarea',
label: '备注',
field: 'remark',
span: 24
},
{
type: 'slot',
label: '提交按钮',
field: 'btns',
span: 24,
formItemProps: {
labelWidth: 0,
class: 'hide-label',
style: { marginBottom: 0 }
}
}
] as FormColumnItem[]
})
async function submit() {
await GiFormRef.value?.formRef?.validate()
}
function reset() {
GiFormRef.value?.formRef?.resetFields()
}
</script>
<style lang="scss" scoped></style>搜索表单
查看代码
vue
<template>
<gi-form ref="GiFormRef" :model-value="form" :columns="columns" search :grid-item-props="{
span: { xs: 24, sm: 12, md: 12, lg: 12, xl: 8, xxl: 8 },
}" @search="search" @reset="reset" @update:model-value="Object.assign(form, $event)">
</gi-form>
</template>
<script lang="ts" setup>
import type { FormColumnItem, FormInstance } from 'gi-component'
import { ElMessage } from 'element-plus'
import { computed, reactive, ref } from 'vue'
const GiFormRef = ref<FormInstance | null>()
function search() {
ElMessage.success('点击了搜索')
}
function reset() {
ElMessage.info('点击了重置')
}
const form = reactive({})
const columns = computed(() => {
return [
{
type: 'input',
label: '姓名',
field: 'name'
},
{
type: 'input',
label: '手机号',
field: 'phone'
},
{
type: 'input',
label: '数量',
field: 'num'
},
{
type: 'input',
label: '评分',
field: 'star'
},
{
type: 'select',
label: '兴趣',
field: 'hobby',
props: {
options: [
{ label: '吃饭', value: '吃饭' },
{ label: '睡觉', value: '睡觉' },
{ label: '打豆豆', value: '打豆豆' }
]
}
},
{
type: 'date-picker',
label: '日期',
field: 'date'
},
{
type: 'date-picker',
label: '时间',
field: 'datetime',
props: {
type: 'datetime'
}
}
] as FormColumnItem[]
})
</script>
<style lang="scss" scoped></style>结合字典
查看代码
vue
<template>
<gi-form ref="GiFormRef" :model-value="form" :columns="columns" :grid-item-props="{
span: { xs: 24, sm: 12, md: 12, lg: 12, xl: 12, xxl: 12 },
}" @update:model-value="Object.assign(form, $event)">
</gi-form>
</template>
<script lang="ts" setup>
import type { FormColumnItem, FormInstance } from 'gi-component'
import { computed, reactive, ref } from 'vue'
import { useDictStore } from './useDictStore'
const GiFormRef = ref<FormInstance | null>()
const form = reactive({
status: '1'
})
const { dict } = useDictStore(['HOBBY', 'STATUS'])
const columns = computed(() => {
return [
{
type: 'select',
label: '性别',
field: 'sex',
dictCode: 'SEX' // 需要配置dictRequest
},
{
type: 'radio-group',
label: '状态',
field: 'status',
dictCode: 'STATUS' // 需要配置dictRequest
},
{
type: 'checkbox-group',
label: '兴趣',
field: 'hobby',
props: {
options: dict.HOBBY // 通过hooks获取字典数据
}
}
] as FormColumnItem[]
})
</script>表单控制
{
"name": {
"required": true,
"disabled": false,
"hidden": false
},
"phone": {
"required": true,
"disabled": false,
"hidden": false
}
}查看代码
vue
<template>
<div>
<gi-edit-table :columns="tableColumns" :data="data" size="small" class="gi-mb"></gi-edit-table>
<gi-form ref="formRef" :model-value="formData" :columns="columns" :fc="fc" :scroll-to-error="false"
@update:model-value="Object.assign(formData, $event)" />
<el-row justify="end">
<el-space>
<el-button @click="handleReset">重置</el-button>
<el-button type="primary" @click="handleSubmit">提交</el-button>
</el-space>
</el-row>
<pre class="doc-pre">{{ fc }}</pre>
</div>
</template>
<script setup lang="ts">
import type { EditTableColumnItem, FormColumnItem } from 'gi-component'
import { ElMessage } from 'element-plus'
import { computed, reactive, ref, useTemplateRef } from 'vue'
const tableColumns: EditTableColumnItem[] = [
{ label: '字段', prop: 'field' },
{ type: 'checkbox', label: '必填', prop: 'required' },
{ type: 'checkbox', label: '禁用', prop: 'disabled' },
{ type: 'checkbox', label: '隐藏', prop: 'hidden' }
]
const data = ref([
{
field: 'name',
required: true,
disabled: false,
hidden: false
},
{
field: 'phone',
required: true,
disabled: false,
hidden: false
}
])
const fc = computed(() => {
const obj: Record<string, { required: boolean, disabled: boolean, hidden: boolean }> = {}
data.value.forEach((item) => {
obj[item.field] = {
required: item.required,
disabled: item.disabled,
hidden: item.hidden
}
})
return obj
})
// 表单数据
const formData = reactive({
name: '',
phone: ''
})
// 表单列配置
const columns = [
{
type: 'input',
label: '姓名',
field: 'name'
},
{
type: 'input',
label: '手机号',
field: 'phone'
}
] as FormColumnItem[]
const formRef = useTemplateRef('formRef')
async function handleSubmit() {
try {
await formRef.value?.formRef?.validate?.()
ElMessage.success('提交成功')
} catch (error) {
ElMessage.error('提交失败')
}
}
function handleReset() {
formRef.value?.formRef?.resetFields?.()
}
</script>
<style lang="scss" scoped>
.header {
font-size: 12px;
}
</style>API 说明
Props
| 参数 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| modelValue / v-model | any | 表单数据对象 | - |
| columns | FormColumnItem[] | 表单项配置数组 | [] |
| gridProps | Grid.Props | 网格配置 | - |
| gridItemProps | GridItem.Props | 网格项默认配置 | { span: { xs: 24, sm: 24, md: 12 } } |
| search | boolean | 是否为搜索表单 | false |
| searchText | string | 搜索按钮文本 | '查询' |
| hideFoldBtn | boolean | 是否隐藏折叠按钮 | false |
| defaultCollapsed | boolean | 默认是否折叠 | - |
| suffix | boolean | 搜索表单时,搜索/重置/折叠按钮所在行是否作为 Grid 的 suffix 布局(靠右或单独一行) | true |
| fc | Record<string, { required: boolean; disabled: boolean; hidden: boolean }> | 表单控制属性 | - |
TIP
继承 el-form 的所有属性
Events
| 事件名 | 说明 | 参数 |
|---|---|---|
| update:modelValue | 表单数据更新事件 | value: any |
| search | 搜索事件 | - |
| reset | 重置事件 | - |
ColumnItem 配置
FormColumnItem 是表单项的配置接口,支持以下属性:
| 属性 | 类型 | 说明 |
|---|---|---|
| type | ColumnType | 表单项类型 |
| label | string | 标签文本 |
| labelRender | () => VNode | 标签渲染函数 |
| field | string | 字段名,用于绑定表单数据 |
| fieldName | string | 字段名称 |
| span | number | GridItemProps['span'] | 占用列数 |
| props | ColumnProps | 组件属性,根据不同的 type 有不同的配置 |
| formItemProps | FormItemProps | ElFormItem 的属性配置 |
| gridItemProps | GridItem.Props | GridItem 的属性配置 |
| required | boolean | 是否必填 |
| rules | FormItemRule[] | 验证规则 |
| hide | boolean | ((form: any) => boolean) | 是否隐藏,支持函数动态控制 |
| tip | string | 提示信息 |
| slotName | string | 插槽名称 |
| slots | ColumnSlots | 插槽配置 |
| extra | string | VNode | 右侧额外内容 |
