Подтверждение пароля с помощью пользовательских угловых валидаторов - PullRequest
0 голосов
/ 18 октября 2019

У меня есть поле пароля, а также поле подтверждения пароля, и все работает нормально, если вы заполняете форму сверху вниз. Однако, если я введу пароль / подтверждение пароля и затем вернусь, чтобы изменить поле пароля, поле подтверждения останется «действительным», если я не изменю его снова, чтобы пользовательский валидатор снова «проверял, совпадают ли пароли».

form.component.ts - форма получает, так сказать, свой «макет» из register.component.ts. Это позволяет мне динамически создавать формы.

import { Component, OnInit, Input                } from '@angular/core';
import { FormGroup, FormControl, AbstractControl } from '@angular/forms';
import { Router                                  } from '@angular/router';
import { ApiService                              } from 'src/app/services/api.service';

@Component({
  selector:  'app-form',
  templateUrl: './form.component.html',
  styleUrls: ['./form.component.scss']
})
export class FormComponent implements OnInit {

  // Variable Declarations
  @Input() form: {
    api: string
    title: string,
    inputs: [{ placeholder: string, type: string, name: string, validators: []}],
    link: { text: string, url: string },
    button: string
   };
   formGroup: FormGroup;

  // Variable Initialization
   inputControls = {};
   message = {};

  // Constructor
  constructor(private api: ApiService, private router: Router) { }

  // On Component Init
  ngOnInit() {

    // Build form
    this.form.inputs.forEach(input => {
      if (input.name === 'confirm') {
        this.inputControls[input.name] = new FormControl(null, [this.PasswordsMatch]);
      } else {
        this.inputControls[input.name] = new FormControl(null, input.validators);
      }
    });

    this.formGroup = new FormGroup(this.inputControls);
  }

  PasswordsMatch = (control: AbstractControl): {[key: string]: boolean} | null => {
    // Check if root exists first - otherwise console error ".value of undefined"
    if (control.root.get('password')) {
      return control.value === control.root.get('password').value ? null : {mismatch: true};
   }
  }
}

form.component.html

<div class="container">
  <form [formGroup]="formGroup">

    <span>{{ form.title }}</span>

    <div *ngFor = "let input of form.inputs; let i = index">
      <input [type]            = "input.type"
             [placeholder]     = "input.placeholder"
             [formControlName] = "input.name">
    </div>

    <button [disabled]="!formGroup.valid">{{ form.button }}</button>
    <a [routerLink]="form.link.url">{{ form.link.text }}</a>

  </form>
</div>

register.component.ts -Я не мог понять, как передать пользовательский валидатор для поля подтверждения пароля, поэтому я просто передал Validators.required, но он просто перезаписывается пользовательским валидатором при создании формы.

import { Component  } from '@angular/core';
import { Validators } from '@angular/forms';

@Component({
  selector: 'app-register',
  templateUrl: './register.component.html',
  styleUrls: ['./register.component.scss']
})
export class RegisterComponent {

  // Validators (Validators.required is used to differentiate between error messages)
  validators = {
    name:     [ Validators.required, Validators.pattern('[a-zA-Z]{2,20}') ],
    email:    [ Validators.required, Validators.pattern('[a-zA-Z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}')],
    username: [ Validators.required, Validators.pattern('[a-zA-Z0-9.+%+-]{1,30}')],
    password: [ Validators.required, Validators.pattern('(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])[a-zA-Z0-9!@#$%^&*-_=+]{10,}')],
    confirm:  [ Validators.required, ]
  };

  // Form data
  form = {
    api: 'register',
    title: 'Are you ready?',
    inputs: [
      { placeholder: 'First Name',       type: 'text',     name: 'name',     validators: this.validators.name     },
      { placeholder: 'Email Address',    type: 'email',    name: 'email',    validators: this.validators.email    },
      { placeholder: 'Mage Name',        type: 'text',     name: 'username', validators: this.validators.username },
      { placeholder: 'Password',         type: 'password', name: 'password', validators: this.validators.password },
      { placeholder: 'Confirm Password', type: 'password', name: 'confirm',  validators: this.validators.confirm  },
    ],
    link: { text: 'I\'m already a Wizard!', url: '/login' },
    button: 'I\'m Ready for War'
  };

  constructor() {}
}

Спасибозаранее за вашу помощь.

Ответы [ 3 ]

0 голосов
/ 18 октября 2019

Просто хотел добавить возможное решение / обходной путь для всех, кто пытается построить формы подобным образом.

Я обновил свой form.component.html для вызова функции (keyup).

<div class="container">
  <form [formGroup]="formGroup">

    <span>{{ form.title }}</span>

    <div *ngFor = "let input of form.inputs; let i = index">
      <input [type]            = "input.type"
             [placeholder]     = "input.placeholder"
             [formControlName] = "input.name"
             (keyup)           = "checkPasswordsMatch(input.name)">
    </div>

    <button [disabled]="!formGroup.valid">{{ form.button }}</button>
    <a [routerLink]="form.link.url">{{ form.link.text }}</a>

  </form>
</div>

В моем form.component.ts я добавил простую функцию checkPasswordsMatch, которая вручную устанавливает ошибки для поля подтверждения пароля, когда поле пароля изменяется, если они больше не совпадают,См. Последнюю функцию ниже:

import { Component, OnInit, Input                } from '@angular/core';
import { FormGroup, FormControl, AbstractControl } from '@angular/forms';
import { Router                                  } from '@angular/router';
import { ApiService                              } from 'src/app/services/api.service';

@Component({
  selector:  'app-form',
  templateUrl: './form.component.html',
  styleUrls: ['./form.component.scss']
})
export class FormComponent implements OnInit {

  // Variable Declarations
  @Input() form: {
    api: string
    title: string,
    inputs: [{ placeholder: string, type: string, name: string, validators: []}],
    link: { text: string, url: string },
    button: string
   };
   formGroup: FormGroup;

  // Variable Initialization
   inputControls = {};
   message = {};

  // Constructor
  constructor(private api: ApiService, private router: Router) { }

  // On Component Init
  ngOnInit() {

    // Build form
    this.form.inputs.forEach(input => {
      if (input.name === 'confirm') {
        this.inputControls[input.name] = new FormControl(null, [this.PasswordsMatch]);
      } else {
        this.inputControls[input.name] = new FormControl(null, input.validators);
      }
    });

    this.formGroup = new FormGroup(this.inputControls);
  }

  // Check if confirm === password anytime the confirm field changes
  PasswordsMatch = (control: AbstractControl): {[key: string]: boolean} | null => {

    // Check if root exists first - otherwise console error ".value of undefined"
    if (control.root.get('password')) {
      return control.value === control.root.get('password').value ? null : {mismatch: true};
   }
  }

  // Check if confirm === password anytime the password field changes
  // "input" is the name of the input field triggering this function
  checkPasswordsMatch(input) {
    if (input === 'password') {
      const p = this.formGroup.get('password');
      const c = this.formGroup.get('confirm');

      c.value === p.value ? c.setErrors(null) : c.setErrors({mismatch: true});
    }
  }
}

Поскольку все эти входные данные являются частью одной и той же FormGroup, форма действительна только тогда, когда все входные данные действительны. Изменение пароля после подтверждения поля подтверждения пароля приведет к запуску checkPasswordsMatch() и установит ошибки вручную для поля подтверждения, если они этого не делают.

0 голосов
/ 24 октября 2019

Попробуйте это решение, вам нужна библиотека проверки ng2 для этого

import { CustomValidators } from 'ng2-validation';
const password = new FormControl('', [Validators.required, Validators.pattern('^(?=.*[A-Z])(?=.*[0-9])(?=.*[a-z]).{8,}$')]);
const confirmPassword = new FormControl('', [Validators.required, CustomValidators.equalTo(password)]);
this.form = this.fb.group({
      password: password,
      confirmPassword: confirmPassword,
    });
0 голосов
/ 18 октября 2019

Вы должны добавить валидацию в группу форм, а не в поле.
Пример:

this.userform = this.fb.group({
            email: new FormControl('', [ Validators.required, Validators.email ]),
            passwordGroup: new FormGroup(                  {
                    password: new FormControl('', [ Validators.required,                        Validators.minLength(6) ]),
                    passwordConfirm: new FormControl('')
                },
                PasswordValidation.MatchPassword
            )
        });

export class PasswordValidation {
    static MatchPassword(AC: AbstractControl) {
        const password = AC.get('password').value; // to get value in input tag
        const confirmPassword = AC.get('passwordConfirm').value; // to get value in input tag
        if (password !== confirmPassword) {
            AC.get('passwordConfirm').setErrors({ MatchPassword: true });
        } else {
            return null;
        }
    }
}
...