Angular 的 ReactiveFormsModule
相當強大,包含了 two way binding data 以及好用的 validator,以下的範例示範怎麼針對單一欄位以及整體表單自製 validator,如果 username 填寫 chan 的話表示帳號重複,年齡大於 100 的話則錯誤,group 的部分兩者都要填寫。
ts
import { Component, OnInit } from '@angular/core';
import { AbstractControl, FormBuilder, ValidationErrors, ValidatorFn } from '@angular/forms';
@Component({
selector: 'app-form-validator',
templateUrl: './form-validator.component.html',
styleUrls: ['./form-validator.component.scss']
})
export class FormValidatorComponent implements OnInit {
public form = this.fb.group({
username: ['', [this.userNameChecker()]],
age: ['', [this.numberChecker()]]
}, { validators: this.bothRequired() });
public ageLimit: number = 100;
constructor(
private fb: FormBuilder
) { }
ngOnInit(): void {
}
get username(): AbstractControl {
return this.form.controls.username;
}
get age(): AbstractControl {
return this.form.controls.age;
}
private userNameChecker(): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
if (control.value === '') {
return null;
}
if (control.value === 'chan') {
return { userNameExists: true };
}
return null;
}
}
private numberChecker(): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
if (control.value === '') {
return null;
}
if (control.value > this.ageLimit) {
return { tooBig: true };
}
return null;
}
}
private bothRequired(): ValidatorFn {
return (group: AbstractControl): ValidationErrors | null => {
return (group.get('username')?.value === '' || group.get('age')?.value === '') ? { bothRequired: true } : null;
}
}
}
html
<h3>{{ form.value | json }}</h3>
<div [formGroup]="form">
<div>
username: <input type="text" formControlName="username">
<div *ngIf="username.errors?.userNameExists">username exists</div>
</div>
<div>
age: <input type="number" formControlName="age">
<div *ngIf="age.errors?.tooBig">age should lower than {{ ageLimit }}</div>
</div>
<div>
<button [disabled]="form.invalid">submit</button>
</div>
</div>