<input type="text" id="first:name" [(ngModel)]="firstName"
required minlength="5" #firstNameFC="ngModel" appForbiddenName="bob" >
템플릿기반폼에서 커스텀유효성검사를 하려면 폼엘리먼트를 ngModel로 만들어야 valid, error..프로퍼티에 접근할 수 있다.
html에서 지원하는 유효성검사는 ngModel디렉티브의 error프로퍼티로 알 수 있다.
커스텀유효성검사를 하려면 커스텀 디렉티브를 만들어 사용해야 한다.
@Directive({
selector: '[appForbiddenName]',
})
export class ForbiddenNameDirective{
@Input('appForbiddenName') forbiddenName!: string;
constructor() {}
}
selector는 템플릿에서 사용할 디렉티브명이다.
템플릿에서 유효성검사를 수행할 값을 받으므로 Input데코레이터를 사용하며 클래스에서 사용하는 변수명을 달리했다.
입력변수를 사용해서 유효성검사를 수행한 후 결과를 반환하면 된다.
커스텀유효성검사도 ngModel디렉티브가 수행하는 기본 유효성검사의 일부로 수행되어야 결과값이 취합된다.
providers: [
{
provide: NG_VALIDATORS,
useExisting: ForbiddenNameDirective,
multi: true,
},
],
프로바이더에 NG_VALIDATORS를 지정하여 기본유효성검사의 일부로 수행된다.
export class ForbiddenNameDirective implements Validator {
@Input('appForbiddenName') forbiddenName!: string;
constructor() {}
validate(control: AbstractControl<any, any>): ValidationErrors | null {
const regExp = new RegExp(this.forbiddenName,'i');
return this.forbiddenName ? forbiddenNameValidator(regExp)(control) : null;
}
}
implements Validator를 구현하며 validate함수로 결과값을 반환하면 ngModel이 유효성검사의 결과를 가지게 된다.
type ValidationErrors = {
[key: string]: any;
}
ValidationErrors은 string 인덱서블 객체형태다.
function forbiddenNameValidator(nameRe: RegExp): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
const forbidden = nameRe.test(control.value);
return forbidden ? {forbiddenName: {value: control.value}} : null;
};
}
정규표현식을 인자로 받아서 폼콘트롤의 입력값의 매치여부를 반환하는 함수를 따로 만들면 다른 곳에서도 재사용이 가능하다.