[{"data":1,"prerenderedAt":548},["ShallowReactive",2],{"content-\u002Fdocs\u002Freading-the-form\u002Fthe-form":3},{"id":4,"title":5,"body":6,"description":534,"extension":535,"meta":536,"metaRows":537,"navigation":108,"path":543,"seo":544,"source":545,"stem":546,"__hash__":547},"docs\u002Fdocs\u002Freading-the-form\u002Fthe-form.md","The form",{"type":7,"value":8,"toc":525},"minimark",[9,13,20,23,38,126,132,136,141,179,190,194,217,226,230,289,297,301,372,376,406,409,413,442,459,463,521],[10,11,5],"h1",{"id":12},"the-form",[14,15,16],"blockquote",{},[17,18,19],"p",{},"Every form on the page is reactive and supports reading, mutations, validation, and submission handling, all typed against your schema.",[21,22],"docs-meta-table",{},[17,24,25,26,30,31,34,35,37],{},"One call, one form. ",[27,28,29],"code",{},"useForm"," hands back a reactive form that already knows your schema's shape, types, defaults, and validation. Everything below is a property of that single ",[27,32,33],{},"form"," handle: drillable value reads, per-leaf field state, error arrays, the submit handler, mutators. Wire one input, then reach for whatever else you need on the same ",[27,36,33],{},".",[39,40,45],"pre",{"className":41,"code":42,"language":43,"meta":44,"style":44},"language-ts shiki shiki-themes github-light github-dark","const schema = z.object({\n  email: z.email(),\n  age: z.number(),\n})\n\nconst form = useForm({ schema })\n","ts","",[27,46,47,74,86,97,103,110],{"__ignoreMap":44},[48,49,52,56,60,63,67,71],"span",{"class":50,"line":51},"line",1,[48,53,55],{"class":54},"szBVR","const",[48,57,59],{"class":58},"sj4cs"," schema",[48,61,62],{"class":54}," =",[48,64,66],{"class":65},"sVt8B"," z.",[48,68,70],{"class":69},"sScJk","object",[48,72,73],{"class":65},"({\n",[48,75,77,80,83],{"class":50,"line":76},2,[48,78,79],{"class":65},"  email: z.",[48,81,82],{"class":69},"email",[48,84,85],{"class":65},"(),\n",[48,87,89,92,95],{"class":50,"line":88},3,[48,90,91],{"class":65},"  age: z.",[48,93,94],{"class":69},"number",[48,96,85],{"class":65},[48,98,100],{"class":50,"line":99},4,[48,101,102],{"class":65},"})\n",[48,104,106],{"class":50,"line":105},5,[48,107,109],{"emptyLinePlaceholder":108},true,"\n",[48,111,113,115,118,120,123],{"class":50,"line":112},6,[48,114,55],{"class":54},[48,116,117],{"class":58}," form",[48,119,62],{"class":54},[48,121,122],{"class":69}," useForm",[48,124,125],{"class":65},"({ schema })\n",[17,127,128,129,131],{},"The demo below renders one form against an email + name schema. Type, blur, submit, reset; the panels on the right read the same ",[27,130,33],{}," you wire into the inputs.",[133,134],"docs-demo",{"label":135,"slug":12},"The Form Demo",[137,138,140],"h2",{"id":139},"reactive-reads","Reactive reads",[39,142,144],{"className":41,"code":143,"language":43,"meta":44,"style":44},"form.values \u002F\u002F drillable proxy: form.values.email\nform.fields \u002F\u002F per-leaf FieldState: form.fields.email.touched\nform.errors \u002F\u002F per-path errors: form.errors.email\nform.meta \u002F\u002F submit \u002F valid \u002F pending aggregates\n",[27,145,146,155,163,171],{"__ignoreMap":44},[48,147,148,151],{"class":50,"line":51},[48,149,150],{"class":65},"form.values ",[48,152,154],{"class":153},"sJ8bj","\u002F\u002F drillable proxy: form.values.email\n",[48,156,157,160],{"class":50,"line":76},[48,158,159],{"class":65},"form.fields ",[48,161,162],{"class":153},"\u002F\u002F per-leaf FieldState: form.fields.email.touched\n",[48,164,165,168],{"class":50,"line":88},[48,166,167],{"class":65},"form.errors ",[48,169,170],{"class":153},"\u002F\u002F per-path errors: form.errors.email\n",[48,172,173,176],{"class":50,"line":99},[48,174,175],{"class":65},"form.meta ",[48,177,178],{"class":153},"\u002F\u002F submit \u002F valid \u002F pending aggregates\n",[17,180,181,182,185,186,189],{},"Every read inside a reactive scope (template, ",[27,183,184],{},"computed",", ",[27,187,188],{},"watchEffect",") is tracked. Vue re-runs the consumer when the underlying storage changes.",[137,191,193],{"id":192},"directive-surface","Directive surface",[39,195,197],{"className":41,"code":196,"language":43,"meta":44,"style":44},"form.register('email')\n",[27,198,199],{"__ignoreMap":44},[48,200,201,204,207,210,214],{"class":50,"line":51},[48,202,203],{"class":65},"form.",[48,205,206],{"class":69},"register",[48,208,209],{"class":65},"(",[48,211,213],{"class":212},"sZZnC","'email'",[48,215,216],{"class":65},")\n",[17,218,219,221,222,225],{},[27,220,206],{}," returns the RegisterValue the ",[27,223,224],{},"v-register"," directive consumes. Hand it to any native input: text, number, select, checkbox, radio, textarea, file.",[137,227,229],{"id":228},"submission","Submission",[39,231,233],{"className":41,"code":232,"language":43,"meta":44,"style":44},"const onSubmit = form.handleSubmit(async (values) => {\n  await api.signup(values)\n})\n",[27,234,235,271,285],{"__ignoreMap":44},[48,236,237,239,242,244,247,250,252,255,258,262,265,268],{"class":50,"line":51},[48,238,55],{"class":54},[48,240,241],{"class":58}," onSubmit",[48,243,62],{"class":54},[48,245,246],{"class":65}," form.",[48,248,249],{"class":69},"handleSubmit",[48,251,209],{"class":65},[48,253,254],{"class":54},"async",[48,256,257],{"class":65}," (",[48,259,261],{"class":260},"s4XuR","values",[48,263,264],{"class":65},") ",[48,266,267],{"class":54},"=>",[48,269,270],{"class":65}," {\n",[48,272,273,276,279,282],{"class":50,"line":76},[48,274,275],{"class":54},"  await",[48,277,278],{"class":65}," api.",[48,280,281],{"class":69},"signup",[48,283,284],{"class":65},"(values)\n",[48,286,287],{"class":50,"line":88},[48,288,102],{"class":65},[17,290,291,293,294,37],{},[27,292,249],{}," gates dispatch on validation. Returns a handler ready for ",[27,295,296],{},"\u003Cform @submit.prevent>",[137,298,300],{"id":299},"per-field-writes","Per-field writes",[39,302,304],{"className":41,"code":303,"language":43,"meta":44,"style":44},"import { unset } from 'attaform\u002Fzod'\n\nform.setValue('email', 'new@example.com')\nform.setValue('age', unset) \u002F\u002F flag any path blank by passing the sentinel\nform.resetField('email')\n",[27,305,306,320,324,342,359],{"__ignoreMap":44},[48,307,308,311,314,317],{"class":50,"line":51},[48,309,310],{"class":54},"import",[48,312,313],{"class":65}," { unset } ",[48,315,316],{"class":54},"from",[48,318,319],{"class":212}," 'attaform\u002Fzod'\n",[48,321,322],{"class":50,"line":76},[48,323,109],{"emptyLinePlaceholder":108},[48,325,326,328,331,333,335,337,340],{"class":50,"line":88},[48,327,203],{"class":65},[48,329,330],{"class":69},"setValue",[48,332,209],{"class":65},[48,334,213],{"class":212},[48,336,185],{"class":65},[48,338,339],{"class":212},"'new@example.com'",[48,341,216],{"class":65},[48,343,344,346,348,350,353,356],{"class":50,"line":99},[48,345,203],{"class":65},[48,347,330],{"class":69},[48,349,209],{"class":65},[48,351,352],{"class":212},"'age'",[48,354,355],{"class":65},", unset) ",[48,357,358],{"class":153},"\u002F\u002F flag any path blank by passing the sentinel\n",[48,360,361,363,366,368,370],{"class":50,"line":105},[48,362,203],{"class":65},[48,364,365],{"class":69},"resetField",[48,367,209],{"class":65},[48,369,213],{"class":212},[48,371,216],{"class":65},[137,373,375],{"id":374},"form-level-operations","Form-level operations",[39,377,379],{"className":41,"code":378,"language":43,"meta":44,"style":44},"form.reset() \u002F\u002F re-seed every path from defaultValues\nform.clear() \u002F\u002F wipe every path to its falsy-for-type baseline\n",[27,380,381,394],{"__ignoreMap":44},[48,382,383,385,388,391],{"class":50,"line":51},[48,384,203],{"class":65},[48,386,387],{"class":69},"reset",[48,389,390],{"class":65},"() ",[48,392,393],{"class":153},"\u002F\u002F re-seed every path from defaultValues\n",[48,395,396,398,401,403],{"class":50,"line":76},[48,397,203],{"class":65},[48,399,400],{"class":69},"clear",[48,402,390],{"class":65},[48,404,405],{"class":153},"\u002F\u002F wipe every path to its falsy-for-type baseline\n",[17,407,408],{},"Every write path runs the same validation, dirty-tracking, and history pipeline.",[137,410,412],{"id":411},"validation","Validation",[39,414,416],{"className":41,"code":415,"language":43,"meta":44,"style":44},"form.validate() \u002F\u002F sync pass\nform.validateAsync() \u002F\u002F awaits async refinements\n",[27,417,418,430],{"__ignoreMap":44},[48,419,420,422,425,427],{"class":50,"line":51},[48,421,203],{"class":65},[48,423,424],{"class":69},"validate",[48,426,390],{"class":65},[48,428,429],{"class":153},"\u002F\u002F sync pass\n",[48,431,432,434,437,439],{"class":50,"line":76},[48,433,203],{"class":65},[48,435,436],{"class":69},"validateAsync",[48,438,390],{"class":65},[48,440,441],{"class":153},"\u002F\u002F awaits async refinements\n",[17,443,444,445,448,449,455,456,458],{},"Validators emit into ",[27,446,447],{},"form.errors"," on completion. The same pipeline runs inside ",[450,451,453],"a",{"href":452},"\u002Fdocs\u002Fsubmitting\u002Fhandle-submit",[27,454,249],{}," before your success callback fires, so reach for ",[27,457,424],{}," directly only when you need a check outside the submit cycle.",[137,460,462],{"id":461},"where-to-next","Where to next",[464,465,466,475,484,493,502,511],"ul",{},[467,468,469,474],"li",{},[450,470,472],{"href":471},"\u002Fdocs\u002Freading-the-form\u002Fvalues",[27,473,261],{},": drillable reads.",[467,476,477,483],{},[450,478,480],{"href":479},"\u002Fdocs\u002Freading-the-form\u002Ffields",[27,481,482],{},"fields",": per-leaf state, validation, and DOM handles.",[467,485,486,492],{},[450,487,489],{"href":488},"\u002Fdocs\u002Freading-the-form\u002Ferrors",[27,490,491],{},"errors",": per-path error reads.",[467,494,495,501],{},[450,496,498],{"href":497},"\u002Fdocs\u002Freading-the-form\u002Fmeta",[27,499,500],{},"meta",": the form-level aggregation plus the submission cycle.",[467,503,504,510],{},[450,505,507],{"href":506},"\u002Fdocs\u002Freading-the-form\u002Fto-ref",[27,508,509],{},"toRef",": the ref-shaped escape hatch.",[467,512,513,520],{},[450,514,516,517,519],{"href":515},"\u002Fdocs\u002Fbinding-inputs\u002Fv-register","The ",[27,518,224],{}," directive",": the bind layer.",[522,523,524],"style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":44,"searchDepth":76,"depth":76,"links":526},[527,528,529,530,531,532,533],{"id":139,"depth":76,"text":140},{"id":192,"depth":76,"text":193},{"id":228,"depth":76,"text":229},{"id":299,"depth":76,"text":300},{"id":374,"depth":76,"text":375},{"id":411,"depth":76,"text":412},{"id":461,"depth":76,"text":462},"useForm returns one reactive form carrying values, fields, errors, meta, register, handleSubmit, setValue, and reset, all typed against your schema.","md",{},[538,541],{"label":539,"value":540},"Category","Return shape",{"label":542,"value":29,"kind":27},"Returned by","\u002Fdocs\u002Freading-the-form\u002Fthe-form",{"title":5,"description":534},null,"docs\u002Freading-the-form\u002Fthe-form","Ue5E0t2B0fU_CKSheb47o9xtGO1eqRcJHIy2AYwQDw8",1780949758193]