Form
Gebruik
Gebruik de Form-component om formuliergegevens te valideren met behulp van een validatiebibliotheek die Standard ondersteunt Schema zoals Valibot, Zod, Regle, Yup, Joi of Superstruct of uw eigen validatielogica.
Het werkt met de FormField component om foutmeldingen rond formulierelementen automatisch weer te geven.
Schema validatie
Het vereist twee rekwisieten:
state- een reactief object met de status van het formulier.schema- elke Standard Schema of 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>
Aangepaste validatie
Gebruik de validate prop om je eigen validatielogica toe te passen.
De validatiefunctie moet een lijst met fouten retourneren met de volgende kenmerken:
message- het te tonen foutbericht.name- denamevan deFormFieldom de fout naar toe te sturen.
schema-prop worden gebruikt om complexe use-cases te behandelen.<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>
Foutmelding
Fouten worden gekoppeld aan de overeenkomstige FormField met behulp van de name-prop. Een fout in het email-veld wordt weergegeven door <FormField name="email">.
Genestelde velden worden gematcht met behulp van puntnotatie. Een schema zoals { user: z.object({ email: z.string() }) } zal worden toegepast op <FormField name="user.email">.
tags.0, tags.1) en komen niet overeen met <FormField name="tags"> alleen door name.
Gebruik de error-pattern prop met een reguliere expressie zoals /^tags\..+/ om ze vast te leggen. Dit is vooral handig voor componenten zoals 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 gebeurtenissen
Het Form-onderdeel activeert automatisch validatie wanneer een invoer een input, change of blur-gebeurtenis uitzendt.
- Validatie op
inputkomt voor as u type. - Validatie op
changetreedt op wanneer u commit naar een value. - Validatie op
blurgebeurt wanneer een ingang loses focus.
U kunt dit controleren wanneer validatie plaatsvindt met behulp van de validate-on prop.
useFormField composable gebruiken om dit in uw eigen componenten te implementeren.Fout gebeurtenis
U kunt naar de @error-gebeurtenis luisteren om fouten te verwerken. Deze gebeurtenis wordt geactiveerd wanneer het formulier wordt ingediend en bevat een reeks FormError-objecten met de volgende velden:
id- de invoer isid.name- denamevan deFormFieldmessage- het te tonen foutbericht.
Hier is een voorbeeld dat het eerste invoerelement focust met een fout nadat het formulier is ingediend:
<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>
HTML5 validatie: badge{label="4.5+" class="align-text-top"}
Wanneer form.submit() programmatisch wordt aangeroepen, activeert de Form-component automatisch native HTML5-validatie voordat deze wordt ingediend.
<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>
Nestvormen
Gebruik de nested prop om meerdere Form-componenten te nesten en hun validatiefuncties te koppelen. In dit geval zal het valideren van het bovenliggende formulier automatisch alle andere formulieren erin valideren.
Genestelde formulieren erven rechtstreeks de staat van hun ouders, dus u hoeft geen afzonderlijke staat voor hen te definiëren.
U kunt de name-prop gebruiken om een genest attribuut binnen de status van de ouder te targeten.
Het kan worden gebruikt om dynamisch velden toe te voegen op basis van input van de gebruiker:
<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>
Of om lijstinvoer te valideren:
<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; } |
Uitzendt
| Event | Type |
|---|---|
submit | [event: FormSubmitEvent<FormData<S, T>>] |
error | [event: FormErrorEvent] |
Expose
U hebt toegang tot de getypte componentinstantie met useTemplateRef.
<script setup lang="ts">
const form = useTemplateRef('form')
</script>
<template>
<UForm ref="form" />
</template>
Dit geeft u toegang tot het volgende:
| Naam | Type |
|---|---|
submit() | Promise<void> Triggers formulier indienen met HTML5-validatie. |
validate(opts: { name?: keyof T | (keyof T)[], silent?: boolean, nested?: boolean, transform?: boolean }) | Promise<T> Triggers formuliervalidatie. Zal fouten veroorzaken tenzij |
clear(path?: keyof T | RegExp) | void Clears formulierfouten die aan een specifiek pad zijn gekoppeld. Als er geen pad is opgegeven, worden alle formulierfouten verwijderd. |
getErrors(path?: keyof T | RegExp) | FormErrorWithId[] Retrieves formulierfouten die aan een specifiek pad zijn gekoppeld. Als er geen pad is opgegeven, worden alle formulierfouten geretourneerd. |
setErrors(errors: FormError[], name?: keyof T | RegExp) | void Stelt formulierfouten in voor een bepaald pad. Als er geen pad is opgegeven, worden alle fouten overschreven. |
errors | Ref<FormErrorWithId[]> Een verwijzing naar de array die validatiefouten bevat. Gebruik dit om de foutinformatie te openen of te manipuleren. |
disabled | Ref<boolean> |
dirty | Ref<boolean> true als ten minste één formulierveld is bijgewerkt door de gebruiker. |
dirtyFields | ReadonlySet<DeepReadonly<keyof T>> Tracks velden die zijn gewijzigd door de gebruiker. |
touchedFields | ReadonlySet<DeepReadonly<keyof T>> Houdt velden bij waarmee de gebruiker interactie heeft gehad. |
blurredFields | ReadonlySet<DeepReadonly<keyof T>> Velden bijhouden die door de gebruiker zijn vervaagd. |
Thema
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: ''
}
}
})
]
})