Answer the question
In order to leave comments, you need to log in
How to display the entire list of control errors in Angular custom control?
I create a custom control (with ControlValueAccessor, etc.), guided by the article: https://blog.angular-university.io/angular-custom-...
I want all validation errors to be displayed in this control, even external ones, but in fact inside the control there is no list of errors.
Sample code: https://stackblitz.com/edit/ng-custom-control-err?...
Actual behavior:
Expected:
component1 err: { "required": true }
component1 val: ""
component2 err: { "required": true }
component2 val: ""
component1 err: { "customErr": "customErr" }
component1 val: "e"
component2 err: { "customErr": "customErr" }
component2 val: "e"
import { Component, forwardRef, OnDestroy, OnInit } from '@angular/core';
import {
ControlValueAccessor,
FormBuilder,
FormControl,
NG_VALIDATORS,
NG_VALUE_ACCESSOR,
ValidationErrors,
Validator
} from '@angular/forms';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'app-custom-control',
templateUrl: './custom-control.component.html',
styleUrls: ['./custom-control.component.css'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CustomControlComponent),
multi: true
},
{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => CustomControlComponent),
multi: true,
}
],
})
export class CustomControlComponent
implements OnInit, OnDestroy, ControlValueAccessor, Validator {
control = this.fb.control(null);
private onTouched = () => {};
private readonly ngUnsubscribe$ = new Subject<void>();
constructor(
private fb: FormBuilder
) {}
ngOnInit() {}
ngOnDestroy() {
this.ngUnsubscribe$.next();
this.ngUnsubscribe$.complete();
}
registerOnChange(onChange: (value: string | null) => void) {
this.control.valueChanges
.pipe(
takeUntil(this.ngUnsubscribe$)
)
.subscribe(onChange);
}
registerOnTouched(fn: () => void): void {
this.onTouched = fn;
}
writeValue(outsideValue: string | null) {
if (outsideValue) {
this.control.setValue(outsideValue, { emitEvent: false });
}
}
setDisabledState(disabled: boolean) {
if (disabled) {
this.control.disable();
} else {
this.control.enable();
}
}
validate(c: FormControl): ValidationErrors | null {
const value = this.control.value;
const error = value === 'e';
return error ? { customErr: 'customErr' } : null;
}
}
<div>component2 err: {{control?.errors | json}}</div>
<div>component2 val: {{control?.value | json}}</div>
<input [formControl]="control" class="text-control" />
<div>component1 err: {{control?.errors | json}}</div>
<div>component1 val: {{control?.value | json}}</div>
<hr>
<app-custom-control [formControl]="control"></app-custom-control>
import { Component, VERSION } from '@angular/core';
import { FormControl, Validators } from '@angular/forms';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
control = new FormControl(null, Validators.required);
}
Answer the question
In order to leave comments, you need to log in
Because your component that implements ControlValueAccessor knows nothing about errors in the form control. He generally knows nothing about this control, the link here is the formControl directive, which listens to the control and calls writeValue when it is changed externally.
You can make your own directive that will call another method, such as setErrors, but there is no standard such function.
Here in this article you can find a similar implementation, only pristine and touched are transferred there. https://habr.com/ru/post/491062/
Or easier, just pass errors inside via input :)
And in order to transfer internal errors to the top control, you need to implement Validator
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question