03 폼 유효성검사 03
사용자정의 유효성검사기
내장 유효성 검사기가 응용프로그램의 정확한 사용사례와 항상 일치하지는 않기 때문에 사용자 정의 유효성검사기를 만드는 것이 좋습니다.
이 가이드의 이전 예제에서 forbiddenNameValidator 함수를 보겠습니다. 이 함수의 정의는 다음과 같습니다.
shared/forbidden-name.directive.ts (forbiddenNameValidator) |
/** A hero's name can't match the given regular expression */ export function forbiddenNameValidator(nameRe: RegExp): ValidatorFn { return (control: AbstractControl): {[key: string]: any} => { const forbidden = nameRe.test(control.value); return forbidden ? {'forbiddenName': {value: control.value}} : null; }; } |
이 함수는 특정 금지된 이름을 탐지하기 위해 정규표현식을 사용하고 유효성검사기 함수를 리턴하는 팩토리입니다.
이 샘플에서 금지된 이름은 "bob"이므로 유효성검사기는 "bob"이 포함된 영웅이름을 거부합니다. "alice"또는 구성하는 정규식에 일치하는 이름을 거부할 수도 있습니다.
forbiddenNameValidator 팩토리는 구성된 유효성검사기 함수를 리턴합니다. 이 함수는 Angular 컨트롤 객체를 사용하여 제어 값이 유효하면 null을 리턴하고, 그렇지 않으면 유효성검사 오류객체를 리턴합니다. 유효성검사 오류 객체는 일반적으로 이름이 유효성검사 키인 'forbiddenName'이며 값을 오류 메시지 {name}에 삽입할 수 있는 임의의 값 사전입니다.
반응형 폼에 추가하기
반응형 폼에서는 사용자정의 유효성검사기를 추가하는 것이 매우 간단합니다. 함수를 직접 FormControl에 전달하면 됩니다.
reactive/hero-form-reactive.component.ts (validator functions) |
this.heroForm = new FormGroup({ 'name': new FormControl(this.hero.name, [ Validators.required, Validators.minLength(4), forbiddenNameValidator(/bob/i) // <-- Here's how you pass in the custom validator. ]), 'alterEgo': new FormControl(this.hero.alterEgo), 'power': new FormControl(this.hero.power, Validators.required) }); |
템플릿 기반 양식에 추가하기
템플릿 기반 폼에서는 FormControl 인스턴스에 직접 액세스할 수 없으므로 반응형 폼에서처럼 유효성 검사기를 전달할 수 없습니다. 대신 템플릿에 디렉티브를 추가해야합니다.
해당 ForbiddenValidatorDirective는 forbiddenNameValidator 주위의 래퍼 역할을 합니다.
Angular는 유효성검사 프로세스에서 디렉티브의 역할을 인식합니다. 이 디렉티브는 NG_VALIDATORS 공급자와 자체적으로 등록되기 때문입니다. 공급자에는 확장가능한 유효성검사기 모음이 있습니다.
shared/forbidden-name.directive.ts (providers) |
providers: [{provide: NG_VALIDATORS, useExisting: ForbiddenValidatorDirective, multi: true}] |
그런 다음 디렉티브 클래스는 Validator 인터페이스를 구현하므로 Angular 폼과 쉽게 통합 할 수 있습니다. 다음의 나머지 부분은 어떻게 모든 것을 함께 제공하는지 아이디어를 얻는 데 도움이될 디렉티브 입니다.
shared/forbidden-name.directive.ts (directive) |
@Directive({ selector: '[forbiddenName]', providers: [{provide: NG_VALIDATORS, useExisting: ForbiddenValidatorDirective, multi: true}] }) export class ForbiddenValidatorDirective implements Validator { @Input() forbiddenName: string;
validate(control: AbstractControl): {[key: string]: any} { return this.forbiddenName ? forbiddenNameValidator(new RegExp(this.forbiddenName, 'i'))(control) : null; } } |
ForbiddenValidatorDirective가 준비되면 셀렉터에 forbiddenName을 모든 입력 엘리먼트에 추가하기 만하면됩니다. 예:
template/hero-form-template.component.html (forbidden-name-input) |
<input id="name" name="name" class="form-control" required minlength="4" forbiddenName="bob" [(ngModel)]="hero.name" #name="ngModel" > |
사용자 정의 유효성검사 디렉티브는 useClass 대신 useExisting을 사용하여 인스턴스화되었음을 알수 있습니다. 등록된 유효성검사기는 ForbiddenValidatorDirective의 인스턴스 여야하며, forbiddenName 프로퍼티가 "bob"에 바인딩된 폼의 인스턴스 여야합니다. useExisting을 useClass로 바꾸려면 새 클래스 인스턴스를 등록해야합니다. 이것은 forbiddenName이 없습니다. |