Starting with the following setup for a control value accessor:
@Component({
selector: 'some-datepicker',
template: `
<input
[attr.name]="formControlName"
[matDatepicker]="picker"
[value]="inputValue"
(blur)="onBlur($event)
/>
<mat-datepicker-toggle [for]="picker"></mat-datepicker-toggle>
<mat-datepicker #picker></mat-datepicker>
<div *ngIf="errors">
<ul>
<li *ngFor="let error of errors">{{ error.text }}</li>
</ul>
</div>
`
})
export class DatepickerComponent implements ControlValueAccessor, OnInit {
@Input formControlName: string;
// would like to handle this in the component instead of
// passing this down from the parent component
@Input errors: { code: string; text: string; }[]
// ... left out for brevity
constructor(@Self() public ngControl: NgControl) {
this.ngControl.valueAccessor = this;
}
ngOnInit(): void {}
onBlur(event): void {
// here it is still empty, because the validation has not run yet
console.log('onBlur control.errors: ', this.ngControl.control?.errors);
this.onChangeCallback(event.target.value);
this.writeValue(event.target.value);
}
// ... left out. for brevity
writeValue(value: string): void {
this.value = value;
if (value) {
this.inputDate = new Date(value);
}
}
}
The form control is defined in a parent component. So I could pass the errors as @Input into this 'some-datepicker' component. But is there also a way that I don't have to do this, but instead integrate it into this component itself?
--- update
The stackblitz: https://stackblitz.com/edit/angular-ivy-5jnylk?file=src/app/app.component.ts
In there you will find the error handling to reside in the surrounding app component. What I am trying to achieve is that in the app component you can set validators.
But the following error handling should move to the custom component:
ngOnInit(): void {
// this logic could move to the custom component
this.myForm.valueChanges.pipe(takeUntil(this.destroy$)).subscribe(() => {
this.myControlErrors$.next(
this.mapValidationErrors(this.myForm.controls.someControl.errors)
);
});
}