使用 Angular 自定义验证器确认密码



>我有一个密码字段和一个确认密码字段,如果您从上到下填写表格,一切正常。但是,如果我输入密码/密码确认,然后返回更改密码字段,则确认字段将保持"有效",除非我再次更改它以触发自定义验证器再次"检查密码是否匹配"。

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};
}
}
}

表单组件.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() {}
}

提前感谢您的帮助。

您应该将验证添加到表单组而不是字段中。
举个例子:

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;
}
}
}

只是想为任何尝试以类似方式构建表单的人添加一个可能的解决方案/解决方法。

我更新了我的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()运行,如果未运行,则手动为确认字段设置错误。

试试这个解决方案,你需要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,
});

相关内容

  • 没有找到相关文章

最新更新