Form

Form خودش هیچ ورودی‌ای رندر نمی‌کند؛ فقط context مربوط به react-hook-form را پخش می‌کند و FormField/FormItem/FormLabel/FormControl/FormMessage را به هم و به id/aria درست وصل می‌کند. اعتبارسنجی با هر resolver ای از جمله zod کار می‌کند.

ری‌اکت ۱۹ و Next.js با پیاده‌سازی دسترس‌پذیری داخلی دیگویو ۳ با Composition API و Reka UISvelte ۵ با runes و Bits UIانگولار با signals و Angular CDK

این کامپوننت فعلاً برای ۱ فریم‌ورک از ۴ فریم‌ورک آماده است.

همان چیزی که در پروفایل عمومی نشان داده می‌شود.

این نمونه هنوز برای Vue پورت نشده است؛ آنچه می‌بینید نسخهٔ ری‌اکت است.

این نمونه هنوز برای Svelte پورت نشده است؛ آنچه می‌بینید نسخهٔ ری‌اکت است.

این نمونه هنوز برای Angular پورت نشده است؛ آنچه می‌بینید نسخهٔ ری‌اکت است.

نصب

با CLI اختصاصی dig-ui کامپوننت را از رجیستری دیگ نصب کنید؛ وابستگی‌ها و فایل‌ها خودکار اضافه می‌شوند.

نصب سریع با لینک سخت و دیسک مشترکپکیج‌منیجر پیش‌فرض Node.jsYarn نسخهٔ ۲ به بالا (Berry)رانتایم و پکیج‌منیجر Bun
pnpm dlx dig-ui@latest add https://design-system-tau-green.vercel.app/r/form.json
npx dig-ui@latest add https://design-system-tau-green.vercel.app/r/form.json
yarn dlx dig-ui@latest add https://design-system-tau-green.vercel.app/r/form.json
bunx --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 در دست کار است.

ترکیب اجزا

FormField یک react-hook-form Controller است که name فیلد را در FormFieldContext می‌گذارد؛ FormItem یک id تازه با useId می‌سازد و در FormItemContext می‌گذارد. useFormField این دو context را با getFieldState ترکیب می‌کند و id، formItemId، formDescriptionId، formMessageId و وضعیت خطا را برمی‌گرداند. FormLabel از formItemId به‌عنوان htmlFor استفاده می‌کند، FormControl همان id را به کنترل واقعی می‌دهد و aria-describedby را بسته به وجود خطا به FormDescription و/یا FormMessage وصل می‌کند. یعنی کافی‌ست این چهار تکه را همیشه با هم داخل FormItem بگذارید؛ بقیه (اتصال id، اعلام خطا به صفحه‌خوان) خودکار است. برای فرم‌های چندبخشی، FormFieldها را داخل Fieldset بگذارید، Form مسئول اعتبارسنجی/خطا می‌ماند، Fieldset فقط گروه‌بندی معنایی (legend) و چیدمان می‌دهد.

دسترس‌پذیری

  • 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

ویژگینوعپیش‌فرضتوضیح
...formUseFormReturn<T>خروجی useForm همینجا اسپرد می‌شود؛ Form پشت‌پرده FormProvider را با همین مقدار رندر می‌کند.
errorsPartial<Record<FieldPath<T>, string>>خطاهای سمت سرور، کلید = نام فیلد. روی همان فیلد ست می‌شود و با اولین تغییر کاربر در آن فیلد خودکار پاک می‌شود؛ خطاهای معمولیِ resolver/rules را دست‌نخورده می‌گذارد.

FormField

ویژگینوعپیش‌فرضتوضیح
controlControl<T>همان form.control از useForm.
nameFieldPath<T>مسیر فیلد در schema/defaultValues.
render({ field, fieldState }) => ReactNodeهمان الگوی Controller از react-hook-form؛ field شامل value، onChange، onBlur، ref و name است.

useFormField()

ویژگینوعپیش‌فرضتوضیح
errorFieldError | undefinedخطای اعتبارسنجی فیلد جاری، اگر باشد.
formItemId / formDescriptionId / formMessageIdstringidهایی که FormLabel/FormControl/FormDescription/FormMessage برای اتصال aria از همین می‌خوانند.

این کامپوننت هنوز برای Vue پورت نشده است.

نسخهٔ ری‌اکت آماده است؛ پورت این فریم‌ورک روی Reka UI در دست کار است.

این کامپوننت هنوز برای Svelte پورت نشده است.

نسخهٔ ری‌اکت آماده است؛ پورت این فریم‌ورک روی Bits UI در دست کار است.

این کامپوننت هنوز برای Angular پورت نشده است.

نسخهٔ ری‌اکت آماده است؛ پورت این فریم‌ورک روی Angular CDK در دست کار است.