[{"data":1,"prerenderedAt":1216},["ShallowReactive",2],{"content-\u002Fdocs\u002Frecipes\u002Fform-context":3},{"id":4,"title":5,"body":6,"description":1209,"extension":1210,"meta":1211,"navigation":122,"path":1212,"seo":1213,"stem":1214,"__hash__":1215},"docs\u002Fdocs\u002Frecipes\u002Fform-context.md","Form context in nested components",{"type":7,"value":8,"toc":1197},"minimark",[9,13,34,39,42,456,459,672,686,690,693,851,862,872,875,917,923,931,948,1000,1014,1020,1099,1106,1109,1113,1116,1134,1138,1143,1166,1170,1180,1193],[10,11,5],"h1",{"id":12},"form-context-in-nested-components",[14,15,16,17,21,22,25,26,29,30,33],"p",{},"Splitting a form across components? Don't prop-drill ",[18,19,20],"code",{},"register"," \u002F\n",[18,23,24],{},"errors"," \u002F ",[18,27,28],{},"handleSubmit"," through every layer. Call\n",[18,31,32],{},"injectForm()"," in any descendant and get the same handle back.",[35,36,38],"h2",{"id":37},"the-common-case-ambient-resolution","The common case — ambient resolution",[14,40,41],{},"Parent owns the form:",[43,44,49],"pre",{"className":45,"code":46,"language":47,"meta":48,"style":48},"language-vue shiki shiki-themes github-light github-dark","\u003C!-- SignupForm.vue -->\n\u003Cscript setup lang=\"ts\">\n  import { useForm } from 'attaform\u002Fzod'\n  import { z } from 'zod'\n\n  interface Form {\n    email: string\n    profile: { name: string; age: number }\n  }\n\n  const schema = z.object({\n    email: z.email(),\n    profile: z.object({ name: z.string(), age: z.number() }),\n  })\n\n  \u002F\u002F Anonymous useForm — ambient mode. Pass `key: 'signup'` instead\n  \u002F\u002F when descendants should reach it via `injectForm\u003CForm>('signup')`.\n  const { handleSubmit } = useForm\u003CForm>({ schema })\n  const onSubmit = handleSubmit(async (values) => {\n    await api.post('\u002Fsignup', values)\n  })\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cform @submit.prevent=\"onSubmit\">\n    \u003CEmailRow \u002F>\n    \u003CProfileGroup \u002F>\n    \u003Cbutton>Sign up\u003C\u002Fbutton>\n  \u003C\u002Fform>\n\u003C\u002Ftemplate>\n","vue","",[18,50,51,60,88,104,117,124,136,150,183,189,194,215,227,250,256,261,267,273,298,331,351,356,366,371,381,400,412,422,437,447],{"__ignoreMap":48},[52,53,56],"span",{"class":54,"line":55},"line",1,[52,57,59],{"class":58},"sJ8bj","\u003C!-- SignupForm.vue -->\n",[52,61,63,67,71,75,78,81,85],{"class":54,"line":62},2,[52,64,66],{"class":65},"sVt8B","\u003C",[52,68,70],{"class":69},"s9eBZ","script",[52,72,74],{"class":73},"sScJk"," setup",[52,76,77],{"class":73}," lang",[52,79,80],{"class":65},"=",[52,82,84],{"class":83},"sZZnC","\"ts\"",[52,86,87],{"class":65},">\n",[52,89,91,95,98,101],{"class":54,"line":90},3,[52,92,94],{"class":93},"szBVR","  import",[52,96,97],{"class":65}," { useForm } ",[52,99,100],{"class":93},"from",[52,102,103],{"class":83}," 'attaform\u002Fzod'\n",[52,105,107,109,112,114],{"class":54,"line":106},4,[52,108,94],{"class":93},[52,110,111],{"class":65}," { z } ",[52,113,100],{"class":93},[52,115,116],{"class":83}," 'zod'\n",[52,118,120],{"class":54,"line":119},5,[52,121,123],{"emptyLinePlaceholder":122},true,"\n",[52,125,127,130,133],{"class":54,"line":126},6,[52,128,129],{"class":93},"  interface",[52,131,132],{"class":73}," Form",[52,134,135],{"class":65}," {\n",[52,137,139,143,146],{"class":54,"line":138},7,[52,140,142],{"class":141},"s4XuR","    email",[52,144,145],{"class":93},":",[52,147,149],{"class":148},"sj4cs"," string\n",[52,151,153,156,158,161,164,166,169,172,175,177,180],{"class":54,"line":152},8,[52,154,155],{"class":141},"    profile",[52,157,145],{"class":93},[52,159,160],{"class":65}," { ",[52,162,163],{"class":141},"name",[52,165,145],{"class":93},[52,167,168],{"class":148}," string",[52,170,171],{"class":65},"; ",[52,173,174],{"class":141},"age",[52,176,145],{"class":93},[52,178,179],{"class":148}," number",[52,181,182],{"class":65}," }\n",[52,184,186],{"class":54,"line":185},9,[52,187,188],{"class":65},"  }\n",[52,190,192],{"class":54,"line":191},10,[52,193,123],{"emptyLinePlaceholder":122},[52,195,197,200,203,206,209,212],{"class":54,"line":196},11,[52,198,199],{"class":93},"  const",[52,201,202],{"class":148}," schema",[52,204,205],{"class":93}," =",[52,207,208],{"class":65}," z.",[52,210,211],{"class":73},"object",[52,213,214],{"class":65},"({\n",[52,216,218,221,224],{"class":54,"line":217},12,[52,219,220],{"class":65},"    email: z.",[52,222,223],{"class":73},"email",[52,225,226],{"class":65},"(),\n",[52,228,230,233,235,238,241,244,247],{"class":54,"line":229},13,[52,231,232],{"class":65},"    profile: z.",[52,234,211],{"class":73},[52,236,237],{"class":65},"({ name: z.",[52,239,240],{"class":73},"string",[52,242,243],{"class":65},"(), age: z.",[52,245,246],{"class":73},"number",[52,248,249],{"class":65},"() }),\n",[52,251,253],{"class":54,"line":252},14,[52,254,255],{"class":65},"  })\n",[52,257,259],{"class":54,"line":258},15,[52,260,123],{"emptyLinePlaceholder":122},[52,262,264],{"class":54,"line":263},16,[52,265,266],{"class":58},"  \u002F\u002F Anonymous useForm — ambient mode. Pass `key: 'signup'` instead\n",[52,268,270],{"class":54,"line":269},17,[52,271,272],{"class":58},"  \u002F\u002F when descendants should reach it via `injectForm\u003CForm>('signup')`.\n",[52,274,276,278,280,282,285,287,290,292,295],{"class":54,"line":275},18,[52,277,199],{"class":93},[52,279,160],{"class":65},[52,281,28],{"class":148},[52,283,284],{"class":65}," } ",[52,286,80],{"class":93},[52,288,289],{"class":73}," useForm",[52,291,66],{"class":65},[52,293,294],{"class":73},"Form",[52,296,297],{"class":65},">({ schema })\n",[52,299,301,303,306,308,311,314,317,320,323,326,329],{"class":54,"line":300},19,[52,302,199],{"class":93},[52,304,305],{"class":148}," onSubmit",[52,307,205],{"class":93},[52,309,310],{"class":73}," handleSubmit",[52,312,313],{"class":65},"(",[52,315,316],{"class":93},"async",[52,318,319],{"class":65}," (",[52,321,322],{"class":141},"values",[52,324,325],{"class":65},") ",[52,327,328],{"class":93},"=>",[52,330,135],{"class":65},[52,332,334,337,340,343,345,348],{"class":54,"line":333},20,[52,335,336],{"class":93},"    await",[52,338,339],{"class":65}," api.",[52,341,342],{"class":73},"post",[52,344,313],{"class":65},[52,346,347],{"class":83},"'\u002Fsignup'",[52,349,350],{"class":65},", values)\n",[52,352,354],{"class":54,"line":353},21,[52,355,255],{"class":65},[52,357,359,362,364],{"class":54,"line":358},22,[52,360,361],{"class":65},"\u003C\u002F",[52,363,70],{"class":69},[52,365,87],{"class":65},[52,367,369],{"class":54,"line":368},23,[52,370,123],{"emptyLinePlaceholder":122},[52,372,374,376,379],{"class":54,"line":373},24,[52,375,66],{"class":65},[52,377,378],{"class":69},"template",[52,380,87],{"class":65},[52,382,384,387,390,393,395,398],{"class":54,"line":383},25,[52,385,386],{"class":65},"  \u003C",[52,388,389],{"class":69},"form",[52,391,392],{"class":73}," @submit.prevent",[52,394,80],{"class":65},[52,396,397],{"class":83},"\"onSubmit\"",[52,399,87],{"class":65},[52,401,403,406,409],{"class":54,"line":402},26,[52,404,405],{"class":65},"    \u003C",[52,407,408],{"class":69},"EmailRow",[52,410,411],{"class":65}," \u002F>\n",[52,413,415,417,420],{"class":54,"line":414},27,[52,416,405],{"class":65},[52,418,419],{"class":69},"ProfileGroup",[52,421,411],{"class":65},[52,423,425,427,430,433,435],{"class":54,"line":424},28,[52,426,405],{"class":65},[52,428,429],{"class":69},"button",[52,431,432],{"class":65},">Sign up\u003C\u002F",[52,434,429],{"class":69},[52,436,87],{"class":65},[52,438,440,443,445],{"class":54,"line":439},29,[52,441,442],{"class":65},"  \u003C\u002F",[52,444,389],{"class":69},[52,446,87],{"class":65},[52,448,450,452,454],{"class":54,"line":449},30,[52,451,361],{"class":65},[52,453,378],{"class":69},[52,455,87],{"class":65},[14,457,458],{},"Any descendant grabs the same form:",[43,460,462],{"className":45,"code":461,"language":47,"meta":48,"style":48},"\u003C!-- EmailRow.vue -->\n\u003Cscript setup lang=\"ts\">\n  import { injectForm } from 'attaform\u002Fzod'\n\n  interface Form {\n    email: string\n    profile: { name: string; age: number }\n  }\n\n  const { register, errors } = injectForm\u003CForm>()\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Clabel>Email\u003C\u002Flabel>\n  \u003Cinput v-register=\"register('email')\" type=\"email\" \u002F>\n  \u003Csmall v-if=\"errors.email?.[0]\">\n    {{ errors.email[0].message }}\n  \u003C\u002Fsmall>\n\u003C\u002Ftemplate>\n",[18,463,464,469,485,496,500,508,516,540,544,548,575,583,587,595,609,634,651,656,664],{"__ignoreMap":48},[52,465,466],{"class":54,"line":55},[52,467,468],{"class":58},"\u003C!-- EmailRow.vue -->\n",[52,470,471,473,475,477,479,481,483],{"class":54,"line":62},[52,472,66],{"class":65},[52,474,70],{"class":69},[52,476,74],{"class":73},[52,478,77],{"class":73},[52,480,80],{"class":65},[52,482,84],{"class":83},[52,484,87],{"class":65},[52,486,487,489,492,494],{"class":54,"line":90},[52,488,94],{"class":93},[52,490,491],{"class":65}," { injectForm } ",[52,493,100],{"class":93},[52,495,103],{"class":83},[52,497,498],{"class":54,"line":106},[52,499,123],{"emptyLinePlaceholder":122},[52,501,502,504,506],{"class":54,"line":119},[52,503,129],{"class":93},[52,505,132],{"class":73},[52,507,135],{"class":65},[52,509,510,512,514],{"class":54,"line":126},[52,511,142],{"class":141},[52,513,145],{"class":93},[52,515,149],{"class":148},[52,517,518,520,522,524,526,528,530,532,534,536,538],{"class":54,"line":138},[52,519,155],{"class":141},[52,521,145],{"class":93},[52,523,160],{"class":65},[52,525,163],{"class":141},[52,527,145],{"class":93},[52,529,168],{"class":148},[52,531,171],{"class":65},[52,533,174],{"class":141},[52,535,145],{"class":93},[52,537,179],{"class":148},[52,539,182],{"class":65},[52,541,542],{"class":54,"line":152},[52,543,188],{"class":65},[52,545,546],{"class":54,"line":185},[52,547,123],{"emptyLinePlaceholder":122},[52,549,550,552,554,556,559,561,563,565,568,570,572],{"class":54,"line":191},[52,551,199],{"class":93},[52,553,160],{"class":65},[52,555,20],{"class":148},[52,557,558],{"class":65},", ",[52,560,24],{"class":148},[52,562,284],{"class":65},[52,564,80],{"class":93},[52,566,567],{"class":73}," injectForm",[52,569,66],{"class":65},[52,571,294],{"class":73},[52,573,574],{"class":65},">()\n",[52,576,577,579,581],{"class":54,"line":196},[52,578,361],{"class":65},[52,580,70],{"class":69},[52,582,87],{"class":65},[52,584,585],{"class":54,"line":217},[52,586,123],{"emptyLinePlaceholder":122},[52,588,589,591,593],{"class":54,"line":229},[52,590,66],{"class":65},[52,592,378],{"class":69},[52,594,87],{"class":65},[52,596,597,599,602,605,607],{"class":54,"line":252},[52,598,386],{"class":65},[52,600,601],{"class":69},"label",[52,603,604],{"class":65},">Email\u003C\u002F",[52,606,601],{"class":69},[52,608,87],{"class":65},[52,610,611,613,616,619,621,624,627,629,632],{"class":54,"line":258},[52,612,386],{"class":65},[52,614,615],{"class":69},"input",[52,617,618],{"class":73}," v-register",[52,620,80],{"class":65},[52,622,623],{"class":83},"\"register('email')\"",[52,625,626],{"class":73}," type",[52,628,80],{"class":65},[52,630,631],{"class":83},"\"email\"",[52,633,411],{"class":65},[52,635,636,638,641,644,646,649],{"class":54,"line":263},[52,637,386],{"class":65},[52,639,640],{"class":69},"small",[52,642,643],{"class":73}," v-if",[52,645,80],{"class":65},[52,647,648],{"class":83},"\"errors.email?.[0]\"",[52,650,87],{"class":65},[52,652,653],{"class":54,"line":269},[52,654,655],{"class":65},"    {{ errors.email[0].message }}\n",[52,657,658,660,662],{"class":54,"line":275},[52,659,442],{"class":65},[52,661,640],{"class":69},[52,663,87],{"class":65},[52,665,666,668,670],{"class":54,"line":300},[52,667,361],{"class":65},[52,669,378],{"class":69},[52,671,87],{"class":65},[14,673,674,675,677,678,681,682,685],{},"You supply the ",[18,676,294],{}," generic — Vue's injection system erases it,\nso the library can't recover your shape on your behalf. Other than\nthat, ",[18,679,680],{},"injectForm\u003CForm>()"," returns an object type-identical to\n",[18,683,684],{},"useForm","'s return.",[35,687,689],{"id":688},"reaching-a-form-that-isnt-an-ancestor","Reaching a form that isn't an ancestor",[14,691,692],{},"Floating save buttons, sidebar status widgets, anything in a\ndifferent branch of the component tree:",[43,694,696],{"className":45,"code":695,"language":47,"meta":48,"style":48},"\u003C!-- FloatingSaveButton.vue (anywhere in the app) -->\n\u003Cscript setup lang=\"ts\">\n  import { injectForm } from 'attaform\u002Fzod'\n\n  interface Form {\n    \u002F* … *\u002F\n  }\n\n  const { meta, handleSubmit } = injectForm\u003CForm>('signup')\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cbutton :disabled=\"!meta.isDirty || meta.isSubmitting\" @click=\"handleSubmit(onSave)()\">\n    Save\n  \u003C\u002Fbutton>\n\u003C\u002Ftemplate>\n",[18,697,698,703,719,729,733,741,746,750,754,786,794,798,806,830,835,843],{"__ignoreMap":48},[52,699,700],{"class":54,"line":55},[52,701,702],{"class":58},"\u003C!-- FloatingSaveButton.vue (anywhere in the app) -->\n",[52,704,705,707,709,711,713,715,717],{"class":54,"line":62},[52,706,66],{"class":65},[52,708,70],{"class":69},[52,710,74],{"class":73},[52,712,77],{"class":73},[52,714,80],{"class":65},[52,716,84],{"class":83},[52,718,87],{"class":65},[52,720,721,723,725,727],{"class":54,"line":90},[52,722,94],{"class":93},[52,724,491],{"class":65},[52,726,100],{"class":93},[52,728,103],{"class":83},[52,730,731],{"class":54,"line":106},[52,732,123],{"emptyLinePlaceholder":122},[52,734,735,737,739],{"class":54,"line":119},[52,736,129],{"class":93},[52,738,132],{"class":73},[52,740,135],{"class":65},[52,742,743],{"class":54,"line":126},[52,744,745],{"class":58},"    \u002F* … *\u002F\n",[52,747,748],{"class":54,"line":138},[52,749,188],{"class":65},[52,751,752],{"class":54,"line":152},[52,753,123],{"emptyLinePlaceholder":122},[52,755,756,758,760,763,765,767,769,771,773,775,777,780,783],{"class":54,"line":185},[52,757,199],{"class":93},[52,759,160],{"class":65},[52,761,762],{"class":148},"meta",[52,764,558],{"class":65},[52,766,28],{"class":148},[52,768,284],{"class":65},[52,770,80],{"class":93},[52,772,567],{"class":73},[52,774,66],{"class":65},[52,776,294],{"class":73},[52,778,779],{"class":65},">(",[52,781,782],{"class":83},"'signup'",[52,784,785],{"class":65},")\n",[52,787,788,790,792],{"class":54,"line":191},[52,789,361],{"class":65},[52,791,70],{"class":69},[52,793,87],{"class":65},[52,795,796],{"class":54,"line":196},[52,797,123],{"emptyLinePlaceholder":122},[52,799,800,802,804],{"class":54,"line":217},[52,801,66],{"class":65},[52,803,378],{"class":69},[52,805,87],{"class":65},[52,807,808,810,812,815,817,820,823,825,828],{"class":54,"line":229},[52,809,386],{"class":65},[52,811,429],{"class":69},[52,813,814],{"class":73}," :disabled",[52,816,80],{"class":65},[52,818,819],{"class":83},"\"!meta.isDirty || meta.isSubmitting\"",[52,821,822],{"class":73}," @click",[52,824,80],{"class":65},[52,826,827],{"class":83},"\"handleSubmit(onSave)()\"",[52,829,87],{"class":65},[52,831,832],{"class":54,"line":252},[52,833,834],{"class":65},"    Save\n",[52,836,837,839,841],{"class":54,"line":258},[52,838,442],{"class":65},[52,840,429],{"class":69},[52,842,87],{"class":65},[52,844,845,847,849],{"class":54,"line":263},[52,846,361],{"class":65},[52,848,378],{"class":69},[52,850,87],{"class":65},[14,852,853,854,857,858,861],{},"Pass the same ",[18,855,856],{},"key"," you passed to ",[18,859,860],{},"useForm({ key: 'signup' })",". If no\nform is registered under that key when the component mounts, you\nget a clear error naming the missing key.",[35,863,865,866,868,869,871],{"id":864},"do-i-need-to-pass-a-key-to-useform","Do I need to pass a ",[18,867,856],{}," to ",[18,870,684],{},"?",[14,873,874],{},"The two resolution modes are cleanly split:",[876,877,878,896],"ul",{},[879,880,881,888,889,892,893,895],"li",{},[882,883,884,885,887],"strong",{},"Anonymous (no ",[18,886,856],{},") → ambient access."," ",[18,890,891],{},"useForm({ schema })","\nfills the parent's ambient slot. Any descendant's\n",[18,894,680],{}," (no key) resolves to it; closest ancestor\nwins when nested.",[879,897,898,888,905,908,909,912,913,916],{},[882,899,900,901,904],{},"Keyed (",[18,902,903],{},"key: 'x'",") → explicit access only.",[18,906,907],{},"useForm({ schema, key: 'x' })"," registers the form under ",[18,910,911],{},"'x'"," but does NOT fill the\nambient slot. Descendants reach it via ",[18,914,915],{},"injectForm\u003CForm>('x')",",\nnot via the no-key form.",[14,918,919,920,922],{},"Skip ",[18,921,856],{}," for single-component one-off forms (login modal,\nsettings panel). Supply one when you want cross-component lookup,\nmulti-call-site shared state, a stable persistence default, or a\nlegible DevTools label.",[924,925,927,928,930],"h3",{"id":926},"gotcha-multiple-anonymous-useform-calls-in-the-same-component","Gotcha: multiple anonymous ",[18,929,684],{}," calls in the same component",[14,932,933,934,937,938,941,942,944,945,947],{},"Vue's ",[18,935,936],{},"provide","\u002F",[18,939,940],{},"inject"," is last-write-wins per component. If a\nparent calls ",[18,943,684],{}," twice without keys, the second overwrites\nthe first in the ambient slot, and descendants using\n",[18,946,680],{}," only see the second.",[43,949,953],{"className":950,"code":951,"language":952,"meta":48,"style":48},"language-ts shiki shiki-themes github-light github-dark","\u002F\u002F Parent component\nconst formA = useForm({ schema: schemaA }) \u002F\u002F provides ambient → A\nconst formB = useForm({ schema: schemaB }) \u002F\u002F provides ambient → B (overwrites A)\n\u002F\u002F Descendants' injectForm\u003CForm>() reads B. A is unreachable via ambient.\n","ts",[18,954,955,960,978,995],{"__ignoreMap":48},[52,956,957],{"class":54,"line":55},[52,958,959],{"class":58},"\u002F\u002F Parent component\n",[52,961,962,965,968,970,972,975],{"class":54,"line":62},[52,963,964],{"class":93},"const",[52,966,967],{"class":148}," formA",[52,969,205],{"class":93},[52,971,289],{"class":73},[52,973,974],{"class":65},"({ schema: schemaA }) ",[52,976,977],{"class":58},"\u002F\u002F provides ambient → A\n",[52,979,980,982,985,987,989,992],{"class":54,"line":90},[52,981,964],{"class":93},[52,983,984],{"class":148}," formB",[52,986,205],{"class":93},[52,988,289],{"class":73},[52,990,991],{"class":65},"({ schema: schemaB }) ",[52,993,994],{"class":58},"\u002F\u002F provides ambient → B (overwrites A)\n",[52,996,997],{"class":54,"line":106},[52,998,999],{"class":58},"\u002F\u002F Descendants' injectForm\u003CForm>() reads B. A is unreachable via ambient.\n",[14,1001,1002,1003,1006,1007,1009,1010,1013],{},"The runtime emits a dev-mode ",[18,1004,1005],{},"console.warn"," lazily — when (and only\nwhen) a descendant actually consumes the ambient slot via\n",[18,1008,680],{}," with no key. The warning lists each\nanonymous ",[18,1011,1012],{},"useForm()"," call by source frame so you can navigate to\nthe offending sites.",[14,1015,1016,1019],{},[882,1017,1018],{},"Fix"," — give each form a key (which removes them from the ambient\nslot entirely) and look them up explicitly:",[43,1021,1023],{"className":950,"code":1022,"language":952,"meta":48,"style":48},"useForm({ schema: schemaA, key: 'a' })\nuseForm({ schema: schemaB, key: 'b' })\n\u002F\u002F Descendants:\nconst a = injectForm\u003CFormA>('a')\nconst b = injectForm\u003CFormB>('b')\n",[18,1024,1025,1038,1050,1055,1077],{"__ignoreMap":48},[52,1026,1027,1029,1032,1035],{"class":54,"line":55},[52,1028,684],{"class":73},[52,1030,1031],{"class":65},"({ schema: schemaA, key: ",[52,1033,1034],{"class":83},"'a'",[52,1036,1037],{"class":65}," })\n",[52,1039,1040,1042,1045,1048],{"class":54,"line":62},[52,1041,684],{"class":73},[52,1043,1044],{"class":65},"({ schema: schemaB, key: ",[52,1046,1047],{"class":83},"'b'",[52,1049,1037],{"class":65},[52,1051,1052],{"class":54,"line":90},[52,1053,1054],{"class":58},"\u002F\u002F Descendants:\n",[52,1056,1057,1059,1062,1064,1066,1068,1071,1073,1075],{"class":54,"line":106},[52,1058,964],{"class":93},[52,1060,1061],{"class":148}," a",[52,1063,205],{"class":93},[52,1065,567],{"class":73},[52,1067,66],{"class":65},[52,1069,1070],{"class":73},"FormA",[52,1072,779],{"class":65},[52,1074,1034],{"class":83},[52,1076,785],{"class":65},[52,1078,1079,1081,1084,1086,1088,1090,1093,1095,1097],{"class":54,"line":119},[52,1080,964],{"class":93},[52,1082,1083],{"class":148}," b",[52,1085,205],{"class":93},[52,1087,567],{"class":73},[52,1089,66],{"class":65},[52,1091,1092],{"class":73},"FormB",[52,1094,779],{"class":65},[52,1096,1047],{"class":83},[52,1098,785],{"class":65},[14,1100,1101,1102,1105],{},"Mixing modes is fine — keyed forms don't interfere with an ambient\nsibling. A parent with three keyed forms plus one anonymous form\nproduces no warning; the descendant's ",[18,1103,1104],{},"injectForm\u003CF>()","\nunambiguously resolves to the (only) anonymous one.",[14,1107,1108],{},"…or split the two anonymous forms into separate components, so each\nowns the ambient slot of its own subtree.",[35,1110,1112],{"id":1111},"lifetime","Lifetime",[14,1114,1115],{},"Both resolution modes ref-count on the form's registry entry. In\npractice:",[876,1117,1118,1121,1124],{},[879,1119,1120],{},"The form survives until every component that reached it unmounts.",[879,1122,1123],{},"Cleanup is automatic — no explicit dispose call from the consumer.",[879,1125,1126,1127,1130,1131,1133],{},"A form accessed only by ",[18,1128,1129],{},"injectForm(key)"," stays alive as long\nas at least one consumer is mounted, even if the original\n",[18,1132,684],{}," owner unmounted first.",[35,1135,1137],{"id":1136},"error-messages","Error messages",[14,1139,1140,1142],{},[18,1141,32],{}," throws only in two cases:",[876,1144,1145,1157],{},[879,1146,1147,1150,1151,1153,1154,1156],{},[882,1148,1149],{},"No ambient form"," — you called ",[18,1152,32],{}," with no\nancestor ",[18,1155,684],{}," and no key argument. The error names both\nresolutions so you can pick either.",[879,1158,1159,1150,1162,1165],{},[882,1160,1161],{},"Key not registered",[18,1163,1164],{},"injectForm('key-name')","\nbut nothing is registered. The error includes the key value so\nyou can spot typos or mounting-order bugs.",[35,1167,1169],{"id":1168},"when-not-to-use-it","When not to use it",[14,1171,1172,1173,1175,1176,1179],{},"If your form logic fits in one component, stick with ",[18,1174,684],{},"\ndirectly. ",[18,1177,1178],{},"injectForm"," is a small reactive overhead you don't\nneed when there's nothing to share.",[14,1181,1182,1183,1186,1187,558,1190,1192],{},"Reach for it when field components are reusable across forms, or\nwhen a distant component needs read-only status (",[18,1184,1185],{},"meta.isDirty",",\n",[18,1188,1189],{},"meta.isSubmitting",[18,1191,24],{},") of a form it doesn't own.",[1194,1195,1196],"style",{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}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 pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}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);}",{"title":48,"searchDepth":62,"depth":62,"links":1198},[1199,1200,1201,1206,1207,1208],{"id":37,"depth":62,"text":38},{"id":688,"depth":62,"text":689},{"id":864,"depth":62,"text":1202,"children":1203},"Do I need to pass a key to useForm?",[1204],{"id":926,"depth":90,"text":1205},"Gotcha: multiple anonymous useForm calls in the same component",{"id":1111,"depth":62,"text":1112},{"id":1136,"depth":62,"text":1137},{"id":1168,"depth":62,"text":1169},"Splitting a form across components? Don't prop-drill register \u002F\nerrors \u002F handleSubmit through every layer. Call\ninjectForm() in any descendant and get the same handle back.","md",{},"\u002Fdocs\u002Frecipes\u002Fform-context",{"title":5,"description":1209},"docs\u002Frecipes\u002Fform-context","R-DwiKS64yiXjPQ2_RWm6FDLyuvu1u1781RrZfzjKj8",1777934136511]