@@ -10,7 +10,7 @@ export type DirtyMap<T> = {
10
10
[ Key in keyof T ] ?: boolean ;
11
11
} ;
12
12
13
- export type ErrorType < T , Error > = Error | ( T extends { } ? ErrorMap < T , Error > : never ) ;
13
+ export type ErrorType < T , Error > = Error | ( T extends { } ? ErrorMap < NonNullable < T > , Error > : never ) ;
14
14
15
15
export type ErrorMap < T , Error > = {
16
16
[ Key in keyof T ] ?: ErrorType < T [ Key ] , Error > ;
@@ -19,7 +19,7 @@ export type ErrorMap<T, Error> = {
19
19
export type DefaultError = string ;
20
20
export type DefaultState = { isSubmitting : boolean } ;
21
21
22
- export function memberCopy < T > ( value : T ) : T {
22
+ function memberCopy < T > ( value : T ) : T {
23
23
if ( Array . isArray ( value ) ) {
24
24
return [ ...value ] as any ;
25
25
} else if ( typeof value === "object" ) {
@@ -29,6 +29,12 @@ export function memberCopy<T>(value: T): T {
29
29
}
30
30
}
31
31
32
+ function addDistinct < T extends any [ ] > ( arr1 : T , arr2 : T ) {
33
+ for ( let i = 0 ; i < arr2 . length ; i ++ ) {
34
+ if ( ! arr1 . includes ( arr2 [ i ] ) ) arr1 . push ( arr2 [ i ] ) ;
35
+ }
36
+ }
37
+
32
38
/**
33
39
* Compares 2 objects that only contain primitive fields (no object fields)
34
40
* @returns true when different, false when 'equal', undefined when an object field was found.
@@ -155,8 +161,6 @@ export class FormState<T, State = DefaultState, Error extends string = DefaultEr
155
161
notifyParent : boolean = true ,
156
162
fireAny : boolean = true
157
163
) {
158
- if ( key === "author" ) console . trace ( "setValueInternal" , key , value , dirty ) ;
159
-
160
164
let valueMap = isDefault ? this . defaultValues : this . values ;
161
165
if ( value === undefined ) {
162
166
if ( Array . isArray ( valueMap ) ) valueMap . splice ( key as number , 1 ) ;
@@ -312,11 +316,10 @@ export class FormState<T, State = DefaultState, Error extends string = DefaultEr
312
316
* @param error The error.
313
317
* @param notifyChild Should this form notify the child form about this change?
314
318
* @param notifyParent Should this form notify the parent form about this change?
315
- * @param setValuesWasUsed
316
319
*/
317
320
public setError < Key extends keyof T > (
318
321
key : Key ,
319
- error : ErrorType < T [ Key ] , Error > | undefined ,
322
+ error : ErrorType < NonNullable < T [ Key ] > , Error > | undefined ,
320
323
notifyChild : boolean = true ,
321
324
notifyParent : boolean = true ,
322
325
fireAny : boolean = true
@@ -327,17 +330,16 @@ export class FormState<T, State = DefaultState, Error extends string = DefaultEr
327
330
else this . errorMap [ key ] = error ;
328
331
329
332
if ( notifyChild && this . childMap [ key ] ) {
330
- if ( typeof error === "object" ) {
331
- let changed = this . childMap [ key ] ! . setErrors ( ( error as any ) ?? { } , true , false ) ;
332
- if ( ! changed ) return false ;
333
- } else {
334
- this . childMap [ key ] ! . setErrors ( { } as any , true , false ) ;
335
- }
333
+ let changed = this . childMap [ key ] ! . setErrors ( error ?? ( { } as any ) , true , false ) ;
334
+ if ( ! changed && error !== undefined ) return false ;
336
335
}
337
336
338
337
this . fireListeners ( key ) ;
339
338
if ( fireAny ) this . fireAnyListeners ( ) ; // When setValuesWasUsed, it will call fireAnyListener itself when all values were set
340
- if ( notifyParent ) this . updateParentErrors ( ) ; // Will call setError on parent
339
+
340
+ if ( notifyParent && this instanceof ChildFormState ) {
341
+ this . parent . setError ( this . name , this . error ? memberCopy ( this . errorMap ) : undefined , false , true ) ;
342
+ }
341
343
return true ;
342
344
}
343
345
@@ -348,34 +350,37 @@ export class FormState<T, State = DefaultState, Error extends string = DefaultEr
348
350
* @param notifyParent Should this form notify the parent form about this change?
349
351
*/
350
352
public setErrors ( errors : ErrorType < T , Error > , notifyChild : boolean = true , notifyParent : boolean = true ) {
353
+ let keys = Object . keys ( this . errorMap ) ;
354
+
351
355
if ( typeof errors === "string" ) {
352
356
if ( notifyParent && this instanceof ChildFormState ) {
353
357
this . parent . setError ( this . name , errors , false , true ) ;
354
358
}
355
- return ;
356
- }
357
- let keys = Object . keys ( this . errorMap ) ;
358
- let newKeys = Object . keys ( errors ) ;
359
- for ( let i = 0 ; i < newKeys . length ; i ++ ) {
360
- if ( ! keys . includes ( newKeys [ i ] ) ) keys . push ( newKeys [ i ] ) ;
359
+ errors = { } as any ;
360
+ } else {
361
+ addDistinct ( keys , Object . keys ( errors ) ) ;
361
362
}
363
+
362
364
let changed = false ;
363
365
for ( let i = keys . length ; i >= 0 ; i -- ) {
364
366
let key = keys [ i ] as keyof T ;
365
367
if (
366
368
this . setError (
367
369
key ,
368
- errors [ key ] as any ,
370
+ ( errors as ErrorMap < T , Error > ) [ key ] as ErrorType < NonNullable < T [ keyof T ] > , Error > ,
369
371
notifyChild ,
370
- false , // Will call updateParentErrors by itself after all values have been copied, see 3 lines down
372
+ false , // Will call this.parent.setError by itself after all values have been copied, see 3 lines down
371
373
false // Will call fireAnyListener by itself after all values have been copied, see 3 lines down
372
374
)
373
375
)
374
376
changed = true ;
375
377
}
376
378
if ( ! changed ) return false ;
379
+
377
380
this . fireAnyListeners ( ) ;
378
- if ( notifyParent ) this . updateParentErrors ( ) ;
381
+ if ( notifyParent && this instanceof ChildFormState ) {
382
+ this . parent . setError ( this . name , this . error ? ( memberCopy ( this . errorMap ) as any ) : undefined , false , true ) ;
383
+ }
379
384
return true ;
380
385
}
381
386
@@ -512,10 +517,6 @@ export class FormState<T, State = DefaultState, Error extends string = DefaultEr
512
517
// Not implemented for root form, as it does not have a parent
513
518
}
514
519
515
- protected updateParentErrors ( ) {
516
- // Not implemented for root form, as it does not have a parent
517
- }
518
-
519
520
protected updateParentState ( ) {
520
521
// Not implemented for root form, as it does not have a parent
521
522
}
@@ -556,10 +557,6 @@ export class ChildFormState<Parent, Key extends keyof Parent, ParentState, Paren
556
557
) ;
557
558
}
558
559
559
- protected updateParentErrors ( ) {
560
- this . parent . setError ( this . name , this . error ? ( memberCopy ( this . errorMap ) as any ) : undefined , false , true ) ;
561
- }
562
-
563
560
protected updateParentState ( ) {
564
561
this . parent . setState ( memberCopy ( this . state ) , false , true ) ;
565
562
}
0 commit comments