组件
表单
收集和验证表单数据。
使用
使用 Form 组件通过 schema 库(如 Yup、Zod、Joi、Valibot、Superstruct 或你自己的验证逻辑)来验证表单数据。
它与 FormGroup 组件配合使用,可以自动在表单元素周围显示错误消息。
表单组件需要两个 props
state
- 一个包含表单状态的响应式对象。schema
- 来自验证库(如 Yup、Zod、Joi、Valibot 或 Superstruct)的 schema 对象。
请注意,默认情况下 不包含任何验证库,因此请确保 安装所需的库。
<script setup lang="ts">
import { object, string, type InferType } from 'yup'
import type { FormSubmitEvent } from '#ui/types'
const schema = object({
email: string().email('Invalid email').required('Required'),
password: string()
.min(8, 'Must be at least 8 characters')
.required('Required')
})
type Schema = InferType<typeof schema>
const state = reactive({
email: undefined,
password: undefined
})
async function onSubmit(event: FormSubmitEvent<Schema>) {
// Do something with event.data
console.log(event.data)
}
</script>
<template>
<UForm :schema="schema" :state="state" class="space-y-4" @submit="onSubmit">
<UFormGroup label="Email" name="email">
<UInput v-model="state.email" />
</UFormGroup>
<UFormGroup label="Password" name="password">
<UInput v-model="state.password" type="password" />
</UFormGroup>
<UButton type="submit">
Submit
</UButton>
</UForm>
</template>
自定义验证
使用 validate
prop 应用你自己的验证逻辑。
验证函数必须返回一个错误列表,其中包含以下属性
message
- 要显示的错误消息。path
- 与name
属性相对应的表单元素的路径。
请注意,它可以与
schema
prop 一起使用,以处理复杂的用例。<script setup lang="ts">
import type { FormError, FormSubmitEvent } from '#ui/types'
const state = reactive({
email: undefined,
password: undefined
})
const validate = (state: any): FormError[] => {
const errors = []
if (!state.email) errors.push({ path: 'email', message: 'Required' })
if (!state.password) errors.push({ path: 'password', message: 'Required' })
return errors
}
async function onSubmit(event: FormSubmitEvent<any>) {
// Do something with data
console.log(event.data)
}
</script>
<template>
<UForm :validate="validate" :state="state" class="space-y-4" @submit="onSubmit">
<UFormGroup label="Email" name="email">
<UInput v-model="state.email" />
</UFormGroup>
<UFormGroup label="Password" name="password">
<UInput v-model="state.password" type="password" />
</UFormGroup>
<UButton type="submit">
Submit
</UButton>
</UForm>
</template>
这也可以用于与其他验证库集成。以下是用 Vuelidate 的示例
<script setup lang="ts">
import useVuelidate from '@vuelidate/core'
const props = defineProps({
rules: { type: Object, required: true },
model: { type: Object, required: true }
})
const form = ref();
const v = useVuelidate(props.rules, props.model)
async function validateWithVuelidate() {
v.value.$touch()
await v.value.$validate()
return v.value.$errors.map((error) => ({
message: error.$message,
path: error.$propertyPath,
}))
}
defineExpose({
validate: async () => {
await form.value.validate()
}
})
</script>
<template>
<UForm ref="form" :state="model" :validate="validateWithVuelidate">
<slot />
</UForm>
</template>
后端验证
如果需要,你可以在表单提交后手动设置错误。为此,只需使用 form.setErrors
函数设置所需的错误即可。
<script setup lang="ts">
import type { Form, FormSubmitEvent } from '#ui/types'
interface Schema {
email?: string
password?: string
}
const state = reactive<Schema>({
email: undefined,
password: undefined
})
const form = ref<Form<Schema>>()
async function onSubmit (event: FormSubmitEvent<Schema>) {
form.value!.clear()
try {
const response = await $fetch('...')
// ...
} catch (err) {
if (err.statusCode === 422) {
form.value!.setErrors(err.data.errors.map((err) => ({
// Map validation errors to { path: string, message: string }
message: err.message,
path: err.path,
})))
}
}
}
</script>
<template>
<UForm ref="form" :state="state" @submit="onSubmit">
<UFormGroup label="Email" name="email">
<UInput v-model="state.email" />
</UFormGroup>
<UFormGroup label="Password" name="password">
<UInput v-model="state.password" type="password" />
</UFormGroup>
<UButton type="submit">
Submit
</UButton>
</UForm>
</template>
输入事件
Form 组件在 submit
、input
、blur
或 change
事件发生时自动触发验证。
这确保了只要用户与表单元素交互,就会显示任何错误。你可以使用 validate-on
prop 控制验证发生的时机。
请注意,
input
事件直到初始 blur
事件发生后才会触发。这是为了防止在用户键入时表单被验证。可以通过在 eager-validation
prop 上将 FormGroup
设置为 true
来覆盖此行为。错误事件
你可以监听 @error
事件来处理错误。此事件在表单提交时触发,并包含一个 FormError
对象数组,其中包含以下字段
id
- 表单元素的标识符。path
- 与name
相匹配的表单元素的路径。message
- 要显示的错误消息。
以下是一个示例,它在表单提交后将焦点设置到第一个包含错误的输入元素上
<script setup lang="ts">
import type { FormError, FormErrorEvent, FormSubmitEvent } from '#ui/types'
const state = reactive({
email: undefined,
password: undefined
})
const validate = (state: any): FormError[] => {
const errors = []
if (!state.email) errors.push({ path: 'email', message: 'Required' })
if (!state.password) errors.push({ path: 'password', message: 'Required' })
return errors
}
async function onSubmit(event: FormSubmitEvent<any>) {
// Do something with data
console.log(event.data)
}
async function onError(event: FormErrorEvent) {
const element = document.getElementById(event.errors[0].id)
element?.focus()
element?.scrollIntoView({ behavior: 'smooth', block: 'center' })
}
</script>
<template>
<UForm :validate="validate" :state="state" class="space-y-4" @submit="onSubmit" @error="onError">
<UFormGroup label="Email" name="email">
<UInput v-model="state.email" />
</UFormGroup>
<UFormGroup label="Password" name="password">
<UInput v-model="state.password" type="password" />
</UFormGroup>
<UButton type="submit">
Submit
</UButton>
</UForm>
</template>
Props
state必需
Record<string, any>
schema
ZodType<any, ZodTypeDef, any> | ObjectSchema<any, AnyObject, any, ""> | AnySchema<any> | BaseSchema<any, any> | ... 7 more ... | Struct<...>
undefined
validate
((state: any) => Promise<FormError<string>[]>) | ((state: any) => FormError<string>[])
[]
validateOn
FormEventType[]
["blur", "input", "change", "submit"]
API
通过模板 ref 访问组件时,可以使用以下方法
submit ()
Promise<void>
触发表单提交。
validate (path?: string | string[], opts: { silent?: boolean })
Promise<T>
触发表单验证。除非将 opts.silent
设置为 true,否则会引发任何错误。
clear (path?: string)
清除与特定路径关联的表单错误。如果未提供路径,则清除所有表单错误。
getErrors (path?: string)
FormError[]
检索与特定路径关联的表单错误。如果未提供路径,则返回所有表单错误。
setErrors (errors: FormError[], path?: string)
为给定路径设置表单错误。如果未提供路径,则覆盖所有错误。
errors
Ref<FormError[]>
对包含验证错误的数组的引用。使用它来访问或操作错误信息。