| name | nuxt-forms |
| description | Form handling with useFormBuilder and native forms. Use when creating forms, handling validation errors, managing form state, or building form-based slideovers and modals. |
Nuxt Forms
Form handling with useFormBuilder composable and native form elements.
Core Concepts
forms.md - useFormBuilder, native forms, validation patterns
useFormBuilder Pattern
<script lang="ts" setup>
import { Input } from '~/components/ui/input'
import { Button } from '~/components/ui/button'
import { Label } from '~/components/ui/label'
import { Loader2 } from 'lucide-vue-next'
const form = useFormBuilder<CreatePostData>()
.post('/api/posts')
.data({ title: '' })
.waiting('posts.creating')
.success(() => emits('close', true))
.error(({ error }) => { /* handle */ })
.build()
</script>
<template>
<form @submit.prevent="form.submit()">
<div class="flex flex-col gap-2">
<Label>Title</Label>
<Input v-model="form.data.title" />
<p v-if="form.errors.has('title')" class="text-sm text-destructive">
{{ form.errors.first('title') }}
</p>
</div>
<div class="flex justify-end gap-2 mt-4">
<Button type="submit" :disabled="form.processing">
<Loader2 v-if="form.processing" data-icon="inline-start" class="animate-spin" />
Create
</Button>
</div>
</form>
</template>
Form Data Pattern
const formData = ref<CreatePostData>({
title: '',
content: '',
authorId: '',
isDraft: true,
})
const onSubmit = async (data: CreatePostData) => {
await createPostAction(data)
}
const onSuccess = () => {
emits('close', true)
}
Validation Errors
form.errors.has('title')
form.errors.first('title')
form.errors.get('title')
form.errors.any()
<!-- Display in template -->
<div class="flex flex-col gap-2">
<Label>Title</Label>
<Input v-model="formData.title" />
<p v-if="form?.errors.has('title')" class="text-sm text-destructive">
{{ form?.errors.first('title') }}
</p>
</div>