앵귤러/04 폼(Forms)

03 폼 유효성검사 03

linor 2017. 9. 24. 17:41

사용자정의 유효성검사기

내장 유효성 검사기가 응용프로그램의 정확한 사용사례와 항상 일치하지는 않기 때문에 사용자 정의 유효성검사기를 만드는 것이 좋습니다.

이 가이드의 이전 예제에서 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이 없습니다.