Асинхронная валидация (AsyncValidator) компонента angular 2*, передача состояния PENDING

Задача:

Внутренний компонент формы реализующий интерфейс ControlValueAccessor, имеет свою асинхронную валидацию. В нем есть метод
validate(c: AbstractControl): ValidationErrors | null;
который не может обработать ситуацию когда в нем возвращается promise, видно что этот метод работает синхронно.
Форма видела этот компонент только в двух состояниях - VALID, либо INVALID, но нужно получить состояние PENDING.

Решение:

Погуглив оказалось, что есть метод аналогичный, поддерживающий асинронную передачу состояния компонента в родительскую форму, и это метод интерфейса AsyncValidator
validate(c: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null>;

Полезные заметки:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
https://angular.io/api/forms/ControlValueAccessor

interface ControlValueAccessor {
writeValue(obj: any): void
registerOnChange(fn: any): void
registerOnTouched(fn: any): void
setDisabledState(isDisabled: boolean)?: void
}

--

viewProviders: [{ provide: ControlContainer, useExisting: NgForm }],
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => GroupComponent),
multi: true,
},
{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => GroupComponent),
multi: true,
}]
})
export class GroupComponent implements ControlValueAccessor, Validator, OnInit, OnDestroy {

-------------------

// This method is called from parent form to check state of the child component

public validate() {
onsole.log('ChildComponent --> validate --> ', this.childComponentGroup.valid, this.childComponentGroup.status);

-------------------

export interface Validator {
validate(c: AbstractControl): ValidationErrors | null;
registerOnValidatorChange?(fn: () => void): void;
}
/** @experimental */
export interface AsyncValidator extends Validator {
validate(c: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null>;
}

https://angular.io/api/forms/AsyncValidator

1
2
3
4
5
providers: [{provide: NG_ASYNC_VALIDATORS, useExisting: CustomAsyncValidatorDirective, multi:true}]

validate(control: AbstractControl): Observable<ValidationErrors|null> {
return observableOf({'value': true});
}

Never again be confused when implementing ControlValueAccessor in Angular forms
https://blog.angularindepth.com/never-again-be-confused-when-implementing-controlvalueaccessor-in-angular-forms-93b9eee9ee83

https://stackoverflow.com/questions/36235446/angular2-template-driven-async-validator

Share