J'ai un élément personnalisé:

<div formControlName="surveyType">
  <div *ngFor="let type of surveyTypes"
       (click)="onSelectType(type)"
       [class.selected]="type === selectedType">
    <md-icon>{{ type.icon }}</md-icon>
    <span>{{ type.description }}</span>
  </div>
</div>

Lorsque j'essaye d'ajouter le formControlName, j'obtiens un message d'erreur:

ERREUR Erreur: aucun accesseur de valeur pour le contrôle de formulaire avec le nom: 'surveyType'

J'ai essayé d'ajouter ngDefaultControl sans succès. Il semble que c'est parce qu'il n'y a pas d'entrée / sélection ... et je ne sais pas quoi faire.

Je voudrais lier mon clic à ce formControl afin que, lorsque quelqu'un clique sur la carte entière, cela pousse mon «type» dans le formControl. C'est possible?

156
jbtd 13 août 2017 à 14:13

2 réponses

Meilleure réponse

Vous ne pouvez utiliser formControlName que sur des directives qui implémentent ControlValueAccessor.

Implémenter l'interface

Donc, pour faire ce que vous voulez, vous devez créer un composant qui implémente ControlValueAccessor, ce qui signifie implémenter les trois fonctions suivantes :

  • writeValue (indique à Angular comment écrire la valeur du modèle dans la vue)
  • registerOnChange (enregistre une fonction de gestionnaire qui est appelée lorsque la vue change)
  • registerOnTouched (enregistre un gestionnaire à appeler lorsque le composant reçoit un événement tactile, utile pour savoir si le composant a été focalisé).

Enregistrer un fournisseur

Ensuite, vous devez dire à Angular que cette directive est un ControlValueAccessor (l'interface ne la coupera pas car elle est supprimée du code lorsque TypeScript est compilé en JavaScript). Pour ce faire, enregistrant un fournisseur .

Le fournisseur doit fournir NG_VALUE_ACCESSOR et utilise une valeur existante. Vous aurez également besoin d'un forwardRef ici. Notez que NG_VALUE_ACCESSOR doit être un multi-fournisseur.

Par exemple, si votre directive personnalisée est nommée MyControlComponent, vous devez ajouter quelque chose le long des lignes suivantes à l'intérieur de l'objet passé au décorateur @Component:

providers: [
  { 
    provide: NG_VALUE_ACCESSOR,
    multi: true,
    useExisting: forwardRef(() => MyControlComponent),
  }
]

Usage

Votre composant est prêt à être utilisé. Avec les formulaires basés sur des modèles, la liaison ngModel fonctionnera désormais correctement.

Avec les formulaires réactifs, vous pouvez désormais utiliser correctement formControlName et le contrôle de formulaire se comportera comme attendu.

Ressources

241
Lazar Ljubenović 9 déc. 2019 à 08:05

Je pense que vous devriez utiliser formControlName="surveyType" sur un input et non sur un div

68
Vega 13 août 2017 à 11:20