기본으로 제공되는 validation외에 cusom validation을 사용하는 방법을 알아보겠습니다.
여기에서는 정규식 적용하기와 새로운 validation 적용하는 방법을 간단히 로그인 form을 활용해 알아보겠습니다.
먼저 template을 작성합니다.
material을 적용하면 에러 메시지를 쉽게 표현할 수 있으므로 여기에서는 angular material을 적용한 template을 작성하겠습니다.
{% raw %}
<form [formGroup]="loginForm" (ngSubmit)="submit($event)">
<mat-form-field>
<input type="text" formControlName="id" placeholder="ID" tabindex="1" />
<mat-error>ID를 입력해주세요.</mat-error>
</mat-form-field>
<mat-form-field>
<input type="password" formControlName="password" placeholder="로그인 p/w 재설정" tabindex="4" />
<mat-error>영문 대소문자, 숫자, 특수문자 포함 8 ~ 14자리</mat-error>
</mat-form-field>
<mat-form-field>
<input type="password" formControlName="passwordConfirm" placeholder="P/W를 한번 더 입력하세요." tabindex="5" />
<mat-error>입력하신 P/W를 한번 더 확인해주세요. </mat-error>
</mat-form-field>
<button type="submit">확인</button>
</form>
{% endraw %}
import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef, NgZone } from '@angular/core';
import { FormGroup, Validators, FormBuilder } from '@angular/forms';
import { ValidatorService } from '../../services/validator.service';
@Component({
selector: 'app',
templateUrl: './app.html',
styleUrls: ['./app.css'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class AppComponent implements OnInit {
loginForm: FormGroup;
constructor(
private fb: FormBuilder,
private validatorService: ValidatorService,
private cd: ChangeDetectorRef,
private zone: NgZone
) {
}
ngOnInit() {
this.loginForm = this.fb.group({
id: ['', [Validators.required]],
password: ['', [Validators.required, Validators.pattern(this.validatorService.passwordValidator)]],
passwordConfirm: ['', [Validators.required, this.validatorService.equalTo('password')]]
});
위의 코드를 보면 password에 정규표현식이 적용되어 있습니다.
password: ['', [Validators.required, Validators.pattern(this.validatorService.passwordValidator)]],
또한 passwordConfirm에는 Validators를 활용하지 않는 새로 작성한 validation이 적용되어 있습니다.
passwordConfirm: ['', [Validators.required, this.validatorService.equalTo('password')]]
이제 service를 작성하겠습니다.
import { Injectable } from '@angular/core';
import { ValidatorFn, AbstractControl } from '@angular/forms';
@Injectable({
providedIn: 'root'
})
export class ValidatorService {
public passwordValidator: RegExp;
constructor() {
this.passwordValidator = /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[#$^+=!*()@%&]).[^/<>:\\]{6,12}$/;
}
public equalTo(field_name: string): ValidatorFn {
return (control: AbstractControl): { [key: string]: any } => {
let isValid = control.root.value[field_name] == control.value;
if (!isValid) {
return { 'equalTo': { isValid } };
}
return null;
};
}
}
passwordValidator는 정규 표현식이 적용되어 있습니다. 정규 표현식에 대해서는 설명이 잘 되어있는 좋은 사이트가 많으므로 여기에서는 설명을 생략하겠습니다.
equalTo 함수를 보면 field_name을 받고, ValdatorFn 형식을 리턴합니다.
모든 control 중 field_name을 가진 control의 값과 현재 control의 값이 일치하면 null (정상)을 일치하지 않으면 { equalTo: false } 값을 리턴합니다.
아래의 조건이 올바로 적용되는지 테스트 해보겠습니다.
모든 테스트가 올바르게 동작한다면 제대로 적용된 것입니다.
위의 코드와 다른 방법으로도 validation을 적용할 수 있습니다.
실시간 적용하기 위해 valueChange에서 validation을 체크할 수도 있고,
실시간 적용을 포기하고 submit 시 할 수도 있습니다.
프로젝트에 알맞은 방법을 찾아 적용하시기 바랍니다.