14 votes

Angulaire : ControlValueAccessor vs @Input - Quand utiliser quoi avec les formulaires ?

Les ControlValueAccessors sont apparus au cours des derniers mois et je ne sais pas trop pourquoi ni quand je dois les utiliser au lieu d'utiliser @Input avec mes formes réactives.

Voici un exemple de code pour montrer comment j'ai travaillé avec les formulaires réactifs jusqu'à présent :

@Component({
 selector: 'app-my-component',
 template: `<input [formControl]="form.get('specificControlName')"  />` 
 // or the alternative method of [formGroup]="form" and formControlName="specificControlName"
})
export class MyComponent {
 @Input() form: FormGroup; // passed in formGroup

 ngOnInit() {
  form.valueChanges.pipe(
   // do rxjs magic here
  ).subscribe(value => {
   // do something with the value
  })
 }
}

Les formulaires réactifs enregistrent l'état du formulaire, de sorte que je peux accéder à cet état même à partir des composants parents. Je peux également accéder à tous les différents NgControl des attributs comme valid , disabled , dirty et touched .

Qu'apportent les ControlValueAccessors que cette façon de travailler avec les formulaires réactifs n'apporte pas ? Et quels sont les cas d'utilisation où les ControlValueAccessors fonctionnent mieux que les formulaires réactifs ? @Input y @Output en général ?

EDIT :

https://medium.com/angular-in-depth/angular-nested-reactive-forms-using-cvas-b394ba2e5d0d

Dans cet article, l'auteur mentionne les points suivants comme étant les principales différences :

Trois façons de mettre en œuvre des formulaires imbriqués :

...

  1. En passant un handle du FormGroup aux composants enfants via Input et en le référençant dans les templates enfants. Il existe quelques bons tutoriels à ce sujet.

Mais l'inconvénient de cette approche est que vous liez étroitement le groupe de formulaires parent à celui du groupe enfant.

  1. Utilisation des CVA composites.

Pour : Hautement réutilisable, portable. Meilleure encapsulation (les contrôles de formulaires internes du composant ne doivent pas nécessairement être visibles pour les composants parents). Ceci est mieux utilisé lorsque vous avez un grand nombre de modules de formulaire, ce qui est typiquement un grand projet.

Inconvénient : la nécessité de mettre en œuvre l'interface CVA entraîne un code passe-partout.

C'est intéressant, mais cela soulève quelques autres questions : Pourquoi et quand ne voulez-vous pas que vos contrôles de formulaires internes soient visibles pour le parent ? Que signifie "portable" ?

Aussi :

import { Component, OnInit } from '@angular/core';
import { ControlValueAccessor,NG_VALUE_ACCESSOR, NG_VALIDATORS, FormGroup,FormControl, Validator, Validators,AbstractControl, ValidationErrors } from "@angular/forms";

@Component({
  selector: 'app-address-info',
  templateUrl: './address-info.component.html',
  styleUrls: ['./address-info.component.css']
})
export class AddressInfoComponent implements OnInit, ControlValueAccessor {

public addressForm: FormGroup = new FormGroup({
  addressLine: new FormControl("",[Validators.required]),
  areacode: new FormControl('', [Validators.required, Validators.maxLength(5)])
});
  constructor() { }
  ngOnInit() {
  }

  public onTouched: () => void = () => {};

  writeValue(val: any): void {
    val && this.addressForm.setValue(val, { emitEvent: false });
  }
  registerOnChange(fn: any): void {
    console.log("on change");
    this.addressForm.valueChanges.subscribe(fn);
  }
  registerOnTouched(fn: any): void {
    console.log("on blur");
    this.onTouched = fn;
  }
  setDisabledState?(isDisabled: boolean): void {
    isDisabled ? this.addressForm.disable() : this.addressForm.enable();
  }
}

lorsque vous passez dans un FormGroup en un ControlValueAccessor L'auteur initialise un nouveau composant FormGroup à l'intérieur du composant avec la même structure que l'objet transmis. N'est-il pas préférable de passer simplement l'objet FormGroup lui-même alors ? Ou quels sont les avantages de l'encapsulation ?

EDIT2 : Voici une vidéo intéressante sur le sujet :

https://www.youtube.com/watch?v=CD_t3m2WMM8

2voto

Pedro B. Points 39

Utilisez l'API standard Reactive Form chaque fois que vous utilisez du HTML natif natifs (input, select, button, form, etc).

Utiliser ControlValueAccessor par exemple lorsque vous devez travailler avec des éléments HTML (c'est-à-dire mat-list, mat-table, ag-grid-table, etc), la raison est que c'est une interface qui agit comme un pont entre l'API des formulaires Angular et les éléments du DOM. Exemple de ControlValueAccessor

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X