MarieSpeak
MarieSpeak

Reputation: 77

Angular - How to validate two pairs of fields independently

I want to validate two pairs of fields independently.

One pair of fields is the password. I want to check that they are the same.

The second pair of fields is the email address. I want to check that they are the same.

The method below doesn't work or I just don't know how to do it.

I can not. Tell me how to do it?

        export class RegistrationComponent implements OnInit {

          loginForm!:FormGroup;


          constructor(private formBuilder: FormBuilder) {
          }

          ngOnInit(): void {

            this.loginForm = this.formBuilder.group({

              email1: ['', {
                validators: [Validators.required]
              }],

              email2: ['', {
                validators: [Validators.required]
              }],

              password1: ['', {
                validators: [Validators.required]
              }],

              password2: ['', {
                validators: [Validators.required]
              }]

            },

            {validators: this.matchData('email1','email2', 'password1', 'password2')});

          }

          get email1() {
            return this.loginForm.controls['email1'];
          }

          get email2() {
            return this.loginForm.controls['email2'];
          }

          get password1() {
            return this.loginForm.controls['password1'];
          }

          get password2() {
            return this.loginForm.controls['password2'];
          }


          public matchData(email1: any, email2: any, password1: any, password2: any): ValidatorFn {

            return (control: AbstractControl): ValidationErrors | null => {

              let passwordOne = control.get(password1)?.value;
              let passwordTwo = control.get(password2)?.value;

              let emailOne = control.get(email1)?.value;
              let emailTwo = control.get(email2)?.value;

              if (passwordOne != passwordTwo) {
                return { 'noMatchPass': true }
              }
                return null

            }
          }


        }

HTML

    <input type="email" formControlName="email1">
    <div *ngIf="email1.errors?.['required']"> Email address required </div>

    <input type="email" formControlName="email2">
    <div *ngIf="email2.errors?.['required']"> Email address required </div>
    <div *ngIf="loginForm.hasError('noMatchEmail')">Email address does not match</div>


    <input type="password" formControlName="password1">
    <div *ngIf="password1.errors?.['required']"> Password required </div>

    <input type="password" formControlName="password2">
    <div *ngIf="password2.errors?.['required']"> Password required </div>
    <div *ngIf="loginForm.hasError('noMatchPass')"> Passwords do not match </div>

Upvotes: 0

Views: 307

Answers (2)

MarieSpeak
MarieSpeak

Reputation: 77

  <br><br><br>

  <form [formGroup]="loginForm">


    <label for="email1">Email</label>
    <br>
    <input type="email" (ngModelChange)="changeFieldMail()" formControlName="email1" id="email1">
    <div *ngIf="email1.errors?.['required']"> Necessarily </div>

    <br><br>

    <label for="email2">Repeat</label>
    <br>
    <input type="email" (ngModelChange)="changeFieldMail()" formControlName="email2" id="email2">
    <div *ngIf="email2.errors?.['required']"> Necessarily </div>
    <div *ngIf="loginForm.hasError('noMatchMail')">Email address does not match</div>

    <br><br><br><br>

    <label for="password1">Password</label>
    <input type="password" (ngModelChange)="changeFieldPass()" formControlName="password1" id="password1">
    <div *ngIf="password1.errors?.['required']"> Necessarily </div>

    <br><br>

    <label for="password2">Repeat</label>
    <input type="password" (ngModelChange)="changeFieldPass()" formControlName="password2" id="password2">
    <div *ngIf="password2.errors?.['required']"> Necessarily </div>
    <div *ngIf="loginForm.hasError('noMatchPass')">Passwords do not match</div>

    <br><br>

    <button type="submit" [disabled]="!loginForm.valid" >
      Отправить
    </button>



  </form>

HTML

  import {Component, OnInit} from '@angular/core';
  import {AbstractControl, FormBuilder, FormGroup, ValidationErrors, ValidatorFn, Validators} from "@angular/forms";
  import {Router} from "@angular/router";

  @Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styles: [``],
  })
  export class AppComponent implements OnInit {




    loginForm:FormGroup = this.formBuilder.group({email1: [''], email2: [''], password1: [''], password2: ['']});


    public editMail!:boolean;
    public editPass!:boolean;



    constructor( private formBuilder: FormBuilder,
                 private router: Router,) {
    }

    ngOnInit(): void {

        this.loginForm = this.formBuilder.group({
          email1: ['', {
            validators: [
              Validators.required,
            ],
            updateOn: 'change'
          }],
          email2: ['', {
            validators: [
              Validators.required,
            ],
            updateOn: 'change'
          }],
          password1: ['', {
            validators: [
              Validators.required,
            ],
            updateOn: 'change'
            /* change
               blur
               submit */
          }],
          password2: ['', {
            validators: [
              Validators.required,
            ],
            updateOn: 'change'
            /* change
               blur
               submit */
          }]
        }, {validators: this.matchPassword('email1', 'email2', 'password1', 'password2')});



    }

    get email1() {
      return this.loginForm.controls['email1'];
    }

    get email2() {
      return this.loginForm.controls['email1'];
    }

    get password1() {
      return this.loginForm.controls['password1'];
    }

    get password2() {
      return this.loginForm.controls['password2'];
    }

    // Сверяем два пароля на одинаковость
    public matchPassword(email1: any, email2: any, password1: any, password2: any): ValidatorFn {

      return (control: AbstractControl): ValidationErrors | null => {


        if (this.editMail) {
          let mailOne = control.get(email1)?.value;
          let mailTwo = control.get(email2)?.value;

          if (mailOne != mailTwo) {
            return { 'noMatchMail': true }
          }
        } else if (this.editPass) {
          let passwordOne = control.get(password1)?.value;
          let passwordTwo = control.get(password2)?.value;

          if (passwordOne != passwordTwo) {
            return { 'noMatchPass': true }
          }
        }



        return null;

      }
    }



    changeFieldMail() {
      this.editMail = true
      this.editPass = false
    }


    changeFieldPass() {
      this.editMail = false
      this.editPass = true
    }

  }

https://github.com/Favorskij/matchAng

https://stackblitz.com/edit/angular-ivy-asdfva?file=src%2Fapp%2Fapp-routing.module.ts,src%2Fapp%2Fapp.component.html

Upvotes: 0

Titus Sutio Fanpula
Titus Sutio Fanpula

Reputation: 3613

You can create a custom validator, for an example this code below is a custom validator for match.validator.ts:

import {
  AbstractControl,
  FormGroup,
  ValidationErrors,
  ValidatorFn,
} from "@angular/forms";
export const matchValidator = (
  matchWith: string,
  message?: string
): ValidatorFn => {
  return (control: AbstractControl): ValidationErrors | null => {
    const value = control.value;
    if (value) {
      const formGroup = control.parent as FormGroup;
      const defaultError = {
        value,
        expectedValue: "",
      };
      if (formGroup && formGroup.get(matchWith) instanceof AbstractControl) {
        const matchValue = formGroup.get(matchWith)?.value;
        if (value !== matchValue) {
          defaultError.expectedValue = matchValue;
          return {
            ...defaultError,
            message: message,
          };
        }
        formGroup.get(matchWith)?.valueChanges.subscribe(() => {
          control.updateValueAndValidity();
        });
      } else {
        if (control.value !== matchWith) {
          defaultError.expectedValue = matchWith;
          return {
            ...defaultError,
            message: message,
          };
        }
      }
    }
    return null;
  };
};

Now you can use that's match validator like an angular validator.

For an example:

this.formGroup = new FormBuilder().group({
  email: [null],
  confirmEmail: [
    null,
    Validators.compose([
      matchValidator('email', 'Confirm email does not match with email'),
    ]),
  ],
  password: [null],
  confirmPassword: [
    null,
    Validators.compose([
      matchValidator(
        'password',
        'Confirm password does not match with password'
      ),
    ]),
  ],
});

Live Code:: https://stackblitz.com/edit/angular-ivy-rltfm5?file=src/app/app.component.ts

Live Preview:: https://angular-ivy-rltfm5.stackblitz.io

I hope it can help.

Upvotes: 1

Related Questions