我有一个密码字段和一个确认密码字段,如果您从上到下填写表格,一切正常。但是,如果我输入密码/密码确认,然后返回更改密码字段,则确认字段保持“有效”,除非我再次更改它以触发自定义验证器再次“检查密码是否匹配”。
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() {}
}
在此先感谢您的帮助。