템플릿기반 폼을 사용하려면 FormsModule 라이브러리를 사용한다.
<input type="text" [(ngModel)]="firstName" #name="ngModel"
required minlength="4" appForbiddenName="bob" >
[(ngModel)]="firstName"은 firstName 프로퍼티와 input엘리먼트 value속성을 바인딩하는 것이므로 input엘리먼트의 valid와 같은 프로퍼티에는 접근할 수 없다.
템플릿변수는 HTML엘리먼트를 참조하며 위에서는 HTMLInputElement를 참조하기때문에 value프로퍼티등 html엘리먼트가 제공하는 프로퍼티만 사용가능하다.
#name="ngModel"와 같이 템플릿변수에 ngModel디렉티브를 할당하면 name 템플릿변수는 ngModel타입이 되며 valid, touched...같은 프로퍼티를 제공한다.
required , minlength="4"은 HTML 유효성 검사 어트리뷰트이고 ppForbiddenName="bob"은 커스텀 유효성검사다.
<div *ngIf="name.invalid && (name.touched || name.dirty )">
<div *ngIf="name.errors?.['required']">
Name is Required
</div>
<div *ngIf="name.errors?.['minlength']">
Name is minlength
</div>
</div>
HTML 유효성검사 어트리뷰트는 ngModel디렉티브가 지원하므로 ngModel타입의 name 템플릿변수를 사용하면 유효성검사를 할 수 있다.
appForbiddenName="bob"은 커스텀유효성검사로 appForbiddenName디렉티브가 수행한다.
커스텀 디렉티브를 만들어서 유효성검사를 해야 한다.
providers:[{provide:NG_VALIDATORS, useExisting:ForbiddenNameDirective, multi:true}]
프로바이더에 NG_VALIDATORS를 사용해야 한다.
export class ForbiddenNameDirective implements Validator {
validate(control: AbstractControl<any, any>): ValidationErrors | null {
Validate를 구현해야하고 ValidationErrors | null 를 반환해야 한다.
프로바이더에 NG_VALIDATORS를 전달하기때문에 ngModel디렉티브가 required, minlength, appForbiddenName 유효성검사를 수행하고 결과를 ValidationErrors객체형태로 반환한다.
<form #heroForm="ngForm">
템플릿기반폼에서는 ngForm디렉티브를 사용하면 앵귤러가 내부적으로 FormGroup인스턴스를 만들고 heroForm템플릿변수에 바인딩한다.
<form [formGroup]="heroForm" #formDir="ngForm">
반응형폼에서는 formGroup인스턴스를 직접 클래스코드에서 만든다.
이제 heroForm을 사용해서 유효성검사를 할 수 있다.
<input type="text" id="name" name="name" [(ngModel)]="hero.name"
#name="ngModel" required minlength="4" appForbiddenName="bob">
폼콘트롤은 [(ngModel)]="hero.name"로 먼저 바인딩하고나서 #name="ngModel로 할당해야 한다. 이제 name템플릿변수로 유효성검사를 할 수 있다.
<div *ngIf="name.invalid && (name.touched || name.dirty)" class="alert">
name.invalid일때와 touched로 포커스를 잃었을때 또는 dirty로 사용자 상호작용이 발생했을때 유효성불일치 메세지를 보여주기위해 name의 상태를 검사한다.
<div *ngIf="name.errors?.['required']">
name.error의 인덱서블프로퍼티들 개별적으로 검사한다.