Как улучшить эту директиву, чтобы показать пользовательскую ошибку с mat-error - PullRequest
0 голосов
/ 08 мая 2019

У меня есть форма, созданная с помощью компонентов формы AngularMaterial. Я хочу отобразить ошибку, когда элемент управления формы имеет недопустимое состояние. Это сообщение должно рассчитываться каждый раз, когда изменяется статус или значение элемента управления формы. В качестве входных данных у меня будет элемент управления формы и объект ошибок.

Я подошел к этой проблеме, создав структурную директиву, но я не уверен, что это лучшее решение для нее, синтаксис заставляет меня усомниться в этом.

Директива:

@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();
  }

}

Применяется директива:

<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

В настоящее время подход, который я использовал, работает, но я хотел бы узнать другие альтернативы или предложения по его улучшению.

1 Ответ

0 голосов
/ 08 мая 2019

Я бы сделал это, используя AbstractControl hasErrors.Таким образом, мы пишем сообщения об ошибках отдельно в HTML и определяем триггеры в объявлении FormControl.Кроме того, это избавляет от необходимости использования каких-либо методов.

// Declare the 'magnitud' control
magnitud: FormControl;

// Initialize the control with the 'required' and 'max' validators
ngOnInit(): void {
  this.magnitud = new FormControl('', [Validators.required, Validators.max(600)]);
}

HTML будет выглядеть примерно так:

<mat-form-field floatLabel="always" >
  <mat-label>Magnitud</mat-label>
  <input matInput type="number" formControlName="magnitud">
  <mat-error *ngIf="magnitud.hasError('required')">Es requerido</mat-error>
  <mat-error *ngIf="magnitud.hasError('max')">Maximo 600</mat-error>
</mat-form-field>

Надеюсь, это поможет.

...