Form 表单
高性能订阅式表单,让表单开发变得简单。
何时使用
- 用于创建一个实体或收集信息。
- 需要对输入的数据类型进行校验时。
基本使用
基本的表单数据域控制展示,包含布局、初始化、验证、提交。
vue
<template>
<g-form
ref="formRef"
:model="formState"
name="basic"
:label-col="{ span: 8 }"
:wrapper-col="{ span: 16 }"
autocomplete="off"
@finish="onFinish"
@finishFailed="onFinishFailed"
>
<g-form-item
label="Username"
name="username"
:rules="[{ required: true, message: 'Please input your username!' }]"
>
<g-input v-model:value="formState.username" />
</g-form-item>
<g-form-item
label="Password"
name="password"
:rules="[{ required: true, message: 'Please input your password!' }]"
>
<g-input-password v-model:value="formState.password" />
</g-form-item>
<g-form-item name="remember" :wrapper-col="{ offset: 8, span: 16 }">
<g-checkbox v-model:checked="formState.remember">Remember me</g-checkbox>
</g-form-item>
<g-form-item :wrapper-col="{ offset: 8, span: 16 }">
<g-button type="primary" html-type="submit">Submit</g-button>
</g-form-item>
</g-form>
</template>
<script>
import { reactive } from 'vue'
export default {
setup() {
const formState = reactive({
username: '',
password: '',
remember: true,
})
const onFinish = (values) => {
console.log('Success:', values)
}
const onFinishFailed = (errorInfo) => {
console.log('Failed:', errorInfo)
}
return {
formState,
onFinish,
onFinishFailed,
}
},
}
</script>表单方法调用
通过 Form.useForm 对表单数据域进行交互。
vue
<template>
<g-form
:model="formState"
name="basic"
:label-col="{ span: 8 }"
:wrapper-col="{ span: 16 }"
autocomplete="off"
@finish="onFinish"
@finishFailed="onFinishFailed"
>
<g-form-item
label="Username"
name="username"
:rules="[{ required: true, message: 'Please input your username!' }]"
>
<g-input v-model:value="formState.username" />
</g-form-item>
<g-form-item
label="Password"
name="password"
:rules="[{ required: true, message: 'Please input your password!' }]"
>
<g-input-password v-model:value="formState.password" />
</g-form-item>
<g-form-item :wrapper-col="{ offset: 8, span: 16 }">
<g-button type="primary" html-type="submit">Submit</g-button>
<g-button style="margin-left: 10px;" @click="resetForm">Reset</g-button>
</g-form-item>
</g-form>
</template>
<script>
import { reactive } from 'vue'
import { Form } from '@/components'
export default {
setup() {
const { resetFields, validate, validateInfos } = Form.useForm(
reactive({
username: '',
password: '',
}),
reactive({
username: [{ required: true, message: 'Please input your username!' }],
password: [{ required: true, message: 'Please input your password!' }],
}),
)
const onFinish = (values) => {
console.log('Success:', values)
}
const onFinishFailed = (errorInfo) => {
console.log('Failed:', errorInfo)
}
const resetForm = () => {
resetFields()
}
return {
formState: validateInfos,
onFinish,
onFinishFailed,
resetForm,
}
},
}
</script>表单布局
表单有三种布局。
vue
<template>
<div>
<g-form
:layout="formLayout"
:model="formState"
name="basic"
:label-col="formLayout === 'horizontal' ? { span: 8 } : null"
:wrapper-col="formLayout === 'horizontal' ? { span: 16 } : null"
>
<g-form-item label="Form Layout" name="layout">
<g-radio-group v-model:value="formLayout">
<g-radio-button value="horizontal">Horizontal</g-radio-button>
<g-radio-button value="vertical">Vertical</g-radio-button>
<g-radio-button value="inline">Inline</g-radio-button>
</g-radio-group>
</g-form-item>
<g-form-item label="Field A">
<g-input v-model:value="formState.fieldA" placeholder="input placeholder" />
</g-form-item>
<g-form-item label="Field B">
<g-input v-model:value="formState.fieldB" placeholder="input placeholder" />
</g-form-item>
<g-form-item>
<g-button type="primary">Submit</g-button>
</g-form-item>
</g-form>
</div>
</template>
<script>
import { reactive, ref } from 'vue'
export default {
setup() {
const formLayout = ref('horizontal')
const formState = reactive({
fieldA: '',
fieldB: '',
})
return {
formLayout,
formState,
}
},
}
</script>表单验证
我们为表单控件定义了三种校验状态,你可以通过 validateStatus 属性为 g-form-item 设置校验状态。
vue
<template>
<g-form
:model="formState"
name="validate_other"
:label-col="{ span: 6 }"
:wrapper-col="{ span: 14 }"
>
<g-form-item
label="Fail"
validate-status="error"
help="Should be combination of numbers & alphabets"
>
<g-input v-model:value="formState.userName" placeholder="unavailable choice" />
</g-form-item>
<g-form-item label="Warning" validate-status="warning">
<g-input v-model:value="formState.password" placeholder="Warning" />
</g-form-item>
<g-form-item
label="Validating"
validate-status="validating"
help="The information is being validated..."
>
<g-input v-model:value="formState.confirmPassword" placeholder="I'm the content is being validated" />
</g-form-item>
<g-form-item label="Success" validate-status="success">
<g-input v-model:value="formState.age" placeholder="I'm the content" />
</g-form-item>
<g-form-item label="Warning" validate-status="warning">
<g-input v-model:value="formState.email" placeholder="Warning" />
</g-form-item>
<g-form-item
label="Fail"
validate-status="error"
help="Should have something"
>
<g-date-picker style="width: 100%" />
</g-form-item>
</g-form>
</template>
<script>
import { reactive } from 'vue'
export default {
setup() {
const formState = reactive({
userName: '',
password: '',
confirmPassword: '',
age: '',
email: '',
})
return {
formState,
}
},
}
</script>动态增减表单项
动态增加、减少表单项。
vue
<template>
<g-form
ref="formRef"
name="dynamic_form_nest_item"
:model="dynamicValidateForm"
@finish="onFinish"
>
<g-space
v-for="(user, index) in dynamicValidateForm.users"
:key="user.key"
style="display: flex; margin-bottom: 8px"
align="baseline"
>
<g-form-item
:name="['users', index, 'first']"
:rules="{
required: true,
message: 'Missing first name',
}"
>
<g-input v-model:value="user.first" placeholder="First Name" />
</g-form-item>
<g-form-item
:name="['users', index, 'last']"
:rules="{
required: true,
message: 'Missing last name',
}"
>
<g-input v-model:value="user.last" placeholder="Last Name" />
</g-form-item>
<g-icon
type="minus-circle-o"
class="dynamic-delete-button"
:disabled="dynamicValidateForm.users.length === 1"
@click="removeUser(user)"
/>
</g-space>
<g-form-item>
<g-button type="dashed" style="width: 60%" @click="addUser">
<g-icon type="plus" /> Add field
</g-button>
</g-form-item>
<g-form-item>
<g-button type="primary" html-type="submit">Submit</g-button>
</g-form-item>
</g-form>
</template>
<script>
import { reactive } from 'vue'
export default {
setup() {
const dynamicValidateForm = reactive({
users: [
{
first: '',
last: '',
key: Date.now(),
},
],
})
const removeUser = (item) => {
let index = dynamicValidateForm.users.indexOf(item)
if (index !== -1) {
dynamicValidateForm.users.splice(index, 1)
}
}
const addUser = () => {
dynamicValidateForm.users.push({
first: '',
last: '',
key: Date.now(),
})
}
const onFinish = (values) => {
console.log('Received values of form:', values)
}
return {
dynamicValidateForm,
onFinish,
removeUser,
addUser,
}
},
}
</script>
<style>
.dynamic-delete-button {
cursor: pointer;
position: relative;
top: 4px;
font-size: 24px;
color: #999;
transition: all 0.3s;
}
.dynamic-delete-button:hover {
color: #777;
}
.dynamic-delete-button[disabled] {
cursor: not-allowed;
opacity: 0.5;
}
</style>复杂一点的控件
这里演示 g-form-item 内有多个元素的使用方式。
vue
<template>
<g-form
:model="formState"
name="complex-form"
:label-col="{ span: 6 }"
:wrapper-col="{ span: 18 }"
>
<g-form-item label="Price">
<g-input-group compact>
<g-select
v-model:value="formState.priceType"
style="width: 30%"
>
<g-select-option value="RMB">RMB</g-select-option>
<g-select-option value="Dollar">Dollar</g-select-option>
</g-select>
<g-input
v-model:value="formState.price"
style="width: 70%"
/>
</g-input-group>
</g-form-item>
<g-form-item label="Website">
<g-input-group compact>
<g-select
v-model:value="formState.protocol"
style="width: 20%"
>
<g-select-option value="http://">http://</g-select-option>
<g-select-option value="https://">https://</g-select-option>
</g-select>
<g-input
v-model:value="formState.website"
style="width: 80%"
placeholder="mysite"
/>
</g-input-group>
</g-form-item>
</g-form>
</template>
<script>
import { reactive } from 'vue'
export default {
setup() {
const formState = reactive({
priceType: 'RMB',
price: '',
protocol: 'http://',
website: '',
})
return {
formState,
}
},
}
</script>弹出层中的新建表单
当用户访问一个展示了某个列表的页面,想新建一项但又不想跳转页面时,可以用 Modal 弹出一个表单,用户填写必要信息后创建新的项。
vue
<template>
<div>
<g-button type="primary" @click="showModal">
New Collection
</g-button>
<g-modal
v-model:visible="visible"
title="Create a new collection"
ok-text="Create"
cancel-text="Cancel"
@ok="onCreate"
>
<g-form
ref="formRef"
:model="form"
layout="vertical"
name="form_in_modal"
>
<g-form-item
name="name"
label="Name"
:rules="[{ required: true, message: 'Please input the name of collection!' }]"
>
<g-input v-model:value="form.name" />
</g-form-item>
<g-form-item name="description" label="Description">
<g-input v-model:value="form.description" type="textarea" />
</g-form-item>
<g-form-item name="modifier" class="collection-create-form_last-form-item">
<g-radio-group v-model:value="form.modifier">
<g-radio value="public">Public</g-radio>
<g-radio value="private">Private</g-radio>
</g-radio-group>
</g-form-item>
</g-form>
</g-modal>
</div>
</template>
<script>
import { reactive, ref } from 'vue'
export default {
setup() {
const formRef = ref()
const visible = ref(false)
const form = reactive({
name: '',
description: '',
modifier: 'public',
})
const showModal = () => {
visible.value = true
}
const onCreate = () => {
formRef.value
.validate()
.then(() => {
console.log('values', form, toRaw(form))
visible.value = false
resetForm()
})
.catch((info) => {
console.log('Validate Failed:', info)
})
}
const resetForm = () => {
formRef.value.resetFields()
}
return {
formRef,
visible,
form,
showModal,
onCreate,
}
},
}
</script>API
Form
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|---|---|---|---|---|
| colon | 配置 Form.Item 的 colon 的默认值 | boolean | true | |
| hideRequiredMark | 隐藏所有表单项的必选标记 | boolean | false | |
| labelAlign | label 标签的文本对齐方式 | left | right | right | |
| labelCol | label 标签布局,同 <Col> 组件,设置 span offset 值,如 {span: 3, offset: 12} 或 sm: {span: 3, offset: 12} | object | - | |
| labelWrap | label 标签的文本换行方式 | boolean | false | 4.0.0 |
| layout | 表单布局 | horizontal | vertical | inline | horizontal | |
| model | 表单数据对象 | object | - | |
| name | 表单名称,会作为表单字段 id 前缀使用 | string | - | |
| noStyle | 为 true 时不带样式,作为纯字段控件使用 | boolean | false | |
| rules | 表单验证规则 | object | - | |
| scrollToFirstError | 提交失败自动滚动到第一个错误字段 | boolean | Options | false | |
| size | 设置字段组件的尺寸(仅限 antd 的表单控件) | small | middle | large | - | |
| validateOnRuleChange | 是否在 rules 属性改变后立即触发一次验证 | boolean | true | |
| validateTrigger | 统一设置字段校验规则 | string | string[] | change | 1.5.0 |
| wrapperCol | 需要为输入控件设置布局样式时,使用该属性,用法同 labelCol | object | - |
Form 事件
| 事件名称 | 说明 | 回调参数 |
|---|---|---|
| finish | 提交表单且数据验证成功后回调事件 | function(values) |
| finishFailed | 提交表单且数据验证失败后回调事件 | function({ values, errorFields, outOfDate }) |
| submit | 数据验证成功后回调事件 | function(e) |
| validate | 任一表单项被校验后触发 | function(name, status, errorMsgs) |
Form.Item
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|---|---|---|---|---|
| autoLink | 是否自动关联表单域,对于大部分情况都可以使用自动关联,如果不满足自动关联的条件,可以手动关联,参见下方注意事项 | boolean | true | |
| colon | 配合 label 属性使用,表示是否显示 label 后面的冒号 | boolean | true | |
| extra | 额外的提示信息,和 help 类似,当需要错误信息和提示文案同时出现时,可以使用这个。 | string | slot | - | |
| hasFeedback | 配合 validateStatus 属性使用,展示校验状态图标,建议只配合 Input 组件使用 | boolean | false | |
| help | 提示信息,如不设置,则会根据校验规则自动生成 | string | slot | - | |
| htmlFor | 设置子元素 label htmlFor 属性 | string | - | |
| label | label 标签的文本 | string | slot | - | |
| labelAlign | 标签文本对齐方式 | left | right | right | |
| labelCol | label 标签布局,同 <Col> 组件,设置 span offset 值,如 {span: 3, offset: 12} 或 sm: {span: 3, offset: 12} | object | - | |
| name | 表单域 model 字段,在使用 validate、resetFields 方法的情况下,该属性是必填的 | string | - | |
| required | 是否必填,如不设置,则会根据校验规则自动生成 | boolean | false | |
| rules | 表单验证规则,设置字段的校验逻辑。点击此处查看示例 | object | array | - | |
| validateFirst | 当某一规则校验不通过时,是否停止剩下的规则的校验 | boolean | false | |
| validateStatus | 校验状态,如不设置,则会根据校验规则自动生成,可选:'success' 'warning' 'error' 'validating' | string | - | |
| validateTrigger | 设置字段校验的时机 | string | string[] | change | |
| wrapperCol | 需要为输入控件设置布局样式时,使用该属性,用法同 labelCol | object | - |
Form.useForm()
Form.useForm 通过 composition api 的方式来管理表单数据域。
js
import { Form } from 'ant-design-vue';
const useForm = Form.useForm;
useForm(modelRef, rulesRef, [options])modelRef
表单数据,可以是 reactive 或者 ref 类型
rulesRef
表单校验规则,可以是 reactive 或者 ref 类型
options
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| immediate | 是否在创建时立即校验 | boolean | true |
| deep | 是否深度监听,对于对象类型字段,在其属性变化时也会触发校验 | boolean | true |
| validateOnRuleChange | 是否在 rules 属性改变后立即触发一次验证 | boolean | true |
| debounce | 防抖处理,与 lodash.debounce 完全一致 | object | - |
返回值
| 参数 | 说明 | 类型 |
|---|---|---|
| resetFields | 重置表单 | (name?: NamePath) => void |
| clearValidate | 清理校验 | (name?: NamePath) => void |
| validate | 校验表单 | (name?: NamePath) => Promise |
| validateInfos | 校验信息 | ComputedRef<{ [key: string]: ValidateInfo }> |
validateInfos
| 参数 | 说明 | 类型 |
|---|---|---|
| autoLink | 是否自动关联,如果为 false,则需要手动设置 FormItem 的 validateStatus、help、hasFeedback 等属性。 | boolean |
| required | 是否必填 | boolean |
| validateStatus | 校验状态 | 'success' | 'warning' | 'error' | 'validating' |
| help | 校验信息 | string |