@@ -113,18 +113,24 @@ export class DynamicForm extends React.Component<
113
113
114
114
public componentDidUpdate ( prevProps : IDynamicFormProps , prevState : IDynamicFormState ) : void {
115
115
if ( ! isEqual ( prevProps , this . props ) ) {
116
+ // Props have changed due to parent component or workbench config, reset state
116
117
this . setState ( {
117
118
infoErrorMessages : [ ] , // Reset info/error messages
118
119
validationErrors : { } // Reset validation errors
119
120
} , ( ) => {
120
- this . getListInformation ( )
121
- . then ( ( ) => {
122
- /* no-op; */
123
- } )
124
- . catch ( ( err ) => {
125
- /* no-op; */
126
- console . error ( err ) ;
127
- } ) ;
121
+ // If listId or listItemId have changed, reload list information
122
+ if ( prevProps . listId !== this . props . listId || prevProps . listItemId !== this . props . listItemId ) {
123
+ this . getListInformation ( )
124
+ . then ( ( ) => {
125
+ /* no-op; */
126
+ } )
127
+ . catch ( ( err ) => {
128
+ /* no-op; */
129
+ console . error ( err ) ;
130
+ } ) ;
131
+ } else {
132
+ this . performValidation ( ) ;
133
+ }
128
134
} ) ;
129
135
}
130
136
}
@@ -327,7 +333,7 @@ export class DynamicForm extends React.Component<
327
333
}
328
334
329
335
// Check min and max values for number fields
330
- if ( field . fieldType === "Number" ) {
336
+ if ( field . fieldType === "Number" && field . newValue !== undefined ) {
331
337
if ( ( field . newValue < field . minimumValue ) || ( field . newValue > field . maximumValue ) ) {
332
338
shouldBeReturnBack = true ;
333
339
}
@@ -336,9 +342,13 @@ export class DynamicForm extends React.Component<
336
342
} ) ;
337
343
338
344
// Perform validation
339
- const validationErrors = await this . evaluateFormulas ( this . state . validationFormulas , true ) as Record < string , string > ;
340
- if ( Object . keys ( validationErrors ) . length > 0 ) {
341
- shouldBeReturnBack = true ;
345
+ const validationDisabled = this . props . useFieldValidation === false ;
346
+ let validationErrors : Record < string , string > = { } ;
347
+ if ( ! validationDisabled ) {
348
+ validationErrors = await this . evaluateFormulas ( this . state . validationFormulas , true , true , this . state . hiddenByFormula ) as Record < string , string > ;
349
+ if ( Object . keys ( validationErrors ) . length > 0 ) {
350
+ shouldBeReturnBack = true ;
351
+ }
342
352
}
343
353
344
354
// If validation failed, return without saving
@@ -462,6 +472,8 @@ export class DynamicForm extends React.Component<
462
472
}
463
473
}
464
474
475
+ let apiError : string ;
476
+
465
477
// If we have the item ID, we simply need to update it
466
478
let newETag : string | undefined = undefined ;
467
479
if ( listItemId ) {
@@ -480,6 +492,7 @@ export class DynamicForm extends React.Component<
480
492
) ;
481
493
}
482
494
} catch ( error ) {
495
+ apiError = error . message ;
483
496
if ( onSubmitError ) {
484
497
onSubmitError ( objects , error ) ;
485
498
}
@@ -505,6 +518,7 @@ export class DynamicForm extends React.Component<
505
518
) ;
506
519
}
507
520
} catch ( error ) {
521
+ apiError = error . message ;
508
522
if ( onSubmitError ) {
509
523
onSubmitError ( objects , error ) ;
510
524
}
@@ -551,6 +565,7 @@ export class DynamicForm extends React.Component<
551
565
) ;
552
566
}
553
567
} catch ( error ) {
568
+ apiError = error . message ;
554
569
if ( onSubmitError ) {
555
570
onSubmitError ( objects , error ) ;
556
571
}
@@ -561,6 +576,7 @@ export class DynamicForm extends React.Component<
561
576
this . setState ( {
562
577
isSaving : false ,
563
578
etag : newETag ,
579
+ infoErrorMessages : apiError ? [ { type : MessageBarType . error , message : apiError } ] : [ ] ,
564
580
} ) ;
565
581
} catch ( error ) {
566
582
if ( onSubmitError ) {
@@ -577,7 +593,8 @@ export class DynamicForm extends React.Component<
577
593
internalName : string ,
578
594
// eslint-disable-next-line @typescript-eslint/no-explicit-any
579
595
newValue : any ,
580
- additionalData ?: FieldChangeAdditionalData
596
+ validate : boolean ,
597
+ additionalData ?: FieldChangeAdditionalData ,
581
598
) : Promise < void > => {
582
599
583
600
const fieldCol = cloneDeep ( this . state . fieldCollection || [ ] ) ;
@@ -652,20 +669,33 @@ export class DynamicForm extends React.Component<
652
669
field . stringValue = emails . join ( ";" ) ;
653
670
}
654
671
672
+ const validationErrors = { ...this . state . validationErrors } ;
673
+ if ( validationErrors [ field . columnInternalName ] ) delete validationErrors [ field . columnInternalName ] ;
674
+
655
675
this . setState ( {
656
676
fieldCollection : fieldCol ,
657
- } , this . performValidation ) ;
677
+ validationErrors
678
+ } , ( ) => {
679
+ if ( validate ) this . performValidation ( ) ;
680
+ } ) ;
658
681
} ;
659
682
660
683
/** Validation callback, used when form first loads (getListInformation) and following onChange */
661
684
private performValidation = ( skipFieldValueValidation ?: boolean ) : void => {
662
685
const { useClientSideValidation, useFieldValidation } = this . props ;
663
- const clientSideValidationDisabled = useClientSideValidation === false ;
664
- const fieldValidationDisabled = useFieldValidation === false ;
665
- const hiddenByFormula : string [ ] = ! clientSideValidationDisabled ? this . evaluateColumnVisibilityFormulas ( ) : [ ] ;
666
- let validationErrors = { ...this . state . validationErrors } ;
667
- if ( ! skipFieldValueValidation && ! fieldValidationDisabled ) validationErrors = this . evaluateFieldValueFormulas ( ) ;
668
- this . setState ( { hiddenByFormula, validationErrors } ) ;
686
+ const { clientValidationFormulas, validationFormulas } = this . state ;
687
+ if ( Object . keys ( clientValidationFormulas ) . length || Object . keys ( validationFormulas ) . length ) {
688
+ this . setState ( {
689
+ isSaving : true , // Disable save btn and fields while validation in progress
690
+ } , ( ) => {
691
+ const clientSideValidationDisabled = useClientSideValidation === false ;
692
+ const fieldValidationDisabled = useFieldValidation === false ;
693
+ const hiddenByFormula : string [ ] = ! clientSideValidationDisabled ? this . evaluateColumnVisibilityFormulas ( ) : [ ] ;
694
+ let validationErrors = { ...this . state . validationErrors } ;
695
+ if ( ! skipFieldValueValidation && ! fieldValidationDisabled ) validationErrors = this . evaluateFieldValueFormulas ( hiddenByFormula ) ;
696
+ this . setState ( { hiddenByFormula, isSaving : false , validationErrors } ) ;
697
+ } ) ;
698
+ }
669
699
}
670
700
671
701
/** Determines visibility of fields that have show/hide formulas set in Edit Form > Edit Columns > Edit Conditional Formula */
@@ -674,8 +704,8 @@ export class DynamicForm extends React.Component<
674
704
}
675
705
676
706
/** Evaluates field validation formulas set in column settings and returns a Record of error messages */
677
- private evaluateFieldValueFormulas = ( ) : Record < string , string > => {
678
- return this . evaluateFormulas ( this . state . validationFormulas , true , true ) as Record < string , string > ;
707
+ private evaluateFieldValueFormulas = ( hiddenFields : string [ ] ) : Record < string , string > => {
708
+ return this . evaluateFormulas ( this . state . validationFormulas , true , true , hiddenFields ) as Record < string , string > ;
679
709
}
680
710
681
711
/**
@@ -688,7 +718,8 @@ export class DynamicForm extends React.Component<
688
718
private evaluateFormulas = (
689
719
formulas : Record < string , Pick < ISPField , "ValidationFormula" | "ValidationMessage" > > ,
690
720
returnMessages = true ,
691
- requireValue : boolean = false
721
+ requireValue : boolean = false ,
722
+ ignoreFields : string [ ] = [ ]
692
723
) : string [ ] | Record < string , string > => {
693
724
const { fieldCollection } = this . state ;
694
725
const results : Record < string , string > = { } ;
@@ -697,6 +728,7 @@ export class DynamicForm extends React.Component<
697
728
if ( formulas [ fieldName ] ) {
698
729
const field = fieldCollection . find ( f => f . columnInternalName === fieldName ) ;
699
730
if ( ! field ) continue ;
731
+ if ( ignoreFields . indexOf ( fieldName ) > - 1 ) continue ; // Skip fields that are being ignored (e.g. hidden by formula)
700
732
const formula = formulas [ fieldName ] . ValidationFormula ;
701
733
const message = formulas [ fieldName ] . ValidationMessage ;
702
734
if ( ! formula ) continue ;
0 commit comments