Form
Form خودش هیچ ورودیای رندر نمیکند؛ فقط context مربوط به react-hook-form را پخش میکند و FormField/FormItem/FormLabel/FormControl/FormMessage را به هم و به id/aria درست وصل میکند. اعتبارسنجی با هر resolver ای از جمله zod کار میکند.
این کامپوننت فعلاً برای ۱ فریمورک از ۴ فریمورک آماده است.
این نمونه هنوز برای Vue پورت نشده است؛ آنچه میبینید نسخهٔ ریاکت است.
این نمونه هنوز برای Svelte پورت نشده است؛ آنچه میبینید نسخهٔ ریاکت است.
این نمونه هنوز برای Angular پورت نشده است؛ آنچه میبینید نسخهٔ ریاکت است.
نصب
با CLI اختصاصی dig-ui کامپوننت را از رجیستری دیگ نصب کنید؛ وابستگیها و فایلها خودکار اضافه میشوند.
pnpm dlx dig-ui@latest add https://design-system-tau-green.vercel.app/r/form.jsonnpx dig-ui@latest add https://design-system-tau-green.vercel.app/r/form.jsonyarn dlx dig-ui@latest add https://design-system-tau-green.vercel.app/r/form.jsonbunx --bun dig-ui@latest add https://design-system-tau-green.vercel.app/r/form.jsonاین کامپوننت هنوز برای Vue پورت نشده است.
نسخهٔ ریاکت آماده است؛ پورت این فریمورک روی Reka UI در دست کار است.
این کامپوننت هنوز برای Svelte پورت نشده است.
نسخهٔ ریاکت آماده است؛ پورت این فریمورک روی Bits UI در دست کار است.
این کامپوننت هنوز برای Angular پورت نشده است.
نسخهٔ ریاکت آماده است؛ پورت این فریمورک روی Angular CDK در دست کار است.
استفاده
import { zodResolver } from "@hookform/resolvers/zod"
import { useForm } from "react-hook-form"
import { z } from "zod"
import { Button } from "@/components/ui/button"
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form"
import { Input } from "@/components/ui/input"
const formSchema = z.object({
username: z.string().min(2),
})
function ProfileForm() {
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: { username: "" },
})
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(console.log)}>
<FormField
control={form.control}
name="username"
render={({ field }) => (
<FormItem>
<FormLabel>نام کاربری</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit">ذخیره</Button>
</form>
</Form>
)
}این کامپوننت هنوز برای Vue پورت نشده است.
نسخهٔ ریاکت آماده است؛ پورت این فریمورک روی Reka UI در دست کار است.
این کامپوننت هنوز برای Svelte پورت نشده است.
نسخهٔ ریاکت آماده است؛ پورت این فریمورک روی Bits UI در دست کار است.
این کامپوننت هنوز برای Angular پورت نشده است.
نسخهٔ ریاکت آماده است؛ پورت این فریمورک روی Angular CDK در دست کار است.
ترکیب اجزا
دسترسپذیری
- FormControl خودش aria-invalid و aria-describedby را روی کنترل واقعی ست میکند؛ کافیست کنترل را (Input، Select، Checkbox و…) مستقیم داخلش بگذارید، نیازی به نوشتن دستی این پراپها نیست.
- FormLabel با data-error={true} رنگ خودش را قرمز میکند، اما این فقط بصری است؛ اعلام واقعی خطا به صفحهخوان از طریق aria-describedby روی FormControl و متن FormMessage انجام میشود.
- FormMessage وقتی خطایی نیست چیزی رندر نمیکند (نه یک <p> خالی)؛ پس فضای خالی برای پیام خطا در DOM نمیماند تا صفحهخوان چیزی خالی را اعلام کند.
- برای فیلدهایی که خودشان id ندارند (مثل Select یا Checkbox)، همان الگوی FormControl کافی است؛ خودِ FormControl از طریق Slot، id و aria را به اولین فرزندش تزریق میکند.
- با ارسال ناموفق، react-hook-form بهصورت پیشفرض فوکوس را به اولین فیلدِ دارای خطا میبرد (shouldFocusError)، تا وقتی FormControl، ref کنترل واقعی را درست پاس بدهد (که خودش این کار را میکند)، نیازی به مدیریت دستی فوکوس نیست.
مرجع API
Form
| ویژگی | نوع | پیشفرض | توضیح |
|---|---|---|---|
| ...form | UseFormReturn<T> | — | خروجی useForm همینجا اسپرد میشود؛ Form پشتپرده FormProvider را با همین مقدار رندر میکند. |
| errors | Partial<Record<FieldPath<T>, string>> | — | خطاهای سمت سرور، کلید = نام فیلد. روی همان فیلد ست میشود و با اولین تغییر کاربر در آن فیلد خودکار پاک میشود؛ خطاهای معمولیِ resolver/rules را دستنخورده میگذارد. |
FormField
| ویژگی | نوع | پیشفرض | توضیح |
|---|---|---|---|
| control | Control<T> | — | همان form.control از useForm. |
| name | FieldPath<T> | — | مسیر فیلد در schema/defaultValues. |
| render | ({ field, fieldState }) => ReactNode | — | همان الگوی Controller از react-hook-form؛ field شامل value، onChange، onBlur، ref و name است. |
useFormField()
| ویژگی | نوع | پیشفرض | توضیح |
|---|---|---|---|
| error | FieldError | undefined | — | خطای اعتبارسنجی فیلد جاری، اگر باشد. |
| formItemId / formDescriptionId / formMessageId | string | — | idهایی که FormLabel/FormControl/FormDescription/FormMessage برای اتصال aria از همین میخوانند. |
این کامپوننت هنوز برای Vue پورت نشده است.
نسخهٔ ریاکت آماده است؛ پورت این فریمورک روی Reka UI در دست کار است.
این کامپوننت هنوز برای Svelte پورت نشده است.
نسخهٔ ریاکت آماده است؛ پورت این فریمورک روی Bits UI در دست کار است.
این کامپوننت هنوز برای Angular پورت نشده است.
نسخهٔ ریاکت آماده است؛ پورت این فریمورک روی Angular CDK در دست کار است.
نمونهها
Select Field
کنترلهای بدون id طبیعی (مثل Select) هم همان الگوی FormControl را میپذیرند.
این نمونه هنوز برای Vue پورت نشده است؛ آنچه میبینید نسخهٔ ریاکت است.
این نمونه هنوز برای Svelte پورت نشده است؛ آنچه میبینید نسخهٔ ریاکت است.
این نمونه هنوز برای Angular پورت نشده است؛ آنچه میبینید نسخهٔ ریاکت است.
Disable While Submitting
form.formState.isSubmitting در حین اجرای async onSubmit درست است؛ دکمه را با همین مقدار غیرفعال کنید تا کاربر دوبار کلیک نکند.
این نمونه هنوز برای Vue پورت نشده است؛ آنچه میبینید نسخهٔ ریاکت است.
این نمونه هنوز برای Svelte پورت نشده است؛ آنچه میبینید نسخهٔ ریاکت است.
این نمونه هنوز برای Angular پورت نشده است؛ آنچه میبینید نسخهٔ ریاکت است.
خطای سمت سرور
errors روی Form، خطاهایی را که فقط بعد از رفتوبرگشت با سرور معلوم میشوند (مثل «نام کاربری تکراری است») روی فیلد موردنظر مینشاند؛ بهمحض اینکه کاربر همان فیلد را ویرایش کند، خودش پاک میشود، بدون هیچ setError/clearErrors دستی در onSubmit. برای تست: هر بار «ثبتنام» بزنید، سپس داخل فیلد تایپ کنید تا خطا محو شود.
این نمونه هنوز برای Vue پورت نشده است؛ آنچه میبینید نسخهٔ ریاکت است.
این نمونه هنوز برای Svelte پورت نشده است؛ آنچه میبینید نسخهٔ ریاکت است.
این نمونه هنوز برای Angular پورت نشده است؛ آنچه میبینید نسخهٔ ریاکت است.
اعتبارسنجی زنده
با mode: "onChange" در useForm، خطا همزمان با تایپ ظاهر و محو میشود، نه فقط بعد از تلاش برای ارسال، برای فیلدهایی مثل رمز عبور که بازخورد فوری اهمیت دارد.
این نمونه هنوز برای Vue پورت نشده است؛ آنچه میبینید نسخهٔ ریاکت است.
این نمونه هنوز برای Svelte پورت نشده است؛ آنچه میبینید نسخهٔ ریاکت است.
این نمونه هنوز برای Angular پورت نشده است؛ آنچه میبینید نسخهٔ ریاکت است.
کدام نمونه برای کدام موقعیت
| نمونه | کجا به کار میآید |
|---|---|
| Select Field | کنترلهای بدون id طبیعی (مثل Select) هم همان الگوی FormControl را میپذیرند. |
| Disable While Submitting | form.formState.isSubmitting در حین اجرای async onSubmit درست است؛ دکمه را با همین مقدار غیرفعال کنید تا کاربر دوبار کلیک نکند. |
| خطای سمت سرور | errors روی Form، خطاهایی را که فقط بعد از رفتوبرگشت با سرور معلوم میشوند (مثل «نام کاربری تکراری است») روی فیلد موردنظر مینشاند؛ بهمحض اینکه کاربر همان فیلد را ویرایش کند، خودش پاک میشود، بدون هیچ setError/clearErrors دستی در onSubmit |
| اعتبارسنجی زنده | با mode: "onChange" در useForm، خطا همزمان با تایپ ظاهر و محو میشود، نه فقط بعد از تلاش برای ارسال، برای فیلدهایی مثل رمز عبور که بازخورد فوری اهمیت دارد. |
دستورالعمل استفاده
خطا را همیشه با FormMessage نشان بده، نه متن دستی
انجام بده
FormMessage به formMessageId وصل است و از طریق aria-describedby روی خودِ Input هم اعلام میشود؛ صفحهخوان دقیقاً میفهمد این خطا مال کدام فیلد است.
نام کاربری باید حداقل ۲ حرف باشد.
انجام نده
پاراگراف قرمز زیر ورودی بدون aria-describedby، فقط بصری است؛ کاربر صفحهخوان وقتی روی ورودی فوکوس میکند هیچ پیامی نمیشنود.