模板驱动表单
- 实现思路:
- 使用
ngModel
指令来双向绑定密码和确认密码输入框的值。
- 创建一个自定义验证器函数,该函数接收
AbstractControl
并检查密码和确认密码是否一致。
- 将自定义验证器添加到确认密码输入框的
ngModel
上。
- 利用
(blur)
事件在字段失去焦点时触发验证。
- 关键代码片段:
import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms';
export function passwordMatchValidator(): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
const password = control.get('password');
const confirmPassword = control.get('confirmPassword');
return password && confirmPassword && password.value!== confirmPassword.value
? { passwordMismatch: true }
: null;
};
}
- 模板代码(
register.component.html
):
<form #registerForm="ngForm" (ngSubmit)="onSubmit(registerForm.value)">
<div class="form-group">
<label for="password">Password</label>
<input type="password" id="password" name="password" [(ngModel)]="user.password" required>
</div>
<div class="form-group">
<label for="confirmPassword">Confirm Password</label>
<input type="password" id="confirmPassword" name="confirmPassword" [(ngModel)]="user.confirmPassword" required
(blur)="registerForm.control.updateValueAndValidity()"
[ngModelOptions]="{ standalone: true }"
[validators]="[passwordMatchValidator()]">
<div *ngIf="registerForm.controls.confirmPassword.hasError('passwordMismatch') && (registerForm.controls.confirmPassword.touched || registerForm.controls.confirmPassword.dirty)">
Passwords do not match.
</div>
</div>
<button type="submit" class="btn btn-primary">Register</button>
</form>
- 组件代码(
register.component.ts
):
import { Component } from '@angular/core';
import { passwordMatchValidator } from './validators';
@Component({
selector: 'app-register',
templateUrl: './register.component.html',
styleUrls: ['./register.component.css']
})
export class RegisterComponent {
user = { password: '', confirmPassword: '' };
onSubmit(formData: any) {
console.log(formData);
}
}
响应式表单
- 实现思路:
- 使用
FormGroup
和FormControl
创建响应式表单。
- 创建自定义验证器函数并添加到确认密码的
FormControl
中。
- 使用
valueChanges
或statusChanges
结合debounceTime
等操作符在字段失去焦点时触发验证。
- 关键代码片段:
import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms';
export function passwordMatchValidator(): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
const password = control.get('password');
const confirmPassword = control.get('confirmPassword');
return password && confirmPassword && password.value!== confirmPassword.value
? { passwordMismatch: true }
: null;
};
}
- 组件代码(
register.component.ts
):
import { Component } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
import { passwordMatchValidator } from './validators';
import { debounceTime } from 'rxjs/operators';
@Component({
selector: 'app-register',
templateUrl: './register.component.html',
styleUrls: ['./register.component.css']
})
export class RegisterComponent {
registerForm: FormGroup;
constructor() {
this.registerForm = new FormGroup({
password: new FormControl('', Validators.required),
confirmPassword: new FormControl('', [Validators.required, passwordMatchValidator()])
});
this.registerForm.get('password').valueChanges.pipe(
debounceTime(300)
).subscribe(() => {
this.registerForm.get('confirmPassword').updateValueAndValidity();
});
this.registerForm.get('confirmPassword').valueChanges.pipe(
debounceTime(300)
).subscribe(() => {
this.registerForm.get('confirmPassword').updateValueAndValidity();
});
}
}
- 模板代码(
register.component.html
):
<form [formGroup]="registerForm" (ngSubmit)="onSubmit()">
<div class="form-group">
<label for="password">Password</label>
<input type="password" id="password" formControlName="password">
</div>
<div class="form-group">
<label for="confirmPassword">Confirm Password</label>
<input type="password" id="confirmPassword" formControlName="confirmPassword">
<div *ngIf="registerForm.get('confirmPassword').hasError('passwordMismatch') && (registerForm.get('confirmPassword').touched || registerForm.get('confirmPassword').dirty)">
Passwords do not match.
</div>
</div>
<button type="submit" class="btn btn-primary">Register</button>
</form>
onSubmit() {
if (this.registerForm.valid) {
console.log(this.registerForm.value);
}
}