I have User Form where two inputs 'Username' and 'Email' must to be checked for duplication. ▼
this.userForm = this.formBuilder.group({
username: [
this.isEdit ? this.data.user?.nameIdentifier : null,
Validators.required
],
email: [
this.isEdit ? this.data.user?.email : null,
[Validators.required, Validators.email]
]
});
I have custom validator which needs async data to be loaded, and then uses that data to check for duplication. So I placed that validator in subscribe, and I am setting that validation to the form control when async data loads. ▼
this.userService
.getUsers({ pageSize: 5000 })
.pipe(takeUntil(this.destroy$))
.subscribe((users: IGetUsersRes) => {
this.userForm
.get('username')
?.setValidators(
duplicateNameValidator(
users.list, // this one
['nameIdentifier'],
this.data.user
)
);
this.userForm
.get('email')
?.setValidators(
duplicateNameValidator(
users.list, // this one
['email'],
this.data.user
)
);
});
This worked back then, but now when I am switching to my Custom Input this validation from Subscribe doesn't get assigned to Custom Input (maybe because it is in async). My custom input takes parent Form Control validations in this way ▼
export class InputComponent implements OnInit, OnDestroy, ControlValueAccessor {
inputControl = new FormControl();
isDisabled!: boolean;
@Input() debounce = false;
onChange: any = () => {
// any
};
onTouched: any = () => {
// any
};
constructor(@Self() @Optional() public ngControl: NgControl) {
this.ngControl && (this.ngControl.valueAccessor = this);
}
ngOnInit(): void {
this.updateInputValue();
this.setValidators();
}
ngOnDestroy(): void {
this.destroy$.next();
this.destroy$.complete();
}
setValidators(): void {
const control = this.ngControl.control;
const validators: ValidatorFn[] = control?.validator
? [control?.validator]
: [];
this.inputControl.setValidators(validators);
}
updateInputValue(): void {
this.inputControl.valueChanges
.pipe(
takeUntil(this.destroy$),
debounceTime(this.debounce ? 500 : 0),
distinctUntilChanged()
)
.subscribe((res) => {
this.onChange(res);
});
}
clearInput(): void {
this.inputControl.reset(null, { emitEvent: false });
this.onChange();
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
writeValue(value: any): void {
this.inputControl.setValue(value);
}
registerOnChange(fn: any): void {
this.onChange = fn;
}
registerOnTouched(fn: any): void {
this.onTouched = fn;
}
setDisabledState(disabled: boolean): void {
this.isDisabled = disabled;
}
}
I am not sure that I am doing everything correct, so does anybody know how to fix this issue? I think Parent Control validations are assigned on ngOnInit but since my duplicateNameValidator() is in async it needs additional treatment, and I have no idea how to see it in my Custom Input. Searching in Google has poor results, google gets misleaded.