GEDOPLAN

Bereits hier https://gedoplan.de/angular-formulare-mit-controlvalueaccessor/ haben wir einen Blick darauf geworfen, wie eigene Formular-/Eingabe-Komponenten in Angular implementiert werden können. Eine Anforderung, die bei uns häufig in Projekten vorkommt, ist die flexible Ergänzung von Validatoren.

Konkret geht es darum, dass Validatoren zum einen „ganz normal“ über das Control definiert werden müssen und zum anderen die Komponente selber ergänzend weitere Validatoren hinzufügt. Ein typisches Beispiel: eine Komponente zur Erfassung einer Kundennummer, die einem bestimmten Format unterworfen ist (Validator auf Ebene der Eingabe-Komponente) und an bestimmten Stellen in der Anwendung ein Pflicht- oder Optionales-Feld ist (Validator auf Ebene der fachlichen Komponente).

Verwendung / fachliche Validatoren:

  form = new FormGroup({
    counter: new FormControl<number|null>(0, Validators.required())
  })

<app-btn-in formControlName="counter"></app-btn-in>

Eingabe-Komponente

@Component({
  selector: 'app-btn-in',
  standalone: true,
  templateUrl: './btn-in.component.html',
  styleUrl: './btn-in.component.scss',
  providers: [
    //removed*: {provide: NG_VALUE_ACCESSOR, multi: true, useExisting: forwardRef(() => BtnInComponent),}
  ]
})
export class BtnInComponent implements ControlValueAccessor, OnInit {
  count = signal<number>(0);
  disabled = false;

  change!: (_: number) => void;
  touch!: () => void;

  constructor(private ngControl: NgControl) {
    // * added instead
    ngControl.valueAccessor = this;

    effect(() => {
      this.change(this.count());
    });
  }

  ngOnInit() {    
     // additional validators
    this.ngControl.control?.addValidators([Validators.max(10)])
    this.ngControl.control?.updateValueAndValidity();
  }

  writeValue(obj: number): void {
    this.count.set(obj)
  }

  registerOnChange(fn: any): void {
    this.change = fn;
  }

  registerOnTouched(fn: any): void {
    this.touch = fn;
  }

  setDisabledState?(isDisabled: boolean): void {
    this.disabled = isDisabled;
  }
}

Die grundlegende Implementierung ändert sich kaum. Die Unterschiede: