I have a form made with AngularMaterial form components. I want to display an error when the form control has an invalid state. That message should be calculated everytime either the status or value of the form control changes. As an input i will have the form control and the errors object.
I have approached this problem creating a structural directive but i am not sure it is the best solution for it, the syntax make me doubt about it.
Directive:
@Directive({
selector: '[appMensajeErrores]'
})
export class ErrorValidacionDirective implements OnInit, AfterViewInit, OnDestroy {
control: AbstractControl;
suscripcion: Subscription;
errores: { [key: string]: string };
@Input() set appMensajeErroresControl(c: AbstractControl) {
this.control = c;
}
@Input() set appMensajeErrores(errores: { [key: string]: string }) {
this.errores = errores;
}
constructor(
private templateRef: TemplateRef<any>,
private viewContainer: ViewContainerRef
) { }
ngOnInit(): void {
}
ngAfterViewInit(): void {
this.suscripcion = merge(this.control.valueChanges, this.control.statusChanges).subscribe(_ =>
this.manejarEstadoValidez(), e => console.error(e)
);
}
manejarEstadoValidez(): void {
if (this.control.invalid) {
const mensaje = this.generarMensaje(this.control, this.errores);
this.viewContainer.clear();
this.viewContainer.createEmbeddedView(this.templateRef, { $implicit: mensaje });
} else {
this.viewContainer.clear();
}
}
generarMensaje(control: AbstractControl, errores: { [key: string]: string }): string {
return Object.keys(control.errors)
.reduce((acc, error) => errores[error] ? acc.concat(errores[error]) : acc, [])
.join(',');
}
ngOnDestroy(): void {
this.suscripcion.unsubscribe();
}
}
Directive applied:
<mat-form-field floatLabel="always" >
<mat-label>Magnitud</mat-label>
<input matInput type="number" formControlName="magnitud">
<mat-error *appMensajeErrores="{ required: 'Es requerido', max: 'Maximo 600' };let msg; control: form.get('parametros.magnitud')">{{msg}}</mat-error>
</mat-form-field>
StackBlitz: https://stackblitz.com/edit/angular-material-q3wbeh
Currently the approach i took works but i would like to know other alternatives or suggestions to improve it.