1
votes

Comment définir et obtenir des valeurs de formulaire lorsque nous utilisons la liste déroulante CSS en tant que composant partagé

J'ai un composant partagé qui est une liste déroulante html et css. J'appelle ce composant partagé à partir d'un composant parent avec des données différentes.

Par exemple, j'ai 3 instances de composant partagé du composant parent, donc le groupe de formulaires parent aura 3 formControls. Étant donné que les 3 contrôles de formulaire sont désormais un composant partagé. Comment définir et obtenir des données sélectionnées dans les 3 listes déroulantes.

De même, si un élément par défaut doit être défini pour une liste déroulante, comment pouvons-nous y parvenir?

L'objectif principal ici est d'accéder / d'obtenir toutes les valeurs formControlName dans le groupe de formulaires du composant parent.

J'ai joint le code de démonstration https://stackblitz.com/edit/angular-mncdy5 S'il vous plaît, aidez-moi car je suis dans une phase d'apprentissage!


0 commentaires

3 Réponses :


3
votes

Vous devez implémenter ControlValueAccessors dans le composant partagé afin de pouvoir leur attacher formControls dans le composant parent. Voici un excellent article à ce sujet.

https://medium.com/@majdasab/implementing-control-value-accessor-in-angular-1b89f2f84ebf

Voici comment votre composant customDropdown doit se pencher pour implémenter ControlValueAccessors

this.parentForm = this.fb.group({
  district: ['bangalore', Validators.required], <--- SETS THE DEFAULT VALUE OF THE FORM CONTROL
  distance: [''],
  state:['']
});

Maintenant que nous avons ajouté la possibilité d'attacher formControls à votre composant personnalisé, vous pouvez les ajouter au code HTML de votre app.component:

<form [formGroup]="parentForm">
    <app-common-dropdown placeHolder="select district" [dropDownId]="'districtLabel'" [dataList]="['bangalore','chennai','pune']" formControlName="district" ></app-common-dropdown>
    <app-common-dropdown placeHolder="select distance" [dropDownId]="'distanceLabel'" [dataList]="[100,200,300,400]" formControlName="distance" ></app-common-dropdown>
    <app-common-dropdown placeHolder="select state" [dropDownId]="'stateLabel'" [dataList]="['karnataka','tamil nadu','mumbai']" formControlName="state"  ></app-common-dropdown>
</form>

<button type="submit" (click)="getFormValues()">submit</button>

Et vous devrez ajuster les noms dans votre formGroup car ils ne correspondent pas au formulaire html

import { OnInit } from '@angular/core';
import { Component, forwardRef, HostBinding, Input } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

@Component({
  selector: 'app-common-dropdown',
  templateUrl: './common-dropdown.component.html',
  styleUrls: ['./common-dropdown.component.css'],
  providers: [     
      {       provide: NG_VALUE_ACCESSOR, 
              useExisting: forwardRef(() => CommonDropdownComponent),
              multi: true     
      }
    ] 
})
export class CommonDropdownComponent implements ControlValueAccessor {

  @Input() placeHolder: string;
  @Input() dropDownId: string;
  @Input() dataList: any;

  onChange: any = () => {}
  onTouch: any = () => {}
  val= "" // this is the updated value that the class accesses

  set value(val){  // this value is updated by programmatic changes if( val !== undefined && this.val !== val){
    this.val = val
    this.onChange(val)
    this.onTouch(val)
  }


  constructor() { }

  ngOnInit() {
  }

  // this method sets the value programmatically
  writeValue(value: any){ 
    this.value = value
  }
  registerOnChange(fn: any){
    this.onChange = fn
  }
  registerOnTouched(fn){
    this.onTouch = fn
  }

  propagateChange(_){

  }

  selectClicked(event: any) {
    const ele = event.srcElement.parentNode;
    ele.classList.toggle('cs-active');
  }

  selectedOption(ctrl: string, value: string) {
    this.onChange(value) // <-- CRUCIAL need to inform formControl to update the value 
    document.getElementById(ctrl).innerHTML = value;
    const ele = document.getElementById(ctrl).parentElement;
    ele.classList.toggle('cs-active');
  }

  closeDropDown(event: any) {
    const ele = event.srcElement;
    ele.classList.remove('cs-active');
  }
}

formControlName doit correspondre à une propriété dans le parentForm.


6 commentaires

@Quellson pourriez-vous s'il vous plaît regarder dans mon code de démonstration et me dire quel est le bon endroit pour ajouter un formControlName dans mon composant partagé.


@Quellson, merci mon pote. L'implémentation ci-dessus donne simplement la bonne capacité de contrôler le groupe de formulaires à partir du composant parent lui-même


Heureux que cela ait aidé!


pourriez-vous s'il vous plaît laissez-moi savoir comment définir la valeur par défaut du composant parent. Je dois définir la valeur par défaut du district comme «bangalore». J'ai essayé d'utiliser this.parentForm.controls ['district']. SetValue ('bangalore') - cela ne fonctionne pas


J'ai mis à jour ma réponse pour que le district ait une valeur par défaut pour commencer, la définition des valeurs par défaut est effectuée lors de l'initialisation du formGroup.


J'ai essayé de répliquer avec votre entrée mais je n'ai pas pu le définir. Veuillez vérifier ce stackblitz.com/edit/angular-nuagbc . Merci de votre aide.



2
votes

J'ai changé votre code de démonstration, vérifiez ici: https://stackblitz.com/edit/ angular-sge8r3

Dans CommonDropdownComponent j'ai ajouté un Output () qui émet la valeur sélectionnée dans la liste déroulante:

setDistrict(value: string): void {
  this.district = value;
}


3 commentaires

merci, mais nous pourrions finir par ajouter une nouvelle méthode et une nouvelle variable à chaque fois que nous aurons une nouvelle liste déroulante. Et aussi il serait difficile de gérer les validations de cette manière.


@Onera vous pouvez également éviter de créer des variables et des méthodes pour chaque liste déroulante. Vous pouvez définir des valeurs dans parentForm . Et il peut également y avoir une méthode pour cela, qui obtiendra un type de liste déroulante comme argument.


Un moyen de définir une valeur par défaut dans la liste déroulante?



1
votes

Il existe plusieurs façons de procéder. @porgo mentionné est une méthode. Veuillez vérifier l'url ci-dessous pour l'implémentation en utilisant @ViewChild

https://stackblitz.com/edit/angular-k92uxr

Veuillez vous référer à l'url ci-dessous pour les composants de communication b.w
https://angularfirebase.com/lessons/sharing-data -entre-composants-angulaires-quatre-méthodes /


0 commentaires