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.
Features
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)
Anatomy
<template>
<Form>
<FormField>
<FormItem>
<FormLabel />
<FormControl>
<!-- any Form Input component or native input elements -->
</FormControl>
<FormDescription />
<FormMessage />
</FormItem>
</FormField>
</Form>
</template>Examples
Komponen Input
<template>
<FormField v-slot="{ componentField }">
<FormItem>
<FormLabel>Username</FormLabel>
<FormControl>
<Input placeholder="shadcn" v-bind="componentField" />
</FormControl>
<FormDescription />
<FormMessage />
</FormItem>
</FormField>
</template>2
3
4
5
6
7
8
9
10
11
12
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>2
3
4
5
6
7
8
9
10
11
12
Installation
pnpm dlx kliping@latest add formPasang dependensi berikut:
pnpm add reka-ui vee-validate @vee-validate/zod zodSalin dan tempel kode sumber di GitHub ke project Anda.
Sesuaikan path import dengan struktur project Anda.
Usage
<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>2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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>2
3
4
5
6
7
8
Definisikan form
Buat form memakai composable useForm dari vee-validate, atau memakai komponen <Form />.
<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>2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<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>2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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>2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
Selesai
Selesai. Sekarang Anda punya form yang mudah diakses, aman secara tipe, dan tervalidasi di sisi klien.
Requirements
Semua dipasang otomatis oleh kliping add; tabel ini untuk Anda yang memasang manual atau memeriksa project.
| Requirement | Value |
|---|---|
| Project | Vue 3.5+, Tailwind CSS v4, alias @ — disiapkan kliping init |
| npm packages | reka-ui@^2.10.3, vee-validate@^4.15.1 |
| Kliping items | label |
| Files | components/ui/form/form-control.vuecomponents/ui/form/form-description.vuecomponents/ui/form/form-item.vuecomponents/ui/form/form-label.vuecomponents/ui/form/form-message.vuecomponents/ui/form/index.tscomponents/ui/form/injection-keys.tscomponents/ui/form/use-form-field.ts |
Anatomy
Susunan bagiannya seperti dipakai di contoh-contoh di atas. Impor semua bagian dari satu tempat, lalu susun begini:
<FormItem>
<FormLabel />
<FormControl />
<FormDescription />
<FormMessage />
</FormItem>API Reference
FormControl
| Slot | Props |
|---|---|
#default | — |
| Data attribute | Value |
|---|---|
[data-slot] | "form-control" |
FormDescription
| Slot | Props |
|---|---|
#default | — |
| Data attribute | Value |
|---|---|
[data-slot] | "form-description" |
FormItem
| Slot | Props |
|---|---|
#default | — |
| Data attribute | Value |
|---|---|
[data-slot] | "form-item" |
FormLabel
| Prop | Type | Default | Description |
|---|---|---|---|
for? | string | — | The id of the element the label is associated with. |
asChild? | boolean | — | Change the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. |
as? | AsTag | Component | — | The element or component this component should render as. Can be overwritten by asChild. |
| Slot | Props |
|---|---|
#default | — |
| Data attribute | Value |
|---|---|
[data-slot] | "form-label" |
[data-error] | set at runtime |
FormMessage
| Data attribute | Value |
|---|---|
[data-slot] | "form-message" |
CSS Variables
Token tema yang dibaca komponen ini — ubah nilainya di CSS global (:root dan .dark, lihat Theming) untuk mengubah tampilannya tanpa menyentuh komponennya: --destructive, --muted-foreground.
Credits
Berasal dari shadcn-vue (MIT, Copyright (c) 2023 unovue). Rantai lengkapnya di Credits.