Angular에서 "Expected validator to return Promise or Observable" 오류 해결 방법
Angular에서 "Expected validator to return Promise or Observable" 오류 해결 방법
Angular 5 이상 버전에서 폼 컨트롤에 커스텀 async validator를 사용할 때 "Expected validator to return Promise or Observable" 오류가 발생할 수 있습니다.
원인:
async validator는 비동기 작업을 수행하여 유효성 검사 결과를 반환해야 합니다. 하지만 validator가 Promise 또는 Observable을 반환하지 않으면 오류가 발생합니다.
해결 방법:
- validator 함수가 Promise를 반환하도록 수정:
async customValidator(control: AbstractControl): Promise<ValidationErrors | null> {
const result = await this.dataService.validate(control.value);
return result.isValid ? null : { invalid: true };
}
async customValidator(control: AbstractControl): Observable<ValidationErrors | null> {
return this.dataService.validate(control.value).pipe(
map(result => result.isValid ? null : { invalid: true })
);
}
validator 함수에 async 키워드 추가:
async customValidator(control: AbstractControl): Promise<ValidationErrors | null> {
// ... 비동기 작업 수행 ...
return result.isValid ? null : { invalid: true };
}
Validators.compose 사용:
여러 개의 async validator를 사용할 때 Validators.compose
함수를 사용하여 하나의 validator로 합쳐야 합니다.
const validators = Validators.compose([
Validators.required,
this.customValidator
]);
this.form = new FormGroup({
name: new FormControl('', validators),
});
참고:
추가 정보:
- Angular 5 이상 버전에서는 async validator가 Promise 또는 Observable을 반환해야 합니다.
Validators.compose
함수를 사용하여 여러 개의 async validator를 하나의 validator로 합칠 수 있습니다.
Angular 5에서 커스텀 async validator 예제
// app.component.ts
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
import { DataService } from './data.service';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
form: FormGroup;
constructor(private dataService: DataService) {}
ngOnInit() {
this.form = new FormGroup({
name: new FormControl('', [
Validators.required,
this.customValidator
]),
});
}
async customValidator(control: AbstractControl): Promise<ValidationErrors | null> {
const result = await this.dataService.validate(control.value);
return result.isValid ? null : { invalid: true };
}
}
// data.service.ts
import { Injectable } from '@angular/core';
@Injectable()
export class DataService {
constructor() {}
validate(value: string): Promise<{ isValid: boolean }> {
// ... 비동기 작업 수행 ...
return Promise.resolve({ isValid: true });
}
}
// app.component.html
<form [formGroup]="form">
<input type="text" formControlName="name" />
<button type="submit">Submit</button>
</form>
app.component.ts
파일에서customValidator
함수는async
키워드를 사용하여 비동기 작업을 수행하고 Promise를 반환합니다.data.service.ts
파일에서validate
함수는 비동기 작업을 수행하고 결과를 Promise로 반환합니다.app.component.html
파일에서form
컨트롤에customValidator
함수를 사용합니다.
Angular에서 "Expected validator to return Promise or Observable" 오류 해결 방법 (대체 방법)
asyncPipe
를 사용하여 템플릿에서 비동기 validator의 결과를 구독할 수 있습니다.
// app.component.ts
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
import { DataService } from './data.service';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
form: FormGroup;
constructor(private dataService: DataService) {}
ngOnInit() {
this.form = new FormGroup({
name: new FormControl('', Validators.required),
});
}
customValidator(control: AbstractControl): Observable<ValidationErrors | null> {
return this.dataService.validate(control.value).pipe(
map(result => result.isValid ? null : { invalid: true })
);
}
}
// app.component.html
<form [formGroup]="form">
<input type="text" formControlName="name" />
<div *ngIf="form.controls.name.errors | async as errors">
<div *ngIf="errors.invalid">
이름이 유효하지 않습니다.
</div>
</div>
</form>
설명:
app.component.ts
파일에서customValidator
함수는 Observable을 반환합니다.app.component.html
파일에서asyncPipe
를 사용하여form.controls.name.errors
의 값을 구독하고 템플릿에 표시합니다.
RxJS switchMap 사용:
switchMap
연산자를 사용하여 폼 컨트롤 값의 변경에 따라 비동기 validator를 실행할 수 있습니다.
// app.component.ts
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
import { DataService } from './data.service';
import { Observable } from 'rxjs';
import { switchMap } from 'rxjs/operators';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
form: FormGroup;
constructor(private dataService: DataService) {}
ngOnInit() {
this.form = new FormGroup({
name: new FormControl('', Validators.required),
});
this.form.controls.name.valueChanges.pipe(
switchMap(value => this.dataService.validate(value))
).subscribe(result => {
if (!result.isValid) {
this.form.controls.name.setErrors({ invalid: true });
}
});
}
}
app.component.ts
파일에서switchMap
연산자를 사용하여form.controls.name.valueChanges
Observable을dataService.validate
함수와 연결합니다.dataService.validate
함수의 결과는 폼 컨트롤의errors
속성에 설정됩니다.
javascript angular angular5