Form
Membangun form memakai VeeValidate dan Zod.
We are not actively developing this component anymore.
Komponen Form adalah lapisan abstraksi di atas library vee-validate. Ke depannya, kami menyarankan Anda memakai komponen <Field /> untuk membangun form. Keterangan lengkapnya ada di dokumentasi Form.
Form itu rumit. Ia salah satu hal yang paling sering Anda bangun di aplikasi web, sekaligus salah satu yang paling ruwet.
Form HTML yang dirancang dengan baik punya ciri-ciri berikut:
- Terstruktur rapi dan bermakna secara semantik.
- Mudah dipakai dan dinavigasi, termasuk lewat keyboard.
- Mudah diakses lewat atribut ARIA dan label yang benar.
- Mendukung validasi di sisi klien maupun server.
- Tampilannya rapi dan selaras dengan sisa aplikasi.
Di panduan ini kita akan membangun form memakai vee-validate dan zod. Komponen <FormField> akan kita pakai untuk menyusun form yang mudah diakses dari komponen Reka UI.
Fitur
Komponen <Form /> adalah pembungkus library vee-validate. Ia menyediakan beberapa hal:
- Komponen yang bisa dikomposisikan untuk membangun form.
- Komponen
<FormField />untuk membangun field yang nilainya dikendalikan. - Validasi form memakai
zod. - Menerapkan atribut
ariayang tepat pada tiap field sesuai keadaannya, sekaligus mengurus ID yang unik. - Dirancang agar bekerja dengan semua komponen Reka UI.
- Bebas memilih library skema. Kami memakai
zod, tapi Anda bisa memakai library validasi lain yang didukung, sepertiyupatauvalibot. - Markup dan style-nya sepenuhnya di tangan Anda.
vee-validate menyediakan dua gaya penulisan untuk menambahkan validasi ke form Anda.
- Composition API
- Higher-order component (HOC)
Anatomi
<template>
<Form>
<FormField>
<FormItem>
<FormLabel />
<FormControl>
<!-- any Form Input component or native input elements -->
</FormControl>
<FormDescription />
<FormMessage />
</FormItem>
</FormField>
</Form>
</template>Contoh
Component
Komponen Input
<template>
<FormField v-slot="{ componentField }">
<FormItem>
<FormLabel>Username</FormLabel>
<FormControl>
<Input placeholder="shadcn" v-bind="componentField" />
</FormControl>
<FormDescription />
<FormMessage />
</FormItem>
</FormField>
</template>Native
Elemen input bawaan
<template>
<FormField v-slot="{ field }">
<FormItem>
<FormLabel>Username</FormLabel>
<FormControl>
<input placeholder="shadcn" v-bind="field">
</FormControl>
<FormDescription />
<FormMessage />
</FormItem>
</FormField>
</template>Instalasi
CLI
npx shadcn-vue@latest add formManual
Pasang dependensi berikut:
npm install reka-ui vee-validate @vee-validate/zod zodSalin dan tempel kode sumber di GitHub ke project Anda.
Sesuaikan path import dengan struktur project Anda.
Penggunaan
<script setup lang="ts">
import {
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from '@/components/ui/form'
</script>
<template>
<FormField v-slot="{ componentField }" name="username">
<FormItem>
<FormLabel>Username</FormLabel>
<FormControl>
<Input placeholder="shadcn" v-bind="componentField" />
</FormControl>
<FormDescription>
This is your public display name.
</FormDescription>
<FormMessage />
</FormItem>
</FormField>
</template>Buat skema form
Tentukan bentuk form Anda memakai skema Zod. Penjelasan lengkap soal Zod ada di dokumentasi Zod.
Pakai @vee-validate/zod untuk menyambungkan validasi skema Zod dengan vee-validate.
toTypedSchema sekaligus membuat nilai form dan nilai yang dikirim bertipe otomatis, mencakup tipe masukan maupun keluaran skema tersebut.
<script setup lang="ts">
import { toTypedSchema } from '@vee-validate/zod'
import * as z from 'zod'
const formSchema = toTypedSchema(z.object({
username: z.string().min(2).max(50),
}))
</script>Definisikan form
Buat form memakai composable useForm dari vee-validate, atau memakai komponen <Form />.
Composition
<script setup lang="ts">
import { useForm } from 'vee-validate'
import { toTypedSchema } from '@vee-validate/zod'
import * as z from 'zod'
import {
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage
} from '@/components/ui/form'
const formSchema = toTypedSchema(z.object({
username: z.string().min(2).max(50),
}))
const form = useForm({
validationSchema: formSchema,
})
const onSubmit = form.handleSubmit((values) => {
console.log('Form submitted!', values)
})
</script>
<template>
<form @submit="onSubmit">
...
</form>
</template>Component
<script setup lang="ts">
import { toTypedSchema } from '@vee-validate/zod'
import * as z from 'zod'
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage
} from '@/components/ui/form'
const formSchema = toTypedSchema(z.object({
username: z.string().min(2).max(50),
}))
function onSubmit(values) {
console.log('Form submitted!', values)
}
</script>
<template>
<Form :validation-schema="formSchema" @submit="onSubmit">
...
</Form>
</template>Susun form Anda
Melanjutkan langkah sebelumnya, Anda bisa memakai komponen <Form /> atau composable useForm. useForm lebih disarankan karena nilainya otomatis bertipe.
<script setup lang="ts">
import { toTypedSchema } from '@vee-validate/zod'
import { useForm } from 'vee-validate'
import * as z from 'zod'
import { Button } from '@/components/ui/button'
import {
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from '@/components/ui/form'
import { Input } from '@/components/ui/input'
const formSchema = toTypedSchema(z.object({
username: z.string().min(2).max(50),
}))
const form = useForm({
validationSchema: formSchema,
})
const onSubmit = form.handleSubmit((values) => {
console.log('Form submitted!', values)
})
</script>
<template>
<form @submit="onSubmit">
<FormField v-slot="{ componentField }" name="username">
<FormItem>
<FormLabel>Username</FormLabel>
<FormControl>
<Input type="text" placeholder="shadcn" v-bind="componentField" />
</FormControl>
<FormDescription>
This is your public display name.
</FormDescription>
<FormMessage />
</FormItem>
</FormField>
<Button type="submit">
Submit
</Button>
</form>
</template>Selesai
Selesai. Sekarang Anda punya form yang mudah diakses, aman secara tipe, dan tervalidasi di sisi klien.