it-swarm.com.de

Validierung mit ControlValueAccessor in übernehmen Angular

Ich habe eine benutzerdefinierte Formularsteuerungskomponente (es ist eine verklärte Eingabe). Der Grund dafür, dass es sich um eine benutzerdefinierte Komponente handelt, ist die Vereinfachung von Änderungen an der Benutzeroberfläche. Wenn wir also die Art und Weise ändern, in der wir unsere Eingabesteuerelemente grundlegend ändern, ist es einfach, Änderungen in der gesamten Anwendung zu verbreiten.

Derzeit verwenden wir Material Design in Angular https://material.angular.io

welche Stile steuern sehr gut an, wenn sie ungültig sind.

Wir haben ControlValueAccessor implementiert, damit wir unserer benutzerdefinierten Komponente einen formControlName übergeben können, der perfekt funktioniert. Das Formular ist gültig/ungültig, wenn das benutzerdefinierte Steuerelement gültig/ungültig ist und die Anwendung wie erwartet funktioniert.

Das Problem ist jedoch, dass wir die Benutzeroberfläche innerhalb der benutzerdefinierten Komponente darauf abstimmen müssen, ob sie ungültig ist oder nicht. Dies scheint uns nicht möglich zu sein. Die Eingabe, die tatsächlich gestaltet werden muss, wird niemals validiert Übergibt einfach Daten an und von der übergeordneten Komponente.

KOMPONENTEN.ts

import { Component, forwardRef, Input, OnInit } from '@angular/core';
import {
    AbstractControl,
    ControlValueAccessor,
    NG_VALIDATORS,
    NG_VALUE_ACCESSOR,
    ValidationErrors,
    Validator,
} from '@angular/forms';

@Component({
  selector: 'app-input',
  templateUrl: './input.component.html',
  styleUrls: ['./input.component.css'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => InputComponent),
      multi: true
    }
  ]
})
export class InputComponent implements OnInit, ControlValueAccessor {
  writeValue(obj: any): void {
    this._value = obj;
  }
  registerOnChange(fn: any): void {
    this.onChanged = fn;
  }
  registerOnTouched(fn: any): void {
    this.onTouched = fn;
  }
  setDisabledState?(isDisabled: boolean): void {
    this.disabled = isDisabled;
  }

  get value() {
    return this._value;
  }

  set value(value: any) {
    if (this._value !== value) {
      this._value = value;
      this.onChanged(value);
    }
  }

  @Input() type: string;

  onBlur() {
    this.onTouched();
  }

  private onTouched = () => {};
  private onChanged = (_: any) => {};
  disabled: boolean;

  private _value: any;

  constructor() { }

  ngOnInit() {
  }

}

COMPONENT.html

<ng-container [ngSwitch]="type">
  <md-input-container class="full-width" *ngSwitchCase="'text'">
    <span mdPrefix><md-icon>lock_outline</md-icon> &nbsp; </span>
    <input mdInput placeholder="Password" type="text" [(ngModel)]="value" (blur)="onBlur()" />
  </md-input-container>
</ng-container>

anwendungsbeispiel auf Seite:

HTML:

<app-input type="text" formControlName="foo"></app-input>

TS:

this.form = this.fb.group({
        foo: [null, Validators.required]
    });
5
matthall74

Antwort hier gefunden:

Erhalten Sie Zugriff auf FormControl von der benutzerdefinierten Formularkomponente in Angular

Ich bin nicht sicher, ob dies der beste Weg ist, und ich würde es lieben, wenn jemand einen schöneren Weg findet, aber die Eingabe des Kindes an die auf diese Weise erhaltene Formularsteuerung zu lösen, hat unsere Probleme gelöst

3
matthall74

Außerdem gilt: Kann als schmutzig betrachtet werden, aber für mich ist es der Trick:

  1. lassen Sie Ihre Komponente die Validator-Schnittstelle implementieren. 2 In der Validate-Funktion gelangen Sie mit dem Controlcontainer zur äußeren Formularsteuerung Ihrer Komponente.
  2. Verfolgen Sie den Status des übergeordneten Formularsteuerelements (VALID/INVALID) mithilfe einer Variablen.
  3. prüfe auf Berührungen. Führen Sie Validierungsaktionen für Ihre Felder nur dann durch, wenn die Option "true" berührt und der Status geändert wurde.
1
SomeOne_1

Sie können über DI auf die Variable NgControl zugreifen. NgControl enthält alle Informationen zum Validierungsstatus. Um NgControl abzurufen, sollten Sie Ihre Komponente nicht über NG_VALUE_ACCESSOR bereitstellen.

@Component({
  selector: 'custom-form-comp',
  templateUrl: '..',
  styleUrls: ...
})
export class CustomComponent implements ControlValueAccessor {

   constructor(@Self() @Optional() private control: NgControl) {
     this.control.valueAccessor = this;
   }

   // ControlValueAccessor methods and others

   public get invalid(): boolean {
     return this.control ? this.control.invalid : false;
   }

   public get showError(): boolean {
      if (!this.control) {
       return false;
      }

      const { dirty, touched } = this.control;

      return this.invalid ? (dirty || touched) : false;
   }
}

Bitte lesen Sie diesen Artikel , um die vollständigen Informationen zu erfahren.

0
VJAI