@@ -49,6 +49,11 @@ export type ValidationDirective = {
49
49
*/
50
50
export type ValidationProvider = ( value : string , element : HTMLInputElement , params : StringKeyValuePair ) => boolean | string | Promise < boolean | string > ;
51
51
52
+ /**
53
+ * Callback to receive the result of validating a form.
54
+ */
55
+ export type ValidatedCallback = ( success : boolean ) => void ;
56
+
52
57
/**
53
58
* A callback method signature that kickstarts a new validation task for an input element, as a Boolean Promise.
54
59
*/
@@ -385,7 +390,7 @@ export class ValidationService {
385
390
/**
386
391
* A key-value map for element UID to its trigger element (submit event for <form>, input event for <textarea> and <input>).
387
392
*/
388
- private elementEvents : { [ id : string ] : ( e : Event , callback ?: Function ) => any } = { } ;
393
+ private elementEvents : { [ id : string ] : ( e ? : Event , callback ?: ValidatedCallback ) => void } = { } ;
389
394
390
395
/**
391
396
* A key-value map of input UID to its validation error message.
@@ -572,7 +577,7 @@ export class ValidationService {
572
577
private getFormValidationTask ( formUID : string ) {
573
578
let formInputUIDs = this . formInputs [ formUID ] ;
574
579
if ( ! formInputUIDs || formInputUIDs . length === 0 ) {
575
- return null ;
580
+ return Promise . resolve ( true ) ;
576
581
}
577
582
578
583
let formValidators : Validator [ ] = [ ] ;
@@ -591,14 +596,37 @@ export class ValidationService {
591
596
* @param form
592
597
* @param callback
593
598
*/
594
- validateForm = ( form : HTMLFormElement , callback : Function ) => {
599
+ validateForm = ( form : HTMLFormElement , callback ?: ValidatedCallback ) => {
595
600
let formUID = this . getElementUID ( form ) ;
596
601
let formValidationEvent = this . elementEvents [ formUID ] ;
597
602
if ( formValidationEvent ) {
598
- formValidationEvent ( null , callback ) ;
603
+ formValidationEvent ( undefined , callback ) ;
599
604
}
600
605
}
601
606
607
+ /**
608
+ * Handler for validated form submit events.
609
+ * Default calls `submitValidForm(form)` on success
610
+ * and `focusFirstInvalid(form)` on failure.
611
+ * @param form The form that has been validated.
612
+ * @param success The validation result.
613
+ */
614
+ handleValidated = ( form : HTMLFormElement , success : boolean ) => {
615
+ if ( success ) {
616
+ this . submitValidForm ( form ) ;
617
+ }
618
+ else {
619
+ this . focusFirstInvalid ( form ) ;
620
+ }
621
+ }
622
+
623
+ /**
624
+ * Calls `requestSubmit()` on the provided form.
625
+ * @param form The validated form to submit
626
+ */
627
+ submitValidForm = ( form : HTMLFormElement ) => {
628
+ form . requestSubmit ( ) ;
629
+ }
602
630
603
631
/**
604
632
* Focuses the first invalid element within the provided form
@@ -624,7 +652,7 @@ export class ValidationService {
624
652
* @param callback
625
653
* @returns
626
654
*/
627
- isValid = ( form : HTMLFormElement , prevalidate : boolean = true , callback : Function ) => {
655
+ isValid = ( form : HTMLFormElement , prevalidate : boolean = true , callback ?: ValidatedCallback ) => {
628
656
if ( prevalidate ) {
629
657
this . validateForm ( form , callback ) ;
630
658
}
@@ -641,7 +669,7 @@ export class ValidationService {
641
669
* @param callback
642
670
* @returns
643
671
*/
644
- isFieldValid = ( field : HTMLElement , prevalidate : boolean = true , callback : Function ) => {
672
+ isFieldValid = ( field : HTMLElement , prevalidate : boolean = true , callback ?: ValidatedCallback ) => {
645
673
646
674
if ( prevalidate ) {
647
675
let form = field . closest ( "form" ) ;
@@ -658,9 +686,9 @@ export class ValidationService {
658
686
* Returns true if the event triggering the form submission indicates we should validate the form.
659
687
* @param e
660
688
*/
661
- private shouldValidate ( e : Event ) {
689
+ private shouldValidate ( e ? : Event ) {
662
690
// Skip client-side validation if the form has been submitted via a button that has the "formnovalidate" attribute.
663
- return ! ( e !== null && e [ 'submitter' ] && e [ 'submitter' ] [ 'formNoValidate' ] ) ;
691
+ return ! ( e && e [ 'submitter' ] && e [ 'submitter' ] [ 'formNoValidate' ] ) ;
664
692
}
665
693
666
694
/**
@@ -686,7 +714,7 @@ export class ValidationService {
686
714
}
687
715
688
716
let validating = false ;
689
- let cb = ( e : Event , callback ?: Function ) => {
717
+ let cb = ( e ? : Event , callback ?: ValidatedCallback ) => {
690
718
// Prevent recursion
691
719
if ( validating ) {
692
720
return ;
@@ -712,36 +740,18 @@ export class ValidationService {
712
740
713
741
validate . then ( success => {
714
742
this . logger . log ( 'Validated (success = %s)' , success , form ) ;
715
- let isProgrammaticValidate = ! e ;
716
- if ( success ) {
717
- if ( isProgrammaticValidate ) {
718
- callback ( true ) ;
719
- return ;
720
- }
721
- const validationEvent = new CustomEvent ( 'validation' ,
722
- {
723
- detail : { valid : true }
724
- } ) ;
725
- form . dispatchEvent ( validationEvent ) ;
726
-
727
- //Resubmit the form here, after the async validation is completed.
728
- form . requestSubmit ( ) ;
729
-
743
+ if ( callback ) {
744
+ callback ( success ) ;
730
745
return ;
731
746
}
732
747
733
748
const validationEvent = new CustomEvent ( 'validation' ,
734
749
{
735
- detail : { valid : false }
750
+ detail : { valid : success }
736
751
} ) ;
737
752
form . dispatchEvent ( validationEvent ) ;
738
753
739
- if ( isProgrammaticValidate ) {
740
- callback ( false ) ;
741
- }
742
- else {
743
- this . focusFirstInvalid ( form ) ;
744
- }
754
+ this . handleValidated ( form , success ) ;
745
755
} ) . catch ( error => {
746
756
this . logger . log ( 'Validation error' , error ) ;
747
757
} ) . finally ( ( ) => {
0 commit comments