0

I have a form where I enter an email and confirm email and then continue to the next page and all is well. The validation works fine when the page initially loads and it's the user's first time, so the input field is not prepopulated from cookie data. However, when the user returns, the input field data is prepopulated from cookie data and that is fine but the submit button is still disabled even though the prepopulated text is valid format. I inspected the elements and it seems to think the field is ng-invalid even though it's valid format.

I noticed when I go to one of the fields and backspace to remove the last character and reinsert the same character as before for email and do the same for the next field, the form is valid again. Even though, it's the same text as before.

I'm wondering why validation fails when the form first loads with prepopulated data?

Here's my code:

export class EmailComponent implements OnInit {   

   public user : User;
   Form : FormGroup; 
   displayErrors : boolean; 

   ngOnInit() {
        // initialize model here
        this.user = {
            Email: '', 
            confirmEmail: ''
        }
    }

     constructor(fb: FormBuilder, private cookieService: CookieService, private cryptoService: CryptoService) {


         var encryptedEmail = this.cookieService.get(AppCookie.EmailAddress);

         var Cookie = null;

         if(encryptedEmail != null && encryptedEmail != 'undefined')
            Cookie = this.cryptoService.Decrypt(encryptedEmail);


         if(Cookie == null) {
            this.Form = fb.group({
                email: ['', [Validators.required, Validators.pattern(EMAIL_REGEXP)]],
                confirmEmail: ['', [Validators.required, Validators.pattern(EMAIL_REGEXP)]]
            },
            {
                validator: this.matchingEmailsValidator('email', 'confirmEmail')
            });

         }
         else {
             this.Form = fb.group({
                email: [Cookie, [Validators.required, Validators.pattern(EMAIL_REGEXP)]],
                confirmEmail: [Cookie, [Validators.required, Validators.pattern(EMAIL_REGEXP)]]
            },
            {
                validator: this.matchingEmailsValidator('email', 'confirmEmail')
            });

         }
     }

    save(model: User, isValid: boolean)
    {

        model.Email = this.Form.get('email').value;

        var encrypted = this.cryptoService.Encrypt(model.Email);

        this.cookieService.put(AppCookie.EmailAddress, encrypted);
    } 

    matchingEmailsValidator(emailKey: string, confirmEmailKey: string): ValidatorFn {
        return (group: FormGroup): {[key: string]: any} => {

            let email = group.controls[emailKey];
            let confirmEmail = group.controls[confirmEmailKey];

            if (email.value !== confirmEmail.value) {
                return {                    
                    mismatch: true
                };
            }
        };
    }
}

and here's my view:

<form [formGroup]="Form" novalidate (ngSubmit)="Form.valid && save(Form.value, Form.valid)">

    <div class="login-wrapper">
        <div class="login-page">

            <section class="login-form form-group">
                <p>
                <input id="email" 
                 [class.email-address-entry]="!displayErrors"
                 [class.email-address-entry-text]="!displayErrors && this.Form.get('email').value !='' "
                 type="email"
                 placeholder="name@domain.com" formControlName="email" />
                </p>

                <p class="login-form__msg">Reenter your email to confirm</p>

                <input id="reenteremail" 
                 [class.email-address-entry]="!displayErrors"
                 [class.entry-border-invalid]="displayErrors && !Form.valid && Form.errors?.mismatch"
                 [class.email-address-entry-text]="!displayErrors && this.Form.get('email').value !='' "
                 (blur)="displayErrors=true"
                 type="email" placeholder="name@domain.com" 
                 formControlName="confirmEmail"/>
                <p class="error-msg" *ngIf="displayErrors && !Form.valid && Form.errors?.mismatch">The email you entered does not match.</p>

            </section>

                <p class="login-confirm">
                    <span>
                     <button type="submit" [disabled]="!Form.valid"  (click)="Form.get('email').length > 0 ? save(Form.value, Form.valid) : NaN">Confirm</button> 
                     </span>
                </p>
        </div>

    </div>
    </form>

EDIT: It's similar to this issue as well:

Angular 2 - Form is invalid when browser autofill

I tried adding this:

  ngAfterViewChecked() {

        if (Cookie) {
            // enable to button here.
            var element = <HTMLInputElement> document.getElementById("confirmBtn");
           element.disabled = false;

        }

But it won't work because fields are still invalid. I need a way to manually set re-validation or change ng-invalid to ng-valid.

Community
  • 1
  • 1
Euridice01
  • 2,510
  • 11
  • 44
  • 76

1 Answers1

1

If you keep a reference to the form instance (either by using reactive forms or by accessing it using @ViewChild) you should be able to write the following in ngAfterViewInit():

for (var i in this.form.controls) {
   this.form.controls[i].updateValueAndValidity();
}

Or perhaps marking the fields as touched will be better in your case:

for (var i in this.form.controls) {
   this.form.controls[i].markAsTouched();
}