[{"data":1,"prerenderedAt":457},["ShallowReactive",2],{"content-\u002Fdocs\u002Fvalidation\u002Flifecycle":3},{"id":4,"title":5,"body":6,"description":435,"extension":436,"meta":437,"metaRows":438,"navigation":451,"path":452,"seo":453,"source":454,"stem":455,"__hash__":456},"docs\u002Fdocs\u002Fvalidation\u002Flifecycle.md","The validation lifecycle",{"type":7,"value":8,"toc":428},"minimark",[9,13,20,23,39,44,51,100,115,125,136,142,185,191,194,200,249,270,282,292,296,366,375,379,424],[10,11,5],"h1",{"id":12},"the-validation-lifecycle",[14,15,16],"blockquote",{},[17,18,19],"p",{},"Three imperative entry points to the same validator. Pick by what you need next: reactive read, awaited verdict, or parsed payload.",[21,22],"docs-meta-table",{},[17,24,25,26,30,31,34,35,38],{},"Click each button to dispatch the matching method against the current form values. The result panel surfaces the return shape of each: a reactive status snapshot from ",[27,28,29],"code",{},"validate()",", an awaited verdict from ",[27,32,33],{},"validateAsync()",", and the fully parsed Zod output from ",[27,36,37],{},"parse()",". The methods share the predicate pipeline; the differences are about what they hand you back.",[40,41],"docs-demo",{"label":42,"slug":43},"Lifecycle Demo","validation-lifecycle",[45,46,48],"h2",{"id":47},"validatepath",[27,49,50],{},"validate(path?)",[52,53,58],"pre",{"className":54,"code":55,"language":56,"meta":57,"style":57},"language-ts shiki shiki-themes github-light github-dark","const status = form.validate()\n\u002F\u002F status.value.pending: true while async refinements are in flight\n\u002F\u002F status.value.success: true once everything passes (after settling)\n","ts","",[27,59,60,87,94],{"__ignoreMap":57},[61,62,65,69,73,76,80,84],"span",{"class":63,"line":64},"line",1,[61,66,68],{"class":67},"szBVR","const",[61,70,72],{"class":71},"sj4cs"," status",[61,74,75],{"class":67}," =",[61,77,79],{"class":78},"sVt8B"," form.",[61,81,83],{"class":82},"sScJk","validate",[61,85,86],{"class":78},"()\n",[61,88,90],{"class":63,"line":89},2,[61,91,93],{"class":92},"sJ8bj","\u002F\u002F status.value.pending: true while async refinements are in flight\n",[61,95,97],{"class":63,"line":96},3,[61,98,99],{"class":92},"\u002F\u002F status.value.success: true once everything passes (after settling)\n",[17,101,102,103,106,107,110,111,114],{},"Returns a ",[27,104,105],{},"Readonly\u003CRef\u003CReactiveValidationStatus\u003CForm>>>",", Vue's reactive surface for the validation result. Reads inside ",[27,108,109],{},"computed"," \u002F ",[27,112,113],{},"watchEffect"," \u002F templates track changes; the ref re-renders consumers when the verdict flips.",[17,116,117,118,121,122,124],{},"Sync-only by nature: the predicate work runs synchronously, but async refinements get observed via the ",[27,119,120],{},"pending"," flag rather than awaited. Use ",[27,123,29],{}," when you want a reactive \"is this valid right now?\" read without holding up the caller.",[17,126,127,128,131,132,135],{},"Optional ",[27,129,130],{},"path"," argument scopes the validation to a subtree (",[27,133,134],{},"validate('profile.email')"," runs predicates only for that path).",[45,137,139],{"id":138},"validateasyncpath",[27,140,141],{},"validateAsync(path?)",[52,143,145],{"className":54,"code":144,"language":56,"meta":57,"style":57},"const result = await form.validateAsync()\nif (result.success) {\n  \u002F\u002F every refinement passed, including async ones\n}\n",[27,146,147,166,174,179],{"__ignoreMap":57},[61,148,149,151,154,156,159,161,164],{"class":63,"line":64},[61,150,68],{"class":67},[61,152,153],{"class":71}," result",[61,155,75],{"class":67},[61,157,158],{"class":67}," await",[61,160,79],{"class":78},[61,162,163],{"class":82},"validateAsync",[61,165,86],{"class":78},[61,167,168,171],{"class":63,"line":89},[61,169,170],{"class":67},"if",[61,172,173],{"class":78}," (result.success) {\n",[61,175,176],{"class":63,"line":96},[61,177,178],{"class":92},"  \u002F\u002F every refinement passed, including async ones\n",[61,180,182],{"class":63,"line":181},4,[61,183,184],{"class":78},"}\n",[17,186,102,187,190],{},[27,188,189],{},"Promise\u003CValidationResponseWithoutValue\u003CForm>>",". Awaits every async refinement before resolving; the result is the final verdict.",[17,192,193],{},"Use this for non-submit code paths that need a synchronous-feeling \"is this valid?\" gate: a \"Save draft\" button that can write partial state but wants to know whether the data is shippable, a step-completion guard in a multi-step flow, anything that needs to react after every check has settled.",[45,195,197],{"id":196},"parsepath",[27,198,199],{},"parse(path?)",[52,201,203],{"className":54,"code":202,"language":56,"meta":57,"style":57},"const result = await form.parse()\nif (result.success) {\n  await api.send(result.data) \u002F\u002F parsed Zod output\n}\n",[27,204,205,222,228,245],{"__ignoreMap":57},[61,206,207,209,211,213,215,217,220],{"class":63,"line":64},[61,208,68],{"class":67},[61,210,153],{"class":71},[61,212,75],{"class":67},[61,214,158],{"class":67},[61,216,79],{"class":78},[61,218,219],{"class":82},"parse",[61,221,86],{"class":78},[61,223,224,226],{"class":63,"line":89},[61,225,170],{"class":67},[61,227,173],{"class":78},[61,229,230,233,236,239,242],{"class":63,"line":96},[61,231,232],{"class":67},"  await",[61,234,235],{"class":78}," api.",[61,237,238],{"class":82},"send",[61,240,241],{"class":78},"(result.data) ",[61,243,244],{"class":92},"\u002F\u002F parsed Zod output\n",[61,246,247],{"class":63,"line":181},[61,248,184],{"class":78},[17,250,102,251,254,255,257,258,261,262,265,266,269],{},[27,252,253],{},"Promise\u003CValidationResponse\u003CGetValueFormType>>",", the same shape as ",[27,256,163],{}," plus the parsed value when validation passes. The parsed value runs through Zod's transforms and refinements, so ",[27,259,260],{},"result.data"," reflects every ",[27,263,264],{},".transform(...)"," and ",[27,267,268],{},".preprocess(...)"," in the schema.",[17,271,272,274,275,277,278,281],{},[27,273,219],{}," is always async, and there is no synchronous variant by design. A schema can grow an async refinement or transform at any moment, and a sync parse would quietly skip it the instant one lands. One always awaited ",[27,276,219],{}," closes that whole category, so the call reads the same way every time: ",[27,279,280],{},"await form.parse()",".",[17,283,284,285,287,288,291],{},"Use ",[27,286,219],{}," when validation success means dispatching the parsed output to an API or downstream pipeline; ",[27,289,290],{},"handleSubmit"," is built on top of it.",[45,293,295],{"id":294},"choosing-between-the-three","Choosing between the three",[297,298,299,312],"table",{},[300,301,302],"thead",{},[303,304,305,309],"tr",{},[306,307,308],"th",{},"Need",[306,310,311],{},"Reach for",[313,314,315,330,339,348],"tbody",{},[303,316,317,321],{},[318,319,320],"td",{},"Reactive \"is this valid?\" read in a template",[318,322,323,325,326,329],{},[27,324,29],{}," (or ",[27,327,328],{},"meta.valid",")",[303,331,332,335],{},[318,333,334],{},"Awaited verdict in a code path",[318,336,337],{},[27,338,33],{},[303,340,341,344],{},[318,342,343],{},"Awaited verdict + parsed payload to ship",[318,345,346],{},[27,347,37],{},[303,349,350,357],{},[318,351,352,353,356],{},"Submit gate that calls ",[27,354,355],{},"onSubmit"," with parsed values",[318,358,359,362,363,365],{},[27,360,361],{},"handleSubmit()"," (which calls ",[27,364,219],{}," internally)",[17,367,368,369,371,372,374],{},"For most form UX, you reach for ",[27,370,328],{}," (reactive read) and ",[27,373,290],{}," (gated dispatch). The three lifecycle methods are escape hatches for the cases where those two don't fit.",[45,376,378],{"id":377},"where-to-next","Where to next",[380,381,382,391,403,414],"ul",{},[383,384,385,390],"li",{},[386,387,389],"a",{"href":388},"\u002Fdocs\u002Fvalidation\u002Fper-field-validation","Per-field validation",": the predicate patterns the lifecycle runs against.",[383,392,393,397,398,265,400,402],{},[386,394,396],{"href":395},"\u002Fdocs\u002Fvalidation\u002Fasync-refinements","Async refinements",": what ",[27,399,163],{},[27,401,219],{}," await.",[383,404,405,409,410,413],{},[386,406,408],{"href":407},"\u002Fdocs\u002Fvalidation\u002Fwhen-validation-runs","When validation runs",": the ",[27,411,412],{},"validateOn"," cadence that drives passive runs.",[383,415,416,421,422,281],{},[386,417,419],{"href":418},"\u002Fdocs\u002Fsubmitting\u002Fhandle-submit",[27,420,290],{},": the dispatch surface built on top of ",[27,423,219],{},[425,426,427],"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 pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}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":57,"searchDepth":89,"depth":89,"links":429},[430,431,432,433,434],{"id":47,"depth":89,"text":50},{"id":138,"depth":89,"text":141},{"id":196,"depth":89,"text":199},{"id":294,"depth":89,"text":295},{"id":377,"depth":89,"text":378},"validate(), validateAsync(), and parse() are the three imperative entry points to the validator. Same predicates, different return shapes; pick by what you need to do next.","md",{},[439,442,445,447,449],{"label":440,"value":441},"Category","Return methods",{"label":443,"value":444,"kind":27},"Methods","validate · validateAsync · parse",{"label":83,"value":446},"reactive ref, sync only",{"label":163,"value":448},"Promise, awaits async refinements",{"label":219,"value":450},"Promise, returns parsed Zod output",true,"\u002Fdocs\u002Fvalidation\u002Flifecycle",{"title":5,"description":435},null,"docs\u002Fvalidation\u002Flifecycle","s8ik_90vZqQPk2udxf-kIED9pWxovz94r8Caq9XayJI",1780949760389]