Form
Utilisation
Utilisez le composant Formulaire pour valider les données de formulaire à l'aide de n'importe quelle bibliothèque de validation prenant en charge [xhttps://github.com/standard-schema/standard-schema), telle que [Valibotxph006https://github.com/fabian-hiller/valibot), Zod, [Reglesph014xph015), [Yupxph018https://github.com/jquense/yup), Joi ou Superstruct ou votre propre logique de validation
Il fonctionne avec le composant FormField pour afficher automatiquement les messages d'erreur autour des éléments de formulaire.
Validation du schéma
Cela nécessite deux props:
state-un objet réactif contenant l'état de la forme.schema-tout schéma [Standard ou Superstruct.
<script setup lang="ts">
import * as v from 'valibot'
import type { FormSubmitEvent } from '@nuxt/ui'
const schema = v.object({
email: v.pipe(v.string(), v.email('Invalid email')),
password: v.pipe(v.string(), v.minLength(8, 'Must be at least 8 characters'))
})
type Schema = v.InferOutput<typeof schema>
const state = reactive({
email: '',
password: ''
})
const toast = useToast()
async function onSubmit(event: FormSubmitEvent<Schema>) {
toast.add({ title: 'Success', description: 'The form has been submitted.', color: 'success' })
console.log(event.data)
}
</script>
<template>
<UForm :schema="schema" :state="state" class="space-y-4" @submit="onSubmit">
<UFormField label="Email" name="email">
<UInput v-model="state.email" />
</UFormField>
<UFormField label="Password" name="password">
<UInput v-model="state.password" type="password" />
</UFormField>
<UButton type="submit">
Submit
</UButton>
</UForm>
</template>
<script setup lang="ts">
import { reactive } from 'vue'
import * as v from 'valibot'
import type { FormSubmitEvent } from '@nuxt/ui'
const schema = v.object({
email: v.pipe(v.string(), v.email('Invalid email')),
password: v.pipe(v.string(), v.minLength(8, 'Must be at least 8 characters'))
})
type Schema = v.InferOutput<typeof schema>
const state = reactive({
email: '',
password: ''
})
const toast = useToast()
async function onSubmit(event: FormSubmitEvent<Schema>) {
toast.add({ title: 'Success', description: 'The form has been submitted.', color: 'success' })
console.log(event.data)
}
</script>
<template>
<UForm :schema="schema" :state="state" class="space-y-4" @submit="onSubmit">
<UFormField label="Email" name="email">
<UInput v-model="state.email" />
</UFormField>
<UFormField label="Password" name="password">
<UInput v-model="state.password" type="password" />
</UFormField>
<UButton type="submit">
Submit
</UButton>
</UForm>
</template>
<script setup lang="ts">
import * as z from 'zod'
import type { FormSubmitEvent } from '@nuxt/ui'
const schema = z.object({
email: z.email('Invalid email'),
password: z.string('Password is required').min(8, 'Must be at least 8 characters')
})
type Schema = z.output<typeof schema>
const state = reactive<Partial<Schema>>({
email: undefined,
password: undefined
})
const toast = useToast()
async function onSubmit(event: FormSubmitEvent<Schema>) {
toast.add({ title: 'Success', description: 'The form has been submitted.', color: 'success' })
console.log(event.data)
}
</script>
<template>
<UForm :schema="schema" :state="state" class="space-y-4" @submit="onSubmit">
<UFormField label="Email" name="email">
<UInput v-model="state.email" />
</UFormField>
<UFormField label="Password" name="password">
<UInput v-model="state.password" type="password" />
</UFormField>
<UButton type="submit">
Submit
</UButton>
</UForm>
</template>
<script setup lang="ts">
import { reactive } from 'vue'
import * as z from 'zod'
import type { FormSubmitEvent } from '@nuxt/ui'
const schema = z.object({
email: z.email('Invalid email'),
password: z.string('Password is required').min(8, 'Must be at least 8 characters')
})
type Schema = z.output<typeof schema>
const state = reactive<Partial<Schema>>({
email: undefined,
password: undefined
})
const toast = useToast()
async function onSubmit(event: FormSubmitEvent<Schema>) {
toast.add({ title: 'Success', description: 'The form has been submitted.', color: 'success' })
console.log(event.data)
}
</script>
<template>
<UForm :schema="schema" :state="state" class="space-y-4" @submit="onSubmit">
<UFormField label="Email" name="email">
<UInput v-model="state.email" />
</UFormField>
<UFormField label="Password" name="password">
<UInput v-model="state.password" type="password" />
</UFormField>
<UButton type="submit">
Submit
</UButton>
</UForm>
</template>
<script setup lang="ts">
import { useRegle, type InferInput } from '@regle/core'
import { required, email, minLength, withMessage } from '@regle/rules'
import type { FormSubmitEvent } from '@nuxt/ui'
const { r$ } = useRegle({ email: '', password: '' }, {
email: { required, email: withMessage(email, 'Invalid email') },
password: { required, minLength: withMessage(minLength(8), 'Must be at least 8 characters') }
})
type Schema = InferInput<typeof r$>
const toast = useToast()
async function onSubmit(event: FormSubmitEvent<Schema>) {
toast.add({ title: 'Success', description: 'The form has been submitted.', color: 'success' })
console.log(event.data)
}
</script>
<template>
<UForm :schema="r$" :state="r$.$value" class="space-y-4" @submit="onSubmit">
<UFormField label="Email" name="email">
<UInput v-model="r$.$value.email" />
</UFormField>
<UFormField label="Password" name="password">
<UInput v-model="r$.$value.password" type="password" />
</UFormField>
<UButton type="submit">
Submit
</UButton>
</UForm>
</template>
<script setup lang="ts">
import { object, string } from 'yup'
import type { InferType } from 'yup'
import type { FormSubmitEvent } from '@nuxt/ui'
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
})
const toast = useToast()
async function onSubmit(event: FormSubmitEvent<Schema>) {
toast.add({ title: 'Success', description: 'The form has been submitted.', color: 'success' })
console.log(event.data)
}
</script>
<template>
<UForm :schema="schema" :state="state" class="space-y-4" @submit="onSubmit">
<UFormField label="Email" name="email">
<UInput v-model="state.email" />
</UFormField>
<UFormField label="Password" name="password">
<UInput v-model="state.password" type="password" />
</UFormField>
<UButton type="submit">
Submit
</UButton>
</UForm>
</template>
<script setup lang="ts">
import { reactive } from 'vue'
import { object, string } from 'yup'
import type { InferType } from 'yup'
import type { FormSubmitEvent } from '@nuxt/ui'
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
})
const toast = useToast()
async function onSubmit(event: FormSubmitEvent<Schema>) {
toast.add({ title: 'Success', description: 'The form has been submitted.', color: 'success' })
console.log(event.data)
}
</script>
<template>
<UForm :schema="schema" :state="state" class="space-y-4" @submit="onSubmit">
<UFormField label="Email" name="email">
<UInput v-model="state.email" />
</UFormField>
<UFormField label="Password" name="password">
<UInput v-model="state.password" type="password" />
</UFormField>
<UButton type="submit">
Submit
</UButton>
</UForm>
</template>
<script setup lang="ts">
import Joi from 'joi'
import type { FormSubmitEvent } from '@nuxt/ui'
const schema = Joi.object({
email: Joi.string().required(),
password: Joi.string()
.min(8)
.required()
})
const state = reactive({
email: undefined,
password: undefined
})
const toast = useToast()
async function onSubmit(event: FormSubmitEvent<typeof state>) {
toast.add({ title: 'Success', description: 'The form has been submitted.', color: 'success' })
console.log(event.data)
}
</script>
<template>
<UForm :schema="schema" :state="state" class="space-y-4" @submit="onSubmit">
<UFormField label="Email" name="email">
<UInput v-model="state.email" />
</UFormField>
<UFormField label="Password" name="password">
<UInput v-model="state.password" type="password" />
</UFormField>
<UButton type="submit">
Submit
</UButton>
</UForm>
</template>
<script setup lang="ts">
import { reactive } from 'vue'
import Joi from 'joi'
import type { FormSubmitEvent } from '@nuxt/ui'
const schema = Joi.object({
email: Joi.string().required(),
password: Joi.string()
.min(8)
.required()
})
const state = reactive({
email: undefined,
password: undefined
})
const toast = useToast()
async function onSubmit(event: FormSubmitEvent<typeof state>) {
toast.add({ title: 'Success', description: 'The form has been submitted.', color: 'success' })
console.log(event.data)
}
</script>
<template>
<UForm :schema="schema" :state="state" class="space-y-4" @submit="onSubmit">
<UFormField label="Email" name="email">
<UInput v-model="state.email" />
</UFormField>
<UFormField label="Password" name="password">
<UInput v-model="state.password" type="password" />
</UFormField>
<UButton type="submit">
Submit
</UButton>
</UForm>
</template>
<script setup lang="ts">
import { object, string, nonempty, refine } from 'superstruct'
import type { Infer } from 'superstruct'
import type { FormSubmitEvent } from '@nuxt/ui'
const schema = object({
email: nonempty(string()),
password: refine(string(), 'Password', (value) => {
if (value.length >= 8) return true
return 'Must be at least 8 characters'
})
})
const state = reactive({
email: '',
password: ''
})
type Schema = Infer<typeof schema>
async function onSubmit(event: FormSubmitEvent<Schema>) {
console.log(event.data)
}
</script>
<template>
<UForm :schema="schema" :state="state" class="space-y-4" @submit="onSubmit">
<UFormField label="Email" name="email">
<UInput v-model="state.email" />
</UFormField>
<UFormField label="Password" name="password">
<UInput v-model="state.password" type="password" />
</UFormField>
<UButton type="submit">
Submit
</UButton>
</UForm>
</template>
<script setup lang="ts">
import { reactive } from 'vue'
import { object, string, nonempty, refine } from 'superstruct'
import type { Infer } from 'superstruct'
import type { FormSubmitEvent } from '@nuxt/ui'
const schema = object({
email: nonempty(string()),
password: refine(string(), 'Password', (value) => {
if (value.length >= 8) return true
return 'Must be at least 8 characters'
})
})
const state = reactive({
email: '',
password: ''
})
type Schema = Infer<typeof schema>
async function onSubmit(event: FormSubmitEvent<Schema>) {
console.log(event.data)
}
</script>
<template>
<UForm :schema="schema" :state="state" class="space-y-4" @submit="onSubmit">
<UFormField label="Email" name="email">
<UInput v-model="state.email" />
</UFormField>
<UFormField label="Password" name="password">
<UInput v-model="state.password" type="password" />
</UFormField>
<UButton type="submit">
Submit
</UButton>
</UForm>
</template>
Validation personnalisée
Utilisez le prop validate pour appliquer votre propre logique de validation.
La fonction de validation doit renvoyer une liste d'erreurs avec les attributs suivants:
message: message d'erreur à afficher.name-lenameduFormFieldà qui envoyer l'erreur.
schema pour gérer des cas d'utilisation complexes.<script setup lang="ts">
import type { FormError, FormSubmitEvent } from '@nuxt/ui'
const state = reactive({
email: undefined,
password: undefined
})
type Schema = typeof state
function validate(state: Partial<Schema>): FormError[] {
const errors = []
if (!state.email) errors.push({ name: 'email', message: 'Required' })
if (!state.password) errors.push({ name: 'password', message: 'Required' })
return errors
}
const toast = useToast()
async function onSubmit(event: FormSubmitEvent<Schema>) {
toast.add({ title: 'Success', description: 'The form has been submitted.', color: 'success' })
console.log(event.data)
}
</script>
<template>
<UForm :validate="validate" :state="state" class="space-y-4" @submit="onSubmit">
<UFormField label="Email" name="email">
<UInput v-model="state.email" />
</UFormField>
<UFormField label="Password" name="password">
<UInput v-model="state.password" type="password" />
</UFormField>
<UButton type="submit">
Submit
</UButton>
</UForm>
</template>
<script setup lang="ts">
import { reactive } from 'vue'
import type { FormError, FormSubmitEvent } from '@nuxt/ui'
const state = reactive({
email: undefined,
password: undefined
})
type Schema = typeof state
function validate(state: Partial<Schema>): FormError[] {
const errors = []
if (!state.email) errors.push({ name: 'email', message: 'Required' })
if (!state.password) errors.push({ name: 'password', message: 'Required' })
return errors
}
const toast = useToast()
async function onSubmit(event: FormSubmitEvent<Schema>) {
toast.add({ title: 'Success', description: 'The form has been submitted.', color: 'success' })
console.log(event.data)
}
</script>
<template>
<UForm :validate="validate" :state="state" class="space-y-4" @submit="onSubmit">
<UFormField label="Email" name="email">
<UInput v-model="state.email" />
</UFormField>
<UFormField label="Password" name="password">
<UInput v-model="state.password" type="password" />
</UFormField>
<UButton type="submit">
Submit
</UButton>
</UForm>
</template>
Rapport d'erreur ### Error
Les erreurs sont associées au champ FormField correspondant en utilisant sa prop. name Une erreur sur le champ email est affichée par <FormField name="email">.
Un schéma comme { user: z.object({ email: z.string() }) } sera appliqué à <FormField name="user.email">.
tags.0, tags.1) et ne correspondent pas à <FormField name="tags"> par name seul. Utilisez la prop error-pattern avec une expression rationnelle comme /^tags\..+/ pour les capturer. Ceci est particulièrement utile pour les composants comme InputTags.<script setup lang="ts">
import * as z from 'zod'
import type { FormSubmitEvent } from '@nuxt/ui'
const schema = z.object({
email: z.email('Invalid email'),
tags: z.array(z.string().regex(/^[a-z-]+$/, 'Lowercase letters and dashes only')).min(1, 'Please add at least one tag')
})
type Schema = z.output<typeof schema>
const state = reactive<Partial<Schema>>({
email: undefined,
tags: []
})
const toast = useToast()
async function onSubmit(event: FormSubmitEvent<Schema>) {
toast.add({ title: 'Success', description: 'The form has been submitted.', color: 'success' })
console.log(event.data)
}
</script>
<template>
<UForm :schema="schema" :state="state" class="space-y-4" @submit="onSubmit">
<UFormField label="Email" name="email">
<UInput v-model="state.email" />
</UFormField>
<UFormField label="Tags" name="tags" :error-pattern="/^tags\..+/">
<UInputTags v-model="state.tags" />
</UFormField>
<UButton type="submit">
Submit
</UButton>
</UForm>
</template>
<script setup lang="ts">
import { reactive } from 'vue'
import * as z from 'zod'
import type { FormSubmitEvent } from '@nuxt/ui'
const schema = z.object({
email: z.email('Invalid email'),
tags: z.array(z.string().regex(/^[a-z-]+$/, 'Lowercase letters and dashes only')).min(1, 'Please add at least one tag')
})
type Schema = z.output<typeof schema>
const state = reactive<Partial<Schema>>({
email: undefined,
tags: []
})
const toast = useToast()
async function onSubmit(event: FormSubmitEvent<Schema>) {
toast.add({ title: 'Success', description: 'The form has been submitted.', color: 'success' })
console.log(event.data)
}
</script>
<template>
<UForm :schema="schema" :state="state" class="space-y-4" @submit="onSubmit">
<UFormField label="Email" name="email">
<UInput v-model="state.email" />
</UFormField>
<UFormField label="Tags" name="tags" :error-pattern="/^tags\..+/">
<UInputTags v-model="state.tags" />
</UFormField>
<UButton type="submit">
Submit
</UButton>
</UForm>
</template>
Input Événements
Le composant Formulaire déclenche automatiquement la validation lorsqu 'une entrée émet un événement input, change ou blur.
- La validation sur
inputse produit **as vous tapez ph137x. - Validation sur
changese produit lorsque vous commit à une value. La validation surblurse produit lorsqu 'une entrée perd le focus.
Vous pouvez contrôler quand la validation se produit en utilisant le prop validate-on.
useFormField pour implémenter cela dans vos propres composants.Événement ### Error
Cet événement est déclenché lorsque le formulaire est envoyé et contient un tableau d'objets FormError avec les champs suivants:
id-l'entréeid.name-lenameduFormFieldmessage-le message d'erreur à afficher.
Voici un exemple qui focalise le premier élément d'entrée avec une erreur après la soumission du formulaire:
<script setup lang="ts">
import type { FormError, FormErrorEvent, FormSubmitEvent } from '@nuxt/ui'
const state = reactive({
email: undefined,
password: undefined
})
type Schema = typeof state
function validate(state: Partial<Schema>): FormError[] {
const errors = []
if (!state.email) errors.push({ name: 'email', message: 'Required' })
if (!state.password) errors.push({ name: 'password', message: 'Required' })
return errors
}
const toast = useToast()
async function onSubmit(event: FormSubmitEvent<Schema>) {
toast.add({ title: 'Success', description: 'The form has been submitted.', color: 'success' })
console.log(event.data)
}
async function onError(event: FormErrorEvent) {
if (event?.errors?.[0]?.id) {
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">
<UFormField label="Email" name="email">
<UInput v-model="state.email" />
</UFormField>
<UFormField label="Password" name="password">
<UInput v-model="state.password" type="password" />
</UFormField>
<UButton type="submit">
Submit
</UButton>
</UForm>
</template>
<script setup lang="ts">
import { reactive } from 'vue'
import type { FormError, FormErrorEvent, FormSubmitEvent } from '@nuxt/ui'
const state = reactive({
email: undefined,
password: undefined
})
type Schema = typeof state
function validate(state: Partial<Schema>): FormError[] {
const errors = []
if (!state.email) errors.push({ name: 'email', message: 'Required' })
if (!state.password) errors.push({ name: 'password', message: 'Required' })
return errors
}
const toast = useToast()
async function onSubmit(event: FormSubmitEvent<Schema>) {
toast.add({ title: 'Success', description: 'The form has been submitted.', color: 'success' })
console.log(event.data)
}
async function onError(event: FormErrorEvent) {
if (event?.errors?.[0]?.id) {
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">
<UFormField label="Email" name="email">
<UInput v-model="state.email" />
</UFormField>
<UFormField label="Password" name="password">
<UInput v-model="state.password" type="password" />
</UFormField>
<UButton type="submit">
Submit
</UButton>
</UForm>
</template>
Validation ### HTML5: badge{label="4.5+" class="align-text-top"}
Lorsque vous appelez form.submit() par programmation, le composant Formulaire déclenche automatiquement la validation HTML5 native avant la soumission.
<script setup lang="ts">
import type { FormSubmitEvent } from '@nuxt/ui'
const state = reactive({
email: undefined,
age: undefined
})
type Schema = typeof state
const form = useTemplateRef('form')
const toast = useToast()
async function onSubmit(event: FormSubmitEvent<Schema>) {
toast.add({ title: 'Success', description: 'The form has been submitted.', color: 'success' })
console.log(event.data)
}
</script>
<template>
<div class="space-y-4">
<UForm ref="form" :state="state" class="space-y-4" @submit="onSubmit">
<UFormField label="Email" name="email">
<UInput v-model="state.email" type="email" required />
</UFormField>
<UFormField label="Age" name="age">
<UInput v-model="state.age" type="number" min="18" max="100" required />
</UFormField>
</UForm>
<UButton @click="form?.submit()">
Submit
</UButton>
</div>
</template>
<script setup lang="ts">
import { reactive, useTemplateRef } from 'vue'
import type { FormSubmitEvent } from '@nuxt/ui'
const state = reactive({
email: undefined,
age: undefined
})
type Schema = typeof state
const form = useTemplateRef('form')
const toast = useToast()
async function onSubmit(event: FormSubmitEvent<Schema>) {
toast.add({ title: 'Success', description: 'The form has been submitted.', color: 'success' })
console.log(event.data)
}
</script>
<template>
<div class="space-y-4">
<UForm ref="form" :state="state" class="space-y-4" @submit="onSubmit">
<UFormField label="Email" name="email">
<UInput v-model="state.email" type="email" required />
</UFormField>
<UFormField label="Age" name="age">
<UInput v-model="state.age" type="number" min="18" max="100" required />
</UFormField>
</UForm>
<UButton @click="form?.submit()">
Submit
</UButton>
</div>
</template>
Formulaires de nesting
Utilisez la prop nested pour imbriquer plusieurs composants de formulaire et lier leurs fonctions de validation. Dans ce cas, la validation du formulaire parent validera automatiquement tous les autres formulaires qu 'il contient.
Les formulaires imbriqués héritent directement de l'état de leur parent, vous n'avez donc pas besoin de définir un état distinct pour eux. Vous pouvez utiliser la prop name pour cibler un attribut imbriqué dans l'état du parent.
Il peut être utilisé pour ajouter dynamiquement des champs en fonction de la saisie de l'utilisateur:
<script setup lang="ts">
import * as z from 'zod'
import type { FormSubmitEvent } from '@nuxt/ui'
const schema = z.object({
name: z.string().min(2),
news: z.boolean().default(false)
})
type Schema = z.output<typeof schema>
const nestedSchema = z.object({
email: z.email()
})
type NestedSchema = z.output<typeof nestedSchema>
const state = reactive<Partial<Schema & NestedSchema>>({ })
const toast = useToast()
async function onSubmit(event: FormSubmitEvent<Schema>) {
toast.add({ title: 'Success', description: 'The form has been submitted.', color: 'success' })
console.log(event.data)
}
</script>
<template>
<UForm
ref="form"
:state="state"
:schema="schema"
class="gap-4 flex flex-col w-60"
@submit="onSubmit"
>
<UFormField label="Name" name="name">
<UInput v-model="state.name" placeholder="John Lennon" />
</UFormField>
<div>
<UCheckbox v-model="state.news" name="news" label="Register to our newsletter" @update:model-value="state.email = undefined" />
</div>
<UForm v-if="state.news" :schema="nestedSchema" nested>
<UFormField label="Email" name="email">
<UInput v-model="state.email" placeholder="john@lennon.com" />
</UFormField>
</UForm>
<div>
<UButton type="submit">
Submit
</UButton>
</div>
</UForm>
</template>
<script setup lang="ts">
import { reactive } from 'vue'
import * as z from 'zod'
import type { FormSubmitEvent } from '@nuxt/ui'
const schema = z.object({
name: z.string().min(2),
news: z.boolean().default(false)
})
type Schema = z.output<typeof schema>
const nestedSchema = z.object({
email: z.email()
})
type NestedSchema = z.output<typeof nestedSchema>
const state = reactive<Partial<Schema & NestedSchema>>({ })
const toast = useToast()
async function onSubmit(event: FormSubmitEvent<Schema>) {
toast.add({ title: 'Success', description: 'The form has been submitted.', color: 'success' })
console.log(event.data)
}
</script>
<template>
<UForm
ref="form"
:state="state"
:schema="schema"
class="gap-4 flex flex-col w-60"
@submit="onSubmit"
>
<UFormField label="Name" name="name">
<UInput v-model="state.name" placeholder="John Lennon" />
</UFormField>
<div>
<UCheckbox v-model="state.news" name="news" label="Register to our newsletter" @update:model-value="state.email = undefined" />
</div>
<UForm v-if="state.news" :schema="nestedSchema" nested>
<UFormField label="Email" name="email">
<UInput v-model="state.email" placeholder="john@lennon.com" />
</UFormField>
</UForm>
<div>
<UButton type="submit">
Submit
</UButton>
</div>
</UForm>
</template>
Ou pour valider les entrées de liste:
<script setup lang="ts">
import * as z from 'zod'
import type { FormSubmitEvent } from '@nuxt/ui'
const schema = z.object({
customer: z.string().min(2)
})
type Schema = z.output<typeof schema>
const itemSchema = z.object({
description: z.string().min(1),
price: z.number().min(0)
})
type ItemSchema = z.output<typeof itemSchema>
const state = reactive<Partial<Schema & { items: Partial<ItemSchema>[] }>>({ })
function addItem() {
if (!state.items) {
state.items = []
}
state.items.push({})
}
function removeItem() {
if (state.items) {
state.items.pop()
}
}
const toast = useToast()
async function onSubmit(event: FormSubmitEvent<Schema>) {
toast.add({ title: 'Success', description: 'The form has been submitted.', color: 'success' })
console.log(event.data)
}
</script>
<template>
<UForm
:state="state"
:schema="schema"
class="gap-4 flex flex-col w-60"
@submit="onSubmit"
>
<UFormField label="Customer" name="customer">
<UInput v-model="state.customer" placeholder="Wonka Industries" />
</UFormField>
<UForm
v-for="item, count in state.items"
:key="count"
:name="`items.${count}`"
:schema="itemSchema"
class="flex gap-2"
nested
>
<UFormField :label="!count ? 'Description' : undefined" name="description">
<UInput v-model="item.description" />
</UFormField>
<UFormField :label="!count ? 'Price' : undefined" name="price" class="w-20">
<UInput v-model="item.price" type="number" />
</UFormField>
</UForm>
<div class="flex gap-2">
<UButton color="neutral" variant="subtle" size="sm" @click="addItem()">
Add Item
</UButton>
<UButton color="neutral" variant="ghost" size="sm" @click="removeItem()">
Remove Item
</UButton>
</div>
<div>
<UButton type="submit">
Submit
</UButton>
</div>
</UForm>
</template>
<script setup lang="ts">
import { reactive } from 'vue'
import * as z from 'zod'
import type { FormSubmitEvent } from '@nuxt/ui'
const schema = z.object({
customer: z.string().min(2)
})
type Schema = z.output<typeof schema>
const itemSchema = z.object({
description: z.string().min(1),
price: z.number().min(0)
})
type ItemSchema = z.output<typeof itemSchema>
const state = reactive<Partial<Schema & { items: Partial<ItemSchema>[] }>>({ })
function addItem() {
if (!state.items) {
state.items = []
}
state.items.push({})
}
function removeItem() {
if (state.items) {
state.items.pop()
}
}
const toast = useToast()
async function onSubmit(event: FormSubmitEvent<Schema>) {
toast.add({ title: 'Success', description: 'The form has been submitted.', color: 'success' })
console.log(event.data)
}
</script>
<template>
<UForm
:state="state"
:schema="schema"
class="gap-4 flex flex-col w-60"
@submit="onSubmit"
>
<UFormField label="Customer" name="customer">
<UInput v-model="state.customer" placeholder="Wonka Industries" />
</UFormField>
<UForm
v-for="item, count in state.items"
:key="count"
:name="`items.${count}`"
:schema="itemSchema"
class="flex gap-2"
nested
>
<UFormField :label="!count ? 'Description' : undefined" name="description">
<UInput v-model="item.description" />
</UFormField>
<UFormField :label="!count ? 'Price' : undefined" name="price" class="w-20">
<UInput v-model="item.price" type="number" />
</UFormField>
</UForm>
<div class="flex gap-2">
<UButton color="neutral" variant="subtle" size="sm" @click="addItem()">
Add Item
</UButton>
<UButton color="neutral" variant="ghost" size="sm" @click="removeItem()">
Remove Item
</UButton>
</div>
<div>
<UButton type="submit">
Submit
</UButton>
</div>
</UForm>
</template>
API
Props
| Prop | Default | Type |
|---|---|---|
id | string | number | |
schema | SSchema to validate the form state. Supports Standard Schema objects, Yup, Joi, and Superstructs. | |
state | N extends false ? Partial<InferInput<S>> : neverAn object representing the current state of the form. | |
validate | (state: Partial<InferInput<S>>): FormError<string>[] | Promise<FormError<string>[]>Custom validation function to validate the form state. | |
validateOn | `['blur', 'change', 'input']` | FormInputEvents[]The list of input events that trigger the form validation. |
disabled | boolean Disable all inputs inside the form. | |
name | stringThe | |
validateOnInputDelay | 300 | numberDelay in milliseconds before validating the form on input events. |
transform | true as T | TIf true, applies schema transformations on submit. |
nested | `false` | NIf true, this form will attach to its parent Form and validate at the same time. |
loadingAuto | true | boolean When |
acceptcharset | string | |
action | string | |
autocomplete | string | |
enctype | string | |
method | string | |
novalidate | false | true | "true" | "false" | |
target | string | |
ui | { base?: any; } |
Slots
| Slot | Type |
|---|---|
default | { errors: FormErrorWithId[]; loading: boolean; } |
Emits
| Event | Type |
|---|---|
submit | [event: FormSubmitEvent<FormData<S, T>>] |
error | [event: FormErrorEvent] |
Expose à
Vous pouvez accéder à l'instance du composant typé à l'aide de useTemplateRef.
<script setup lang="ts">
const form = useTemplateRef('form')
</script>
<template>
<UForm ref="form" />
</template>
Cela vous donnera accès à ce qui suit:
| nom | type |
|---|---|
submit()x{lang="ts-type"} | Promise<void> Triggers soumission de formulaire avec validation HTML5. |
validate(opts: { name?: keyof T | (keyof T)[], silent?: boolean, nested?: boolean, transform?: boolean }) | Promise<T> Triggers validation de formulaire. Générera des erreurs à moins que |
clear(path?: keyof T | RegExp) | void Efface les erreurs de formulaire associées à un chemin spécifique. Si aucun chemin n'est fourni, efface toutes les erreurs de formulaire. |
getErrors(path?: keyof T | RegExp)x{lang="ts-type"} | FormErrorWithId[] Récupère les erreurs de formulaire associées à un chemin spécifique. Si aucun chemin n'est fourni, renvoie toutes les erreurs de formulaire. |
setErrors(errors: FormError[], name?: keyof T | RegExp)x{lang="ts-type"} | void Ensemble les erreurs de formulaire pour un chemin donné. Si aucun chemin n'est fourni, remplace toutes les erreurs. |
errorsx{lang="ts-type"} | Ref<FormErrorWithId[]> Una referencia a la matriz que contiene errores de validación. Use esto para acceder o manipular la información de error. |
disabledx{lang="ts-type"} | Ref<boolean> |
dirtyx{lang="ts-type"} | Ref<boolean> true si au moins un champ de formulaire a été mis à jour par l'utilisateur. |
dirtyFieldsx{lang="ts-type"} | ReadonlySet<DeepReadonly<keyof T>> Trace les champs qui ont été modifiés par l'utilisateur. |
touchedFieldsx{lang="ts-type"} | ReadonlySet<DeepReadonly<keyof T>> Suit les champs avec lesquels l'utilisateur a interagi. |
blurredFieldsx{lang="ts-type"} | ReadonlySet<DeepReadonly<keyof T>> Trace les champs flous par l'utilisateur. |
Thème
export default defineAppConfig({
ui: {
form: {
base: ''
}
}
})import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from '@nuxt/ui/vite'
export default defineConfig({
plugins: [
vue(),
ui({
ui: {
form: {
base: ''
}
}
})
]
})