[{"data":1,"prerenderedAt":874},["ShallowReactive",2],{"navigation":3,"$fMW9jOOkNpZriWVK3P_bZYNOyYR2IEPvrHsC7cDBlJJc":405,"/docs/components/form":418,"surround-/docs/components/form":871},[4],{"title":5,"path":6,"stem":7,"children":8,"page":17},"Docs","/docs","docs",[9,90,353,360,366,379],{"path":6,"stem":7,"title":10,"type":11,"children":12},"Get Started","group",[13,19,44,48,52,70,74,78,82,86],{"title":14,"path":15,"stem":16,"new":17,"type":18,"children":-1},"Introduction","/docs/introduction","docs/01.introduction",false,"page",{"title":20,"path":21,"stem":22,"children":23,"new":17,"type":11},"Installation","/docs/installation","docs/02.installation",[24,28,32,36,40],{"title":25,"path":26,"stem":27,"new":17,"type":18,"children":-1},"Vite","/docs/installation/vite","docs/installation/01.vite",{"title":29,"path":30,"stem":31,"new":17,"type":18,"children":-1},"Nuxt","/docs/installation/nuxt","docs/installation/02.nuxt",{"title":33,"path":34,"stem":35,"new":17,"type":18,"children":-1},"Astro","/docs/installation/astro","docs/installation/03.astro",{"title":37,"path":38,"stem":39,"new":17,"type":18,"children":-1},"Laravel","/docs/installation/laravel","docs/installation/04.laravel",{"title":41,"path":42,"stem":43,"new":17,"type":18,"children":-1},"Manual Installation","/docs/installation/manual","docs/installation/05.manual",{"title":45,"path":46,"stem":47,"new":17,"type":18,"children":-1},"components.json","/docs/components-json","docs/03.components-json",{"title":49,"path":50,"stem":51,"new":17,"type":18,"children":-1},"Theming","/docs/theming","docs/04.theming",{"title":53,"path":54,"stem":55,"children":56,"new":17,"type":11},"Dark Mode","/docs/dark-mode","docs/05.dark-mode",[57,60,63,67],{"title":25,"path":58,"stem":59,"new":17,"type":18,"children":-1},"/docs/dark-mode/vite","docs/dark-mode/01.vite",{"title":29,"path":61,"stem":62,"new":17,"type":18,"children":-1},"/docs/dark-mode/nuxt","docs/dark-mode/02.nuxt",{"title":64,"path":65,"stem":66,"new":17,"type":18,"children":-1},"Vitepress","/docs/dark-mode/vitepress","docs/dark-mode/03.vitepress",{"title":33,"path":68,"stem":69,"new":17,"type":18,"children":-1},"/docs/dark-mode/astro","docs/dark-mode/04.astro",{"title":71,"path":72,"stem":73,"new":17,"type":18,"children":-1},"CLI","/docs/cli","docs/06.cli",{"title":75,"path":76,"stem":77,"new":17,"type":18,"children":-1},"JavaScript","/docs/javascript","docs/07.javascript",{"title":79,"path":80,"stem":81,"new":17,"type":18,"children":-1},"Figma","/docs/figma","docs/09.figma",{"title":83,"path":84,"stem":85,"new":17,"type":18,"children":-1},"Changelog","/docs/changelog","docs/10.changelog",{"title":87,"path":88,"stem":89,"new":17,"type":18,"children":-1},"Legacy Docs","/docs/legacy","docs/11.legacy",{"title":91,"path":92,"stem":93,"children":94,"new":17,"type":11},"Components","/docs/components","docs/02.components",[95,100,104,108,112,116,120,124,128,133,137,141,145,149,153,157,161,165,169,173,177,181,185,189,193,197,201,205,209,213,217,221,225,229,233,237,241,245,249,253,257,261,265,269,273,277,281,285,289,293,297,301,305,309,313,317,321,325,329,333,337,341,345,349],{"title":96,"path":97,"stem":98,"new":17,"type":99,"children":-1},"Accordion","/docs/components/accordion","docs/components/accordion","component",{"title":101,"path":102,"stem":103,"new":17,"type":99,"children":-1},"Alert","/docs/components/alert","docs/components/alert",{"title":105,"path":106,"stem":107,"new":17,"type":99,"children":-1},"Alert Dialog","/docs/components/alert-dialog","docs/components/alert-dialog",{"title":109,"path":110,"stem":111,"new":17,"type":99,"children":-1},"Aspect Ratio","/docs/components/aspect-ratio","docs/components/aspect-ratio",{"title":113,"path":114,"stem":115,"new":17,"type":99,"children":-1},"Avatar","/docs/components/avatar","docs/components/avatar",{"title":117,"path":118,"stem":119,"new":17,"type":99,"children":-1},"Badge","/docs/components/badge","docs/components/badge",{"title":121,"path":122,"stem":123,"new":17,"type":99,"children":-1},"Breadcrumb","/docs/components/breadcrumb","docs/components/breadcrumb",{"title":125,"path":126,"stem":127,"new":17,"type":99,"children":-1},"Button","/docs/components/button","docs/components/button",{"title":129,"path":130,"stem":131,"new":132,"type":99,"children":-1},"Button Group","/docs/components/button-group","docs/components/button-group",true,{"title":134,"path":135,"stem":136,"new":17,"type":99,"children":-1},"Calendar","/docs/components/calendar","docs/components/calendar",{"title":138,"path":139,"stem":140,"new":17,"type":99,"children":-1},"Card","/docs/components/card","docs/components/card",{"title":142,"path":143,"stem":144,"new":17,"type":99,"children":-1},"Carousel","/docs/components/carousel","docs/components/carousel",{"title":146,"path":147,"stem":148,"new":17,"type":99,"children":-1},"Chart","/docs/components/chart","docs/components/chart",{"title":150,"path":151,"stem":152,"new":17,"type":99,"children":-1},"Checkbox","/docs/components/checkbox","docs/components/checkbox",{"title":154,"path":155,"stem":156,"new":17,"type":99,"children":-1},"Collapsible","/docs/components/collapsible","docs/components/collapsible",{"title":158,"path":159,"stem":160,"new":17,"type":99,"children":-1},"Combobox","/docs/components/combobox","docs/components/combobox",{"title":162,"path":163,"stem":164,"new":17,"type":99,"children":-1},"Command","/docs/components/command","docs/components/command",{"title":166,"path":167,"stem":168,"new":17,"type":99,"children":-1},"Context Menu","/docs/components/context-menu","docs/components/context-menu",{"title":170,"path":171,"stem":172,"new":17,"type":99,"children":-1},"Data Table","/docs/components/data-table","docs/components/data-table",{"title":174,"path":175,"stem":176,"new":17,"type":99,"children":-1},"Date Picker","/docs/components/date-picker","docs/components/date-picker",{"title":178,"path":179,"stem":180,"new":17,"type":99,"children":-1},"Dialog","/docs/components/dialog","docs/components/dialog",{"title":182,"path":183,"stem":184,"new":17,"type":99,"children":-1},"Drawer","/docs/components/drawer","docs/components/drawer",{"title":186,"path":187,"stem":188,"new":17,"type":99,"children":-1},"Dropdown Menu","/docs/components/dropdown-menu","docs/components/dropdown-menu",{"title":190,"path":191,"stem":192,"new":132,"type":99,"children":-1},"Empty","/docs/components/empty","docs/components/empty",{"title":194,"path":195,"stem":196,"new":132,"type":99,"children":-1},"Field","/docs/components/field","docs/components/field",{"title":198,"path":199,"stem":200,"new":17,"type":99,"children":-1},"Form","/docs/components/form","docs/components/form",{"title":202,"path":203,"stem":204,"new":17,"type":99,"children":-1},"Hover Card","/docs/components/hover-card","docs/components/hover-card",{"title":206,"path":207,"stem":208,"new":17,"type":99,"children":-1},"Input","/docs/components/input","docs/components/input",{"title":210,"path":211,"stem":212,"new":132,"type":99,"children":-1},"Input Group","/docs/components/input-group","docs/components/input-group",{"title":214,"path":215,"stem":216,"new":17,"type":99,"children":-1},"Input OTP","/docs/components/input-otp","docs/components/input-otp",{"title":218,"path":219,"stem":220,"new":132,"type":99,"children":-1},"Item","/docs/components/item","docs/components/item",{"title":222,"path":223,"stem":224,"new":132,"type":99,"children":-1},"Kbd","/docs/components/kbd","docs/components/kbd",{"title":226,"path":227,"stem":228,"new":17,"type":99,"children":-1},"Label","/docs/components/label","docs/components/label",{"title":230,"path":231,"stem":232,"new":17,"type":99,"children":-1},"Menubar","/docs/components/menubar","docs/components/menubar",{"title":234,"path":235,"stem":236,"new":132,"type":99,"children":-1},"Native Select","/docs/components/native-select","docs/components/native-select",{"title":238,"path":239,"stem":240,"new":17,"type":99,"children":-1},"Navigation Menu","/docs/components/navigation-menu","docs/components/navigation-menu",{"title":242,"path":243,"stem":244,"new":17,"type":99,"children":-1},"Number Field","/docs/components/number-field","docs/components/number-field",{"title":246,"path":247,"stem":248,"new":17,"type":99,"children":-1},"Pagination","/docs/components/pagination","docs/components/pagination",{"title":250,"path":251,"stem":252,"new":17,"type":99,"children":-1},"Pin Input","/docs/components/pin-input","docs/components/pin-input",{"title":254,"path":255,"stem":256,"new":17,"type":99,"children":-1},"Popover","/docs/components/popover","docs/components/popover",{"title":258,"path":259,"stem":260,"new":17,"type":99,"children":-1},"Progress","/docs/components/progress","docs/components/progress",{"title":262,"path":263,"stem":264,"new":17,"type":99,"children":-1},"Radio Group","/docs/components/radio-group","docs/components/radio-group",{"title":266,"path":267,"stem":268,"new":17,"type":99,"children":-1},"Range Calendar","/docs/components/range-calendar","docs/components/range-calendar",{"title":270,"path":271,"stem":272,"new":17,"type":99,"children":-1},"Resizable","/docs/components/resizable","docs/components/resizable",{"title":274,"path":275,"stem":276,"new":17,"type":99,"children":-1},"Scroll Area","/docs/components/scroll-area","docs/components/scroll-area",{"title":278,"path":279,"stem":280,"new":17,"type":99,"children":-1},"Select","/docs/components/select","docs/components/select",{"title":282,"path":283,"stem":284,"new":17,"type":99,"children":-1},"Separator","/docs/components/separator","docs/components/separator",{"title":286,"path":287,"stem":288,"new":17,"type":99,"children":-1},"Sheet","/docs/components/sheet","docs/components/sheet",{"title":290,"path":291,"stem":292,"new":17,"type":99,"children":-1},"Sidebar","/docs/components/sidebar","docs/components/sidebar",{"title":294,"path":295,"stem":296,"new":17,"type":99,"children":-1},"Skeleton","/docs/components/skeleton","docs/components/skeleton",{"title":298,"path":299,"stem":300,"new":17,"type":99,"children":-1},"Slider","/docs/components/slider","docs/components/slider",{"title":302,"path":303,"stem":304,"new":17,"type":99,"children":-1},"Sonner","/docs/components/sonner","docs/components/sonner",{"title":306,"path":307,"stem":308,"new":132,"type":99,"children":-1},"Spinner","/docs/components/spinner","docs/components/spinner",{"title":310,"path":311,"stem":312,"new":17,"type":99,"children":-1},"Stepper","/docs/components/stepper","docs/components/stepper",{"title":314,"path":315,"stem":316,"new":17,"type":99,"children":-1},"Switch","/docs/components/switch","docs/components/switch",{"title":318,"path":319,"stem":320,"new":17,"type":99,"children":-1},"Table","/docs/components/table","docs/components/table",{"title":322,"path":323,"stem":324,"new":17,"type":99,"children":-1},"Tabs","/docs/components/tabs","docs/components/tabs",{"title":326,"path":327,"stem":328,"new":17,"type":99,"children":-1},"Tags Input","/docs/components/tags-input","docs/components/tags-input",{"title":330,"path":331,"stem":332,"new":17,"type":99,"children":-1},"Textarea","/docs/components/textarea","docs/components/textarea",{"title":334,"path":335,"stem":336,"new":17,"type":99,"children":-1},"Toast","/docs/components/toast","docs/components/toast",{"title":338,"path":339,"stem":340,"new":17,"type":99,"children":-1},"Toggle","/docs/components/toggle","docs/components/toggle",{"title":342,"path":343,"stem":344,"new":17,"type":99,"children":-1},"Toggle Group","/docs/components/toggle-group","docs/components/toggle-group",{"title":346,"path":347,"stem":348,"new":17,"type":99,"children":-1},"Tooltip","/docs/components/tooltip","docs/components/tooltip",{"title":350,"path":351,"stem":352,"new":17,"type":99,"children":-1},"Typography","/docs/components/typography","docs/components/typography",{"title":20,"path":21,"stem":22,"children":354,"new":17,"type":11},[355,356,357,358,359],{"title":25,"path":26,"stem":27,"new":17,"type":18,"children":-1},{"title":29,"path":30,"stem":31,"new":17,"type":18,"children":-1},{"title":33,"path":34,"stem":35,"new":17,"type":18,"children":-1},{"title":37,"path":38,"stem":39,"new":17,"type":18,"children":-1},{"title":41,"path":42,"stem":43,"new":17,"type":18,"children":-1},{"title":53,"path":54,"stem":55,"children":361,"new":17,"type":11},[362,363,364,365],{"title":25,"path":58,"stem":59,"new":17,"type":18,"children":-1},{"title":29,"path":61,"stem":62,"new":17,"type":18,"children":-1},{"title":64,"path":65,"stem":66,"new":17,"type":18,"children":-1},{"title":33,"path":68,"stem":69,"new":17,"type":18,"children":-1},{"title":367,"path":368,"stem":369,"children":370,"new":17,"type":11},"Forms","/docs/forms","docs/forms",[371,375],{"title":372,"path":373,"stem":374,"new":17,"type":18,"children":-1},"VeeValidate","/docs/forms/vee-validate","docs/forms/01.vee-validate",{"title":376,"path":377,"stem":378,"new":17,"type":18,"children":-1},"TanStack Form","/docs/forms/tanstack-form","docs/forms/02.tanstack-form",{"title":380,"path":381,"stem":382,"children":383,"new":17,"type":11},"Registry","/docs/registry","docs/registry/index",[384,385,389,393,397,401],{"title":380,"path":381,"stem":382,"new":17,"type":18,"children":-1},{"title":386,"path":387,"stem":388,"new":17,"type":18,"children":-1},"Examples","/docs/registry/examples","docs/registry/examples",{"title":390,"path":391,"stem":392,"new":17,"type":18,"children":-1},"FAQ","/docs/registry/faq","docs/registry/faq",{"title":394,"path":395,"stem":396,"new":17,"type":18,"children":-1},"Getting Started","/docs/registry/getting-started","docs/registry/getting-started",{"title":398,"path":399,"stem":400,"new":17,"type":18,"children":-1},"registry-item.json","/docs/registry/registry-item-json","docs/registry/registry-item-json",{"title":402,"path":403,"stem":404,"new":17,"type":18,"children":-1},"registry.json","/docs/registry/registry-json","docs/registry/registry-json",{"repo":406},{"id":407,"name":408,"repo":409,"description":410,"createdAt":411,"updatedAt":412,"pushedAt":413,"stars":414,"watchers":415,"forks":416,"defaultBranch":417},658791894,"shadcn-vue","unovue/shadcn-vue","Vue port of shadcn-ui","2023-06-26T13:53:23Z","2026-04-06T17:33:41Z","2026-04-06T17:33:39Z",9706,37,634,"dev",{"id":419,"title":198,"body":420,"description":863,"extension":864,"links":865,"meta":866,"navigation":132,"new":17,"path":199,"rawbody":868,"seo":869,"stem":200,"__hash__":870},"content/docs/components/form.md",{"type":421,"value":422,"toc":851},"minimark",[423,446,449,452,471,494,499,509,564,572,580,584,594,598,649,652,710,714,720,725,732,741,747,759,763,776],[424,425,427],"callout",{"title":426},"We are not actively developing this component anymore.",[428,429,430,431,435,436,442,443,445],"p",{},"The Form component is an abstraction over the ",[432,433,434],"code",{},"vee-validate"," library. Going forward, we recommend using the ",[437,438,439],"a",{"href":195},[432,440,441],{},"\u003CField />"," component to build forms. See the ",[437,444,198],{"href":368}," documentation for more information.",[428,447,448],{},"Forms are tricky. They are one of the most common things you'll build in a web application, but also one of the most complex.",[428,450,451],{},"Well-designed HTML forms are:",[453,454,455,459,462,465,468],"ul",{},[456,457,458],"li",{},"Well-structured and semantically correct.",[456,460,461],{},"Easy to use and navigate (keyboard).",[456,463,464],{},"Accessible with ARIA attributes and proper labels.",[456,466,467],{},"Has support for client and server side validation.",[456,469,470],{},"Well-styled and consistent with the rest of the application.",[428,472,473,474,481,482,489,490,493],{},"In this guide, we will take a look at building forms with ",[437,475,479],{"href":476,"rel":477},"https://vee-validate.logaretm.com/v4/",[478],"nofollow",[432,480,434],{}," and ",[437,483,486],{"href":484,"rel":485},"https://zod.dev",[478],[432,487,488],{},"zod",". We're going to use a ",[432,491,492],{},"\u003CFormField>"," component to compose accessible forms using Reka UI components.",[495,496,498],"h2",{"id":497},"features","Features",[428,500,501,502,505,506,508],{},"The ",[432,503,504],{},"\u003CForm />"," component is a wrapper around the ",[432,507,434],{}," library. It provides a few things:",[453,510,511,514,521,527,534,537,558],{},[456,512,513],{},"Composable components for building forms.",[456,515,516,517,520],{},"A ",[432,518,519],{},"\u003CFormField />"," component for building controlled form fields.",[456,522,523,524,526],{},"Form validation using ",[432,525,488],{},".",[456,528,529,530,533],{},"Applies the correct ",[432,531,532],{},"aria"," attributes to form fields based on states, handle unique IDs",[456,535,536],{},"Built to work with all Reka UI components.",[456,538,539,540,542,543,550,551,526],{},"Bring your own schema library. We use ",[432,541,488],{}," but you can use any other supported schema validation you want, like ",[437,544,547],{"href":545,"rel":546},"https://github.com/jquense/yup",[478],[432,548,549],{},"yup"," or ",[437,552,555],{"href":553,"rel":554},"https://valibot.dev/",[478],[432,556,557],{},"valibot",[456,559,560],{},[561,562,563],"strong",{},"You have full control over the markup and styling.",[428,565,566,571],{},[437,567,569],{"href":476,"rel":568},[478],[432,570,434],{}," makes use of two flavors to add validation to your forms.",[453,573,574,577],{},[456,575,576],{},"Composition API",[456,578,579],{},"Higher-order components (HOC)",[495,581,583],{"id":582},"anatomy","Anatomy",[585,586,592],"pre",{"className":587,"code":589,"language":590,"meta":591},[588],"language-vue","\u003Ctemplate>\n  \u003CForm>\n    \u003CFormField>\n      \u003CFormItem>\n        \u003CFormLabel />\n        \u003CFormControl>\n        \u003C!-- any Form Input component or native input elements -->\n        \u003C/FormControl>\n        \u003CFormDescription />\n        \u003CFormMessage />\n      \u003C/FormItem>\n    \u003C/FormField>\n  \u003C/Form>\n\u003C/template>\n","vue","",[432,593,589],{"__ignoreMap":591},[495,595,597],{"id":596},"example","Example",[599,600,601,616,633],"tabs",{"default-value":99},[602,603,604,610],"tabs-list",{},[605,606,607],"tabs-trigger",{"value":99},[428,608,609],{},"Component",[605,611,613],{"value":612},"native",[428,614,615],{},"Native",[617,618,619,626],"tabs-content",{"value":99},[620,621,623,625],"h4",{"id":622},"input-component",[432,624,206],{}," Component",[585,627,631],{"className":628,"code":629,"language":590,"meta":630},[588],"\u003Ctemplate>\n  \u003CFormField v-slot=\"{ componentField }\">\n    \u003CFormItem>\n      \u003CFormLabel>Username\u003C/FormLabel>\n      \u003CFormControl>\n        \u003CInput placeholder=\"shadcn\" v-bind=\"componentField\" />\n      \u003C/FormControl>\n      \u003CFormDescription />\n      \u003CFormMessage />\n    \u003C/FormItem>\n  \u003C/FormField>\n\u003C/template>\n","showLineNumbers",[432,632,629],{"__ignoreMap":591},[617,634,635,643],{"value":612},[620,636,638,639,642],{"id":637},"native-input-element","native ",[432,640,641],{},"input"," element",[585,644,647],{"className":645,"code":646,"language":590,"meta":630},[588],"\u003Ctemplate>\n  \u003CFormField v-slot=\"{ field }\">\n    \u003CFormItem>\n      \u003CFormLabel>Username\u003C/FormLabel>\n      \u003CFormControl>\n        \u003Cinput placeholder=\"shadcn\" v-bind=\"field\">\n      \u003C/FormControl>\n      \u003CFormDescription />\n      \u003CFormMessage />\n    \u003C/FormItem>\n  \u003C/FormField>\n\u003C/template>\n",[432,648,646],{"__ignoreMap":591},[495,650,20],{"id":651},"installation",[599,653,655,667,677],{"default-value":654},"cli",[602,656,657,661],{},[605,658,659],{"value":654},[428,660,71],{},[605,662,664],{"value":663},"manual",[428,665,666],{},"Manual",[617,668,669],{"value":654},[585,670,675],{"className":671,"code":673,"language":674,"meta":591},[672],"language-bash","npx shadcn-vue@latest add form\n","bash",[432,676,673],{"__ignoreMap":591},[617,678,679],{"value":663},[680,681,682,688,694,705],"steps",{},[683,684,685],"step",{},[428,686,687],{},"Install the following dependency:",[585,689,692],{"className":690,"code":691,"language":674,"meta":591},[672],"npm install reka-ui vee-validate @vee-validate/zod zod\n",[432,693,691],{"__ignoreMap":591},[683,695,696],{},[428,697,698,699,704],{},"Copy and paste the ",[437,700,703],{"href":701,"rel":702},"https://github.com/unovue/shadcn-vue/tree/dev/apps/v4/registry/new-york-v4/ui/form",[478],"GitHub source code"," into your project.",[683,706,707],{},[428,708,709],{},"Update the import paths to match your project setup.",[495,711,713],{"id":712},"usage","Usage",[585,715,718],{"className":716,"code":717,"language":590,"meta":630},[588],"\u003Cscript setup lang=\"ts\">\nimport {\n  FormControl,\n  FormDescription,\n  FormField,\n  FormItem,\n  FormLabel,\n  FormMessage,\n} from '@/components/ui/form'\n\u003C/script>\n\n\u003Ctemplate>\n  \u003CFormField v-slot=\"{ componentField }\" name=\"username\">\n    \u003CFormItem>\n      \u003CFormLabel>Username\u003C/FormLabel>\n      \u003CFormControl>\n        \u003CInput placeholder=\"shadcn\" v-bind=\"componentField\" />\n      \u003C/FormControl>\n      \u003CFormDescription>\n        This is your public display name.\n      \u003C/FormDescription>\n      \u003CFormMessage />\n    \u003C/FormItem>\n  \u003C/FormField>\n\u003C/template>\n",[432,719,717],{"__ignoreMap":591},[721,722,724],"h3",{"id":723},"create-a-form-schema","Create a form schema",[428,726,727,728,526],{},"Define the shape of your form using a Zod schema. You can read more about using Zod in the ",[437,729,731],{"href":484,"rel":730},[478],"Zod documentation",[428,733,734,735,738,739],{},"Use ",[432,736,737],{},"@vee-validate/zod"," to integrate Zod schema validation with ",[432,740,434],{},[428,742,743,746],{},[432,744,745],{},"toTypedSchema"," also makes the form values and submitted values typed automatically and caters for both input and output types of that schema.",[585,748,757],{"className":749,"code":750,"highlights":751,"language":590,"meta":630},[588],"\u003Cscript setup lang=\"ts\">\nimport { toTypedSchema } from '@vee-validate/zod'\nimport * as z from 'zod'\n\nconst formSchema = toTypedSchema(z.object({\n  username: z.string().min(2).max(50),\n}))\n\u003C/script>\n",[752,753,754,755,756],2,3,5,6,7,[432,758,750],{"__ignoreMap":591},[721,760,762],{"id":761},"define-a-form","Define a form",[428,764,765,766,769,770,772,773,775],{},"Use the ",[432,767,768],{},"useForm"," composable from ",[432,771,434],{}," or use ",[432,774,504],{}," component to create a form.",[599,777,779,790,802,814,818,830,837,841,844],{"default-value":778},"composition",[602,780,781,786],{},[605,782,783],{"value":778},[428,784,785],{},"Composition",[605,787,788],{"value":99},[428,789,609],{},[617,791,792],{"value":778},[585,793,800],{"className":794,"code":795,"highlights":796,"language":590,"meta":630},[588],"\u003Cscript setup lang=\"ts\">\nimport { useForm } from 'vee-validate'\nimport { toTypedSchema } from '@vee-validate/zod'\nimport * as z from 'zod'\n\nimport {\n  FormControl,\n  FormDescription,\n  FormField,\n  FormItem,\n  FormLabel,\n  FormMessage\n} from '@/components/ui/form'\n\nconst formSchema = toTypedSchema(z.object({\n  username: z.string().min(2).max(50),\n}))\n\nconst form = useForm({\n  validationSchema: formSchema,\n})\n\nconst onSubmit = form.handleSubmit((values) => {\n  console.log('Form submitted!', values)\n})\n\u003C/script>\n\n\u003Ctemplate>\n  \u003Cform @submit=\"onSubmit\">\n    ...\n  \u003C/form>\n\u003C/template>\n",[752,797,798,799],19,20,21,[432,801,795],{"__ignoreMap":591},[617,803,804],{"value":99},[585,805,812],{"className":806,"code":807,"highlights":808,"language":590,"meta":630},[588],"\u003Cscript setup lang=\"ts\">\nimport { toTypedSchema } from '@vee-validate/zod'\nimport * as z from 'zod'\nimport {\n  Form,\n  FormControl,\n  FormDescription,\n  FormField,\n  FormItem,\n  FormLabel,\n  FormMessage\n} from '@/components/ui/form'\n\nconst formSchema = toTypedSchema(z.object({\n  username: z.string().min(2).max(50),\n}))\n\nfunction onSubmit(values) {\n  console.log('Form submitted!', values)\n}\n\u003C/script>\n\n\u003Ctemplate>\n  \u003CForm :validation-schema=\"formSchema\" @submit=\"onSubmit\">\n    ...\n  \u003C/Form>\n\u003C/template>\n",[754,809,810,811],24,25,26,[432,813,807],{"__ignoreMap":591},[721,815,817],{"id":816},"build-your-form","Build your form",[428,819,820,821,823,824,826,827,829],{},"Based on last step we can either use ",[432,822,504],{}," component or ",[432,825,768],{}," composable\n",[432,828,768],{}," is recommended because values are typed automatically",[585,831,835],{"className":832,"code":833,"highlights":834,"language":590,"meta":630},[588],"\u003Cscript setup lang=\"ts\">\nimport { toTypedSchema } from '@vee-validate/zod'\nimport { useForm } from 'vee-validate'\nimport * as z from 'zod'\n\nimport { Button } from '@/components/ui/button'\nimport {\n  FormControl,\n  FormDescription,\n  FormField,\n  FormItem,\n  FormLabel,\n  FormMessage,\n} from '@/components/ui/form'\nimport { Input } from '@/components/ui/input'\n\nconst formSchema = toTypedSchema(z.object({\n  username: z.string().min(2).max(50),\n}))\n\nconst form = useForm({\n  validationSchema: formSchema,\n})\n\nconst onSubmit = form.handleSubmit((values) => {\n  console.log('Form submitted!', values)\n})\n\u003C/script>\n\n\u003Ctemplate>\n  \u003Cform @submit=\"onSubmit\">\n    \u003CFormField v-slot=\"{ componentField }\" name=\"username\">\n      \u003CFormItem>\n        \u003CFormLabel>Username\u003C/FormLabel>\n        \u003CFormControl>\n          \u003CInput type=\"text\" placeholder=\"shadcn\" v-bind=\"componentField\" />\n        \u003C/FormControl>\n        \u003CFormDescription>\n          This is your public display name.\n        \u003C/FormDescription>\n        \u003CFormMessage />\n      \u003C/FormItem>\n    \u003C/FormField>\n    \u003CButton type=\"submit\">\n      Submit\n    \u003C/Button>\n  \u003C/form>\n\u003C/template>\n",[752],[432,836,833],{"__ignoreMap":591},[721,838,840],{"id":839},"done","Done",[428,842,843],{},"That's it. You now have a fully accessible form that is type-safe with client-side validation.",[845,846],"component-preview",{"className":847,"name":850},[848,849],"[&_[role=tablist]]:hidden","[&>div>div:first-child]:hidden","InputForm",{"title":591,"searchDepth":752,"depth":752,"links":852},[853,854,855,856,857],{"id":497,"depth":752,"text":498},{"id":582,"depth":752,"text":583},{"id":596,"depth":752,"text":597},{"id":651,"depth":752,"text":20},{"id":712,"depth":752,"text":713,"children":858},[859,860,861,862],{"id":723,"depth":753,"text":724},{"id":761,"depth":753,"text":762},{"id":816,"depth":753,"text":817},{"id":839,"depth":753,"text":840},"Building forms with VeeValidate and Zod.","md",null,{"primitive":867,"component":132},"https://vee-validate.logaretm.com/v4/guide/overview/","---\ntitle: Form\ndescription: Building forms with VeeValidate and Zod.\nprimitive: https://vee-validate.logaretm.com/v4/guide/overview/\ncomponent: true\n---\n\n::callout{title=\"We are not actively developing this component anymore.\"}\n\nThe Form component is an abstraction over the `vee-validate` library. Going forward, we recommend using the [`\u003CField />`](/docs/components/field) component to build forms. See the [Form](/docs/forms) documentation for more information.\n\n::\n\nForms are tricky. They are one of the most common things you'll build in a web application, but also one of the most complex.\n\nWell-designed HTML forms are:\n\n- Well-structured and semantically correct.\n- Easy to use and navigate (keyboard).\n- Accessible with ARIA attributes and proper labels.\n- Has support for client and server side validation.\n- Well-styled and consistent with the rest of the application.\n\nIn this guide, we will take a look at building forms with [`vee-validate`](https://vee-validate.logaretm.com/v4/) and [`zod`](https://zod.dev). We're going to use a `\u003CFormField>` component to compose accessible forms using Reka UI components.\n\n## Features\n\nThe `\u003CForm />` component is a wrapper around the `vee-validate` library. It provides a few things:\n\n- Composable components for building forms.\n- A `\u003CFormField />` component for building controlled form fields.\n- Form validation using `zod`.\n- Applies the correct `aria` attributes to form fields based on states, handle unique IDs\n- Built to work with all Reka UI components.\n- Bring your own schema library. We use `zod` but you can use any other supported schema validation you want, like [`yup`](https://github.com/jquense/yup) or [`valibot`](https://valibot.dev/).\n- **You have full control over the markup and styling.**\n\n[`vee-validate`](https://vee-validate.logaretm.com/v4/) makes use of two flavors to add validation to your forms.\n- Composition API\n- Higher-order components (HOC)\n\n## Anatomy\n\n```vue\n\u003Ctemplate>\n  \u003CForm>\n    \u003CFormField>\n      \u003CFormItem>\n        \u003CFormLabel />\n        \u003CFormControl>\n        \u003C!-- any Form Input component or native input elements -->\n        \u003C/FormControl>\n        \u003CFormDescription />\n        \u003CFormMessage />\n      \u003C/FormItem>\n    \u003C/FormField>\n  \u003C/Form>\n\u003C/template>\n```\n\n## Example\n\n::tabs{default-value=\"component\"}\n\n  ::tabs-list\n\n    ::tabs-trigger{value=\"component\"}\n    Component\n    ::\n\n    ::tabs-trigger{value=\"native\"}\n    Native\n    ::\n\n  ::\n\n  ::tabs-content{value=\"component\"}\n\n  #### `Input` Component\n\n  ```vue showLineNumbers\n  \u003Ctemplate>\n    \u003CFormField v-slot=\"{ componentField }\">\n      \u003CFormItem>\n        \u003CFormLabel>Username\u003C/FormLabel>\n        \u003CFormControl>\n          \u003CInput placeholder=\"shadcn\" v-bind=\"componentField\" />\n        \u003C/FormControl>\n        \u003CFormDescription />\n        \u003CFormMessage />\n      \u003C/FormItem>\n    \u003C/FormField>\n  \u003C/template>\n  ```\n\n  ::\n\n  ::tabs-content{value=\"native\"}\n\n  #### native `input` element\n\n  ```vue showLineNumbers\n  \u003Ctemplate>\n    \u003CFormField v-slot=\"{ field }\">\n      \u003CFormItem>\n        \u003CFormLabel>Username\u003C/FormLabel>\n        \u003CFormControl>\n          \u003Cinput placeholder=\"shadcn\" v-bind=\"field\">\n        \u003C/FormControl>\n        \u003CFormDescription />\n        \u003CFormMessage />\n      \u003C/FormItem>\n    \u003C/FormField>\n  \u003C/template>\n  ```\n\n  ::\n::\n\n## Installation\n\n::tabs{default-value=\"cli\"}\n\n  ::tabs-list\n\n    ::tabs-trigger{value=\"cli\"}\n    CLI\n    ::\n\n    ::tabs-trigger{value=\"manual\"}\n    Manual\n    ::\n\n  ::\n\n  ::tabs-content{value=\"cli\"}\n\n  ```bash\n  npx shadcn-vue@latest add form\n  ```\n\n  ::\n\n  ::tabs-content{value=\"manual\"}\n\n    ::steps\n      ::step\n      Install the following dependency:\n      ::\n\n      ```bash\n      npm install reka-ui vee-validate @vee-validate/zod zod\n      ```\n\n      ::step\n      Copy and paste the [GitHub source code](https://github.com/unovue/shadcn-vue/tree/dev/apps/v4/registry/new-york-v4/ui/form) into your project.\n      ::\n\n      ::step\n      Update the import paths to match your project setup.\n      ::\n    ::\n\n  ::\n\n::\n\n## Usage\n\n```vue showLineNumbers\n\u003Cscript setup lang=\"ts\">\nimport {\n  FormControl,\n  FormDescription,\n  FormField,\n  FormItem,\n  FormLabel,\n  FormMessage,\n} from '@/components/ui/form'\n\u003C/script>\n\n\u003Ctemplate>\n  \u003CFormField v-slot=\"{ componentField }\" name=\"username\">\n    \u003CFormItem>\n      \u003CFormLabel>Username\u003C/FormLabel>\n      \u003CFormControl>\n        \u003CInput placeholder=\"shadcn\" v-bind=\"componentField\" />\n      \u003C/FormControl>\n      \u003CFormDescription>\n        This is your public display name.\n      \u003C/FormDescription>\n      \u003CFormMessage />\n    \u003C/FormItem>\n  \u003C/FormField>\n\u003C/template>\n```\n\n### Create a form schema\n\n  Define the shape of your form using a Zod schema. You can read more about using Zod in the [Zod documentation](https://zod.dev).\n\n  Use `@vee-validate/zod` to integrate Zod schema validation with `vee-validate`\n\n  `toTypedSchema` also makes the form values and submitted values typed automatically and caters for both input and output types of that schema.\n\n  ```vue showLineNumbers {2-3,5-7}\n  \u003Cscript setup lang=\"ts\">\n  import { toTypedSchema } from '@vee-validate/zod'\n  import * as z from 'zod'\n\n  const formSchema = toTypedSchema(z.object({\n    username: z.string().min(2).max(50),\n  }))\n  \u003C/script>\n  ```\n\n### Define a form\n\n  Use the `useForm` composable from `vee-validate` or use `\u003CForm />` component to create a form.\n\n  ::tabs{default-value=\"composition\"}\n\n    ::tabs-list\n\n      ::tabs-trigger{value=\"composition\"}\n      Composition\n      ::\n\n      ::tabs-trigger{value=\"component\"}\n      Component\n      ::\n\n    ::\n\n    ::tabs-content{value=\"composition\"}\n\n    ```vue showLineNumbers {2,19-21}\n    \u003Cscript setup lang=\"ts\">\n    import { useForm } from 'vee-validate'\n    import { toTypedSchema } from '@vee-validate/zod'\n    import * as z from 'zod'\n\n    import {\n      FormControl,\n      FormDescription,\n      FormField,\n      FormItem,\n      FormLabel,\n      FormMessage\n    } from '@/components/ui/form'\n\n    const formSchema = toTypedSchema(z.object({\n      username: z.string().min(2).max(50),\n    }))\n\n    const form = useForm({\n      validationSchema: formSchema,\n    })\n\n    const onSubmit = form.handleSubmit((values) => {\n      console.log('Form submitted!', values)\n    })\n    \u003C/script>\n\n    \u003Ctemplate>\n      \u003Cform @submit=\"onSubmit\">\n        ...\n      \u003C/form>\n    \u003C/template>\n    ```\n\n    ::\n\n    ::tabs-content{value=\"component\"}\n\n    ```vue showLineNumbers {5,24-26}\n    \u003Cscript setup lang=\"ts\">\n    import { toTypedSchema } from '@vee-validate/zod'\n    import * as z from 'zod'\n    import {\n      Form,\n      FormControl,\n      FormDescription,\n      FormField,\n      FormItem,\n      FormLabel,\n      FormMessage\n    } from '@/components/ui/form'\n\n    const formSchema = toTypedSchema(z.object({\n      username: z.string().min(2).max(50),\n    }))\n\n    function onSubmit(values) {\n      console.log('Form submitted!', values)\n    }\n    \u003C/script>\n\n    \u003Ctemplate>\n      \u003CForm :validation-schema=\"formSchema\" @submit=\"onSubmit\">\n        ...\n      \u003C/Form>\n    \u003C/template>\n    ```\n\n    ::\n\n### Build your form\n\n  Based on last step we can either use `\u003CForm />` component or `useForm` composable\n  `useForm` is recommended because values are typed automatically\n\n  ```vue showLineNumbers {2}\n  \u003Cscript setup lang=\"ts\">\n  import { toTypedSchema } from '@vee-validate/zod'\n  import { useForm } from 'vee-validate'\n  import * as z from 'zod'\n\n  import { Button } from '@/components/ui/button'\n  import {\n    FormControl,\n    FormDescription,\n    FormField,\n    FormItem,\n    FormLabel,\n    FormMessage,\n  } from '@/components/ui/form'\n  import { Input } from '@/components/ui/input'\n\n  const formSchema = toTypedSchema(z.object({\n    username: z.string().min(2).max(50),\n  }))\n\n  const form = useForm({\n    validationSchema: formSchema,\n  })\n\n  const onSubmit = form.handleSubmit((values) => {\n    console.log('Form submitted!', values)\n  })\n  \u003C/script>\n\n  \u003Ctemplate>\n    \u003Cform @submit=\"onSubmit\">\n      \u003CFormField v-slot=\"{ componentField }\" name=\"username\">\n        \u003CFormItem>\n          \u003CFormLabel>Username\u003C/FormLabel>\n          \u003CFormControl>\n            \u003CInput type=\"text\" placeholder=\"shadcn\" v-bind=\"componentField\" />\n          \u003C/FormControl>\n          \u003CFormDescription>\n            This is your public display name.\n          \u003C/FormDescription>\n          \u003CFormMessage />\n        \u003C/FormItem>\n      \u003C/FormField>\n      \u003CButton type=\"submit\">\n        Submit\n      \u003C/Button>\n    \u003C/form>\n  \u003C/template>\n  ```\n\n### Done\n\n  That's it. You now have a fully accessible form that is type-safe with client-side validation.\n\n  ::component-preview\n  ---\n  name: InputForm\n  class: '[&_[role=tablist]]:hidden [&>div>div:first-child]:hidden'\n  ---\n  ::\n\n::\n\n\u003C!-- ## Extras\n\nThis example shows how to add motion to your forms with [Formkit AutoAnimate](https://auto-animate.formkit.com/)\n\n**Note:** You need to install `@formkit/auto-animate` to use this feature:\n\n```bash\nnpm install @formkit/auto-animate\n```\n\n::component-preview\n---\nname: InputFormAutoAnimate\n---\n:: -->\n",{"title":198,"description":863},"PUmg121XdEVgH6NDOQ0G2ptPggz9T7cSq4QFvhZC9Zw",[872,873],{"title":194,"path":195,"stem":196,"children":-1},{"title":202,"path":203,"stem":204,"children":-1},1775649989687]