@@ -48,7 +48,8 @@ import {
4848 comparePaths ,
4949 setPaths ,
5050 pathExists ,
51- type ZodTypeInfo
51+ type ZodTypeInfo ,
52+ traversePaths
5253} from '../entity.js' ;
5354import { fieldProxy } from './proxies.js' ;
5455import { clone } from '../utils.js' ;
@@ -642,9 +643,6 @@ export function superForm<
642643
643644 ///// When use:enhance is enabled ///////////////////////////////////////////
644645
645- // Prevent client validation on first page load
646- // (when it recieives data from the server)
647-
648646 function isTainted ( obj : unknown ) : boolean {
649647 if ( obj === null )
650648 throw new SuperFormError ( '$tainted store contained null' ) ;
@@ -776,6 +774,7 @@ export function superForm<
776774 options . defaultValidator ,
777775 Form ,
778776 Errors ,
777+ Tainted ,
779778 opts
780779 ) ;
781780 } ,
@@ -843,6 +842,16 @@ function shouldSyncFlash<T extends AnyZodObject, M>(
843842 return options . syncFlashMessage ;
844843}
845844
845+ function isPathTainted (
846+ path : string [ ] ,
847+ tainted : TaintedFields < AnyZodObject > | undefined
848+ ) {
849+ if ( tainted === undefined ) return false ;
850+ const leaf = traversePath ( tainted , path as FieldPath < typeof tainted > ) ;
851+ if ( ! leaf ) return false ;
852+ return leaf . value === true ;
853+ }
854+
846855const effectMapCache = new WeakMap < object , boolean > ( ) ;
847856
848857async function validateField < T extends AnyZodObject , M > (
@@ -851,6 +860,7 @@ async function validateField<T extends AnyZodObject, M>(
851860 defaultValidator : FormOptions < T , M > [ 'defaultValidator' ] ,
852861 data : SuperForm < T , M > [ 'form' ] ,
853862 errors : SuperForm < T , M > [ 'errors' ] ,
863+ tainted : SuperForm < T , M > [ 'tainted' ] ,
854864 options : ValidateOptions < unknown > = { }
855865) : Promise < string [ ] | undefined > {
856866 if ( options . update === undefined ) options . update = true ;
@@ -1006,9 +1016,35 @@ async function validateField<T extends AnyZodObject, M>(
10061016 ) ;
10071017
10081018 if ( ! result . success ) {
1009- const errors = result . error . format ( ) ;
1010- const current = traversePath ( errors , path as FieldPath < typeof errors > ) ;
1011- return setError ( options . errors ?? current ?. value ?. _errors ) ;
1019+ const newErrors = mapErrors ( result . error . format ( ) ) ;
1020+
1021+ if ( options . update === true || options . update == 'errors' ) {
1022+ console . log ( '🚀 ~ file: index.ts:1020 ~ newErrors:' , newErrors ) ;
1023+
1024+ // Set errors for other (tainted) fields, that may have been changed
1025+ const taintedFields = get ( tainted ) ;
1026+ const currentErrors = get ( errors ) ;
1027+ let updated = false ;
1028+
1029+ traversePaths ( newErrors , ( pathData ) => {
1030+ if ( ! Array . isArray ( pathData . value ) ) return ;
1031+ if ( isPathTainted ( pathData . path , taintedFields ) ) {
1032+ setPaths ( currentErrors , [ pathData . path ] , pathData . value ) ;
1033+ updated = true ;
1034+ }
1035+ return 'skip' ;
1036+ } ) ;
1037+
1038+ if ( updated ) errors . set ( currentErrors ) ;
1039+ }
1040+
1041+ // Finally, set errors for the specific field
1042+ const current = traversePath (
1043+ newErrors ,
1044+ path as FieldPath < typeof newErrors >
1045+ ) ;
1046+
1047+ return setError ( options . errors ?? current ?. value ) ;
10121048 } else {
10131049 return setError ( undefined ) ;
10141050 }
@@ -1073,7 +1109,8 @@ function formEnhance<T extends AnyZodObject, M>(
10731109 options . validators ,
10741110 options . defaultValidator ,
10751111 data ,
1076- errors
1112+ errors ,
1113+ tainted
10771114 ) ;
10781115 }
10791116
0 commit comments