[{"data":1,"prerenderedAt":736},["ShallowReactive",2],{"content-\u002Fdocs\u002Fbinding-inputs\u002Fv-register":3},{"id":4,"title":5,"body":6,"description":718,"extension":719,"meta":720,"metaRows":721,"navigation":730,"path":731,"seo":732,"source":733,"stem":734,"__hash__":735},"docs\u002Fdocs\u002Fbinding-inputs\u002Fv-register.md","The v-register directive",{"type":7,"value":8,"toc":707},"minimark",[9,19,30,33,46,50,54,57,110,113,185,189,195,221,225,240,298,313,317,328,400,409,414,427,507,524,528,534,578,581,585,592,613,624,628,703],[10,11,13,14,18],"h1",{"id":12},"the-v-register-directive","The ",[15,16,17],"code",{},"v-register"," directive",[20,21,22],"blockquote",{},[23,24,25,26,29],"p",{},"One directive binds a native input to a schema path. The ",[15,27,28],{},"\u003Cinput>"," stays native; Attaform sits at the directive layer.",[31,32],"docs-meta-table",{},[23,34,35,36,39,40,45],{},"Click the input, type a few characters, blur, refocus. The four ",[15,37,38],{},"form.fields.email.*"," bits in the table below flip with each interaction. The directive surfaces every signal the schema-aware layer needs without you wiring a single event listener; the ",[41,42,44],"a",{"href":43},"#what-it-does","What it does"," section unpacks the four pieces of plumbing.",[47,48],"docs-demo",{"label":49,"slug":17},"v-register Demo",[51,52,44],"h2",{"id":53},"what-it-does",[23,55,56],{},"Bind any native input to a schema path:",[58,59,64],"pre",{"className":60,"code":61,"language":62,"meta":63,"style":63},"language-vue shiki shiki-themes github-light github-dark","\u003Cinput v-register=\"form.register('email')\" \u002F>\n","vue","",[15,65,66],{"__ignoreMap":63},[67,68,71,75,79,83,86,90,93,96,99,102,105,107],"span",{"class":69,"line":70},"line",1,[67,72,74],{"class":73},"sVt8B","\u003C",[67,76,78],{"class":77},"s9eBZ","input",[67,80,82],{"class":81},"sScJk"," v-register",[67,84,85],{"class":73},"=",[67,87,89],{"class":88},"sZZnC","\"",[67,91,92],{"class":73},"form.",[67,94,95],{"class":81},"register",[67,97,98],{"class":73},"(",[67,100,101],{"class":88},"'email'",[67,103,104],{"class":73},")",[67,106,89],{"class":88},[67,108,109],{"class":73}," \u002F>\n",[23,111,112],{},"The directive runs four pieces of plumbing for you:",[114,115,116,128,148,162],"ol",{},[117,118,119,123,124,127],"li",{},[120,121,122],"strong",{},"Reads"," the current value from ",[15,125,126],{},"form.values.\u003Cpath>"," and writes it into the DOM input on initial render and on every reactive update.",[117,129,130,133,134,136,137,139,140,143,144,147],{},[120,131,132],{},"Writes"," back to ",[15,135,126],{}," on every ",[15,138,78],{}," event (or ",[15,141,142],{},"change"," \u002F ",[15,145,146],{},"blur"," with modifiers).",[117,149,150,153,154,157,158,161],{},[120,151,152],{},"Coerces"," the DOM string to the schema's leaf type: ",[15,155,156],{},"type=\"number\""," inputs land in storage as a number, checkboxes as a boolean, radio groups pick the option ",[15,159,160],{},"value",".",[117,163,164,167,168,171,172,171,175,171,178,181,182,161],{},[120,165,166],{},"Tracks"," field state (",[15,169,170],{},"touched",", ",[15,173,174],{},"focused",[15,176,177],{},"blurred",[15,179,180],{},"blank",") and surfaces it through ",[15,183,184],{},"form.fields.\u003Cpath>",[51,186,188],{"id":187},"auto-installed","Auto-installed",[23,190,191,194],{},[15,192,193],{},"createAttaform()"," registers the directive globally, in bare Vue and in Nuxt. You don't import it.",[23,196,197,198,201,202,208,209,211,212,218,219,161],{},"If you wrap inputs inside a component whose root is ",[120,199,200],{},"not"," the input itself, ",[41,203,205],{"href":204},"\u002Fdocs\u002Fbinding-inputs\u002Fuse-register",[15,206,207],{},"useRegister"," re-binds ",[15,210,17],{}," onto an inner native element. For compound components binding multiple paths, prefer ",[41,213,215],{"href":214},"\u002Fdocs\u002Freading-the-form\u002Fthe-form",[15,216,217],{},"injectForm"," over ",[15,220,207],{},[51,222,224],{"id":223},"reading-errors-per-field","Reading errors per field",[23,226,227,228,231,232,235,236,239],{},"The directive's binding pair is read-and-error: ",[15,229,230],{},"form.register('email')"," for the input, ",[15,233,234],{},"form.fields.email.firstError?.message"," for the message, gated by ",[15,237,238],{},"form.fields.email.showErrors"," so a half-typed value doesn't get yelled at on first paint.",[58,241,243],{"className":60,"code":242,"language":62,"meta":63,"style":63},"\u003Cinput v-register=\"form.register('email')\" \u002F>\n\u003Cp v-if=\"form.fields.email.showErrors\">{{ form.fields.email.firstError?.message }}\u003C\u002Fp>\n",[15,244,245,271],{"__ignoreMap":63},[67,246,247,249,251,253,255,257,259,261,263,265,267,269],{"class":69,"line":70},[67,248,74],{"class":73},[67,250,78],{"class":77},[67,252,82],{"class":81},[67,254,85],{"class":73},[67,256,89],{"class":88},[67,258,92],{"class":73},[67,260,95],{"class":81},[67,262,98],{"class":73},[67,264,101],{"class":88},[67,266,104],{"class":73},[67,268,89],{"class":88},[67,270,109],{"class":73},[67,272,274,276,278,282,284,286,288,290,293,295],{"class":69,"line":273},2,[67,275,74],{"class":73},[67,277,23],{"class":77},[67,279,281],{"class":280},"szBVR"," v-if",[67,283,85],{"class":73},[67,285,89],{"class":88},[67,287,238],{"class":73},[67,289,89],{"class":88},[67,291,292],{"class":73},">{{ form.fields.email.firstError?.message }}\u003C\u002F",[67,294,23],{"class":77},[67,296,297],{"class":73},">\n",[23,299,300,301,304,305,308,309,312],{},"The raw ",[15,302,303],{},"form.errors.email"," Proxy stays available as ",[15,306,307],{},"ValidationError[]"," when you need the full array, empty when the field is valid. ",[15,310,311],{},"form.fields"," is the display-ergonomics layer over the same data.",[51,314,316],{"id":315},"accessibility-handled","Accessibility, handled",[23,318,319,320,322,323,327],{},"By default, ",[15,321,17],{}," keeps a field's aria attributes in sync with its ",[41,324,326],{"href":325},"\u002Fdocs\u002Fvalidation\u002Fshowing-errors","display state",", so assistive technology announces exactly what sighted users see, with no extra wiring:",[329,330,331,344],"table",{},[332,333,334],"thead",{},[335,336,337,341],"tr",{},[338,339,340],"th",{},"Attribute",[338,342,343],{},"Set when",[345,346,347,365,380,390],"tbody",{},[335,348,349,355],{},[350,351,352],"td",{},[15,353,354],{},"aria-invalid",[350,356,357,358,361,362],{},"the field's ",[15,359,360],{},"displayState"," is ",[15,363,364],{},"'error'",[335,366,367,372],{},[350,368,369],{},[15,370,371],{},"aria-busy",[350,373,357,374,361,376,379],{},[15,375,360],{},[15,377,378],{},"'pending'"," (an async check is running)",[335,381,382,387],{},[350,383,384],{},[15,385,386],{},"aria-required",[350,388,389],{},"the schema marks the path required",[335,391,392,397],{},[350,393,394],{},[15,395,396],{},"aria-describedby",[350,398,399],{},"points at the field's error id while in the error state",[23,401,402,403,405,406,408],{},"These track the same gated ",[15,404,360],{}," that drives ",[15,407,238],{},", so the announcement and the visible message reveal together, never on a half-typed value. The required and invalid states are emitted during SSR too, so a server-rendered form is accessible before hydration.",[410,411,413],"h3",{"id":412},"wiring-the-error-element","Wiring the error element",[23,415,416,417,419,420,426],{},"Auto-aria sets ",[15,418,396],{}," to ",[41,421,423],{"href":422},"\u002Fdocs\u002Freading-the-form\u002Ffields",[15,424,425],{},"form.fields.\u003Cpath>.aria.errorId",". Put that id on your error element so the reference resolves:",[58,428,430],{"className":60,"code":429,"language":62,"meta":63,"style":63},"\u003Cinput v-register=\"form.register('email')\" \u002F>\n\u003Cp v-if=\"form.fields.email.showErrors\" :id=\"form.fields.email.aria.errorId\">\n  {{ form.fields.email.firstError?.message }}\n\u003C\u002Fp>\n",[15,431,432,458,491,497],{"__ignoreMap":63},[67,433,434,436,438,440,442,444,446,448,450,452,454,456],{"class":69,"line":70},[67,435,74],{"class":73},[67,437,78],{"class":77},[67,439,82],{"class":81},[67,441,85],{"class":73},[67,443,89],{"class":88},[67,445,92],{"class":73},[67,447,95],{"class":81},[67,449,98],{"class":73},[67,451,101],{"class":88},[67,453,104],{"class":73},[67,455,89],{"class":88},[67,457,109],{"class":73},[67,459,460,462,464,466,468,470,472,474,477,480,482,484,487,489],{"class":69,"line":273},[67,461,74],{"class":73},[67,463,23],{"class":77},[67,465,281],{"class":280},[67,467,85],{"class":73},[67,469,89],{"class":88},[67,471,238],{"class":73},[67,473,89],{"class":88},[67,475,476],{"class":73}," :",[67,478,479],{"class":81},"id",[67,481,85],{"class":73},[67,483,89],{"class":88},[67,485,486],{"class":73},"form.fields.email.aria.errorId",[67,488,89],{"class":88},[67,490,297],{"class":73},[67,492,494],{"class":69,"line":493},3,[67,495,496],{"class":73},"  {{ form.fields.email.firstError?.message }}\n",[67,498,500,503,505],{"class":69,"line":499},4,[67,501,502],{"class":73},"\u003C\u002F",[67,504,23],{"class":77},[67,506,297],{"class":73},[23,508,509,511,512,515,516,519,520,523],{},[15,510,486],{}," is stable for the field and unique across every mount on the page (it folds in the form's ",[15,513,514],{},"instanceId","), so two instances of the same form never cross their references. The companion ",[15,517,518],{},"form.fields.email.id"," wires a ",[15,521,522],{},"\u003Clabel :for>"," to the input when you need one.",[410,525,527],{"id":526},"respect-your-markup","Respect your markup",[23,529,530,531,533],{},"Write any aria attribute yourself and Attaform leaves it alone, for that one attribute. Author ",[15,532,354],{}," while the other three stay automatic:",[58,535,537],{"className":60,"code":536,"language":62,"meta":63,"style":63},"\u003Cinput v-register=\"form.register('email')\" :aria-invalid=\"hasCustomError\" \u002F>\n",[15,538,539],{"__ignoreMap":63},[67,540,541,543,545,547,549,551,553,555,557,559,561,563,565,567,569,571,574,576],{"class":69,"line":70},[67,542,74],{"class":73},[67,544,78],{"class":77},[67,546,82],{"class":81},[67,548,85],{"class":73},[67,550,89],{"class":88},[67,552,92],{"class":73},[67,554,95],{"class":81},[67,556,98],{"class":73},[67,558,101],{"class":88},[67,560,104],{"class":73},[67,562,89],{"class":88},[67,564,476],{"class":73},[67,566,354],{"class":81},[67,568,85],{"class":73},[67,570,89],{"class":88},[67,572,573],{"class":73},"hasCustomError",[67,575,89],{"class":88},[67,577,109],{"class":73},[23,579,580],{},"The check happens per attribute and per binding, so reaching for one escape hatch never disables the rest.",[410,582,584],{"id":583},"turning-it-off","Turning it off",[23,586,587,588,591],{},"One knob, ",[15,589,590],{},"autoAria",", at three tiers; the narrower tier wins:",[593,594,595,601,607],"ul",{},[117,596,597,598,161],{},"Per binding: ",[15,599,600],{},"form.register('email', { autoAria: false })",[117,602,603,604,161],{},"Per form: ",[15,605,606],{},"useForm({ schema, autoAria: false })",[117,608,609,610,161],{},"App-wide: ",[15,611,612],{},"createAttaform({ defaults: { autoAria: false } })",[23,614,615,616,619,620,623],{},"A narrower tier overrides the wider one in either direction, so a single binding can re-enable management with ",[15,617,618],{},"{ autoAria: true }"," even when the form opted out. Any tier set to ",[15,621,622],{},"false"," hands every aria attribute back to your markup; an authored attribute is always preserved regardless.",[51,625,627],{"id":626},"where-to-next","Where to next",[593,629,630,640,657,664,673,682,697],{},[117,631,632,636,637,639],{},[41,633,634],{"href":204},[15,635,207],{},": the composable for re-binding ",[15,638,17],{}," onto an inner native element inside a wrapper component.",[117,641,642,646,647,171,650,171,653,656],{},[41,643,645],{"href":644},"\u002Fdocs\u002Fbinding-inputs\u002Fmodifiers","Modifiers",": ",[15,648,649],{},".lazy",[15,651,652],{},".trim",[15,654,655],{},".number"," for tuning the write side.",[117,658,659,663],{},[41,660,662],{"href":661},"\u002Fdocs\u002Fbinding-inputs\u002Fcoercion","Schema-driven coercion",": how DOM strings land at the right leaf type.",[117,665,666,672],{},[41,667,669],{"href":668},"\u002Fdocs\u002Freading-the-form\u002Fvalues",[15,670,671],{},"values",": what the directive writes into.",[117,674,675,681],{},[41,676,678],{"href":677},"\u002Fdocs\u002Freading-the-form\u002Ferrors",[15,679,680],{},"errors",": the error reads paired with each registered path.",[117,683,684,689,690,692,693,696],{},[41,685,686],{"href":422},[15,687,688],{},"fields",": the ",[15,691,479],{}," and ",[15,694,695],{},"aria"," ids the accessibility wiring reads from.",[117,698,699,702],{},[41,700,701],{"href":325},"Display state and showing errors",": the gated verdict the aria attributes track.",[704,705,706],"style",{},"html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}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 .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}",{"title":63,"searchDepth":273,"depth":273,"links":708},[709,710,711,712,717],{"id":53,"depth":273,"text":44},{"id":187,"depth":273,"text":188},{"id":223,"depth":273,"text":224},{"id":315,"depth":273,"text":316,"children":713},[714,715,716],{"id":412,"depth":493,"text":413},{"id":526,"depth":493,"text":527},{"id":583,"depth":493,"text":584},{"id":626,"depth":273,"text":627},"v-register binds a native input to a schema path. The directive handles the value sync, the coercion, the dirty-tracking, and the focus pass while your input stays native.","md",{},[722,725,728],{"label":723,"value":724},"Category","Directive",{"label":726,"value":727},"Element","input \u002F select \u002F textarea \u002F file",{"label":188,"value":729},"Yes",true,"\u002Fdocs\u002Fbinding-inputs\u002Fv-register",{"title":5,"description":718},null,"docs\u002Fbinding-inputs\u002Fv-register","gmw4XgTHt9TZQvG-bRIIWF1hrflAQ7fUSPfChH17rIc",1780949758883]