GEDOPLAN
Webprogrammierung

Angular – Formulare mit ControlValueAccessor

Webprogrammierung
puzzle 3223941 640

Formulare dürften in den meisten Business-Angular-Anwendungen zum täglich Brot gehören. Eigene Komponenten in ein Formular einzubetten ist dabei gar nicht schwer und erlaubt ein nahtloses Zusammenspiel mit FormGroup, Validator & Co.

Ziel ist es, die eigenen Komponenten nahtlos in ein Formular einzubinden. Es sollte keine Rollen spielen, ob wir zur Erfassung unserer Werte ein einfaches Input-Field ein mat-slider aus der Angular Material Bibliothek oder eine selbst geschriebene Komponente verwenden:

    this.form = fb.group({
      number: fb.control<CustomerType | null>(null, [Validators.required, Validators.minLength(5)]),
    })
<input formControlName="number"/>
<mat-slider formControlName="number"/>
<app-customer-number formControlName="number"/>

Damit die korrekte Verbindung zur FormGroup hergestellt werden kann und Validatoren den Status des Formulars basierend auf unserer Komponente setzen genügt ein einfaches Interface: ControlValueAccessor. Dieses Interface muss von unserer Komponente implementiert werden + unsere Komponte muss als VALUE_ACCESSOR registriert werden:

@Component({
  selector: 'app-customer-number',
  standalone: true,
  imports: [ReactiveFormsModule],
  templateUrl: './customer-number.component.html',
  styleUrl: './customer-number.component.scss',
  providers: [
    {provide: NG_VALUE_ACCESSOR, multi: true, useExisting: forwardRef(() => CustomerNumberComponent)},
  ]
})
export class CustomerNumberComponent implements ControlValueAccessor {

  control = new FormControl<number | null>(null);

  constructor() {
    this.control.valueChanges.pipe(takeUntilDestroyed()).subscribe(v => {
      this.onChange(v);
      this.onTouch();
    })
  }

  private onChange: any = () => {
  };
  private onTouch: any = () => {
  };

  registerOnChange(fn: any): void { // "fn" rufen wir bei Änderungen auf
    this.onChange = fn;
  }

  registerOnTouched(fn: any): void { // "fn" rufen wir bei "Touch" auf
    this.onTouch = fn;
  }

  setDisabledState(isDisabled: boolean): void { // wird aufgerufen wenn das control state sich ändert
    if (isDisabled) this.control.disable();
    else this.control.enable();
  }

  writeValue(obj: any): void { // wird aufgerufen wenn sich der control wert ändert
    this.control.patchValue(obj);
  }
}

Damit nicht genug. Zusätzlich könnten wir auch das Interface “Validator” implementieren und (zusätzlich zu den am Control deklarierten Validatoren) eine individuelle Prüfung vorzunehmen:

@Component({
....
  providers: [
    {provide: NG_VALUE_ACCESSOR, multi: true, useExisting: forwardRef(() => CustomerNumberVVComponent)},
    {provide: NG_VALIDATORS, multi: true, useExisting: forwardRef(() => CustomerNumberVVComponent)},
  ]
})
export class CustomerNumberVVComponent implements ControlValueAccessor, Validator {
....
  validate(control: AbstractControl): ValidationErrors | null {
    const value = control.value;

    return (!value || value.startsWith('600')) ? null : {'customerNumber': 'have to start with 600'}
  }

Live. In Farbe. Github

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Bitte füllen Sie dieses Feld aus.
Bitte füllen Sie dieses Feld aus.
Bitte gib eine gültige E-Mail-Adresse ein.
Sie müssen den Bedingungen zustimmen, um fortzufahren.

Autor

Diesen Artikel teilen

LinkedIn
Xing

Gibt es noch Fragen?

Fragen beantworten wir sehr gerne! Schreibe uns einfach per Kontaktformular.

Kurse

weitere Blogbeiträge

Work Life Balance. Jobs bei Gedoplan

We are looking for you!

Lust bei GEDOPLAN mitzuarbeiten? Wir suchen immer Verstärkung – egal ob Entwickler, Dozent, Trainerberater oder für unser IT-Marketing! Schau doch einfach mal auf unsere Jobseiten! Wir freuen uns auf Dich!

Work Life Balance. Jobs bei Gedoplan

We are looking for you!

Lust bei GEDOPLAN mitzuarbeiten? Wir suchen immer Verstärkung – egal ob Entwickler, Dozent, Trainerberater oder für unser IT-Marketing! Schau doch einfach mal auf unsere Jobseiten! Wir freuen uns auf Dich!