web-dev-qa-db-fra.com

Angular 5 + Angular Sélection du matériau + formulaires réactifs == Aucune option initiale affichée

Comme le titre l'indique, j'ai un formulaire réactif contenant plusieurs <mat-select>. Lors du chargement initial du formulaire, l'option initiale ne s'affiche pas même si form.value l'indique.

Composants pertinents:

export class DesJobInfoEditComponent implements OnInit {

...

currentJobData: IJob;
jobTypes: IJobType[];

...

constructor(private fb: FormBuilder) {

    ...

        // Construct forms
        this.createForm();

        this.initializeForm();

}

createForm() {
    this.editJobInfoForm = this.fb.group({
        ...
        JobType: '', // mat-select
        ...
    });
}

initializeForm() {
    this.rebuildForm();
}

rebuildForm() {
    this.editJobInfoForm.reset({
        ...
        JobType: this.jobTypes[this.currentJobData.JobType].DisplayDesc,
        ...
    });
}

}

Html pertinent:

<mat-form-field fxFlex>
      <mat-label>Job Type</mat-label>
       <mat-select formControlName="JobType" placeholder="Job Type">
              <mat-option *ngFor="let jobType of jobTypes" value="jobType.value">
                     {{ jobType.DisplayDesc }}
               </mat-option>
        </mat-select>
  </mat-form-field>

Lorsque le formulaire est chargé, les sélections n'affichent pas l'option initialement sélectionnée. Cependant, elles sont correctement définies, apparemment:

Form value { ... "JobType": "0 - Standard", ... } 

Tout ce qui s'affiche sur le formulaire est l'espace réservé.

Cela semble ne pas être si difficile.

Qu'est-ce que je fais mal?

MODIFIER:

this.jobTypes est chargé lorsque le module est chargé et il s'agit d'un BehaviorSubject qui réside dans mon service de données. J'y souscris dans le constructeur de ce composant ainsi:

this.data.jobTypes.subscribe(jobTypes => { this.jobTypes = jobTypes });

3
OCDDev

Quelques choses

  1. [formControlName] must doit être utilisé avec [formGroup]. Si vous ne souhaitez pas utiliser [formControlName] + [formGroup], vous pouvez utiliser [formControl] à la place.

  2. En mode angulaire, il existe une différence entre spécifier un attribut sous la forme value et [value]. Lorsqu'un attribut est placé entre crochets [], il est interprété comme javascript / script de modèle angulaire (identique à {{}}, je pense). Quand il est pas / entre crochets, il est interprété comme une chaîne (par exemple, value="jobType.value" === [value]="'jobType.value'" et [value]="jobType.value" === value="{{jobType.value}}" (en fait, je pense qu’il existe de subtiles différences entre [value]="jobType.value" et value="{{jobType.value}}", mais w/e)) . Ainsi, lorsque vous écrivez <mat-option *ngFor="let jobType of jobTypes" value="jobType.value">, la valeur de chaque mat-option est "jobType.value" qui, je suppose, ne veut pas de vous. Donc, vous devez changer le code en <mat-option *ngFor="let jobType of jobTypes" [value]="jobType.value">

par exemple.

<mat-form-field [formGroup]='editJobInfoForm' fxFlex>
  <mat-label>Job Type</mat-label>
  <mat-select formControlName="JobType" placeholder="Job Type">
    <mat-option *ngFor="let jobType of jobTypes" [value]="jobType.value">
      {{ jobType.DisplayDesc }}
    </mat-option>
  </mat-select>
</mat-form-field>

Quelque chose de non lié à votre problème, pourquoi avoir à la fois les méthodes createForm() et initializeForm()? Pourquoi pas simplement

constructor(private fb: FormBuilder) {

    ...

        // Construct forms
        this.createForm();    
}

createForm() {
    this.editJobInfoForm = this.fb.group({
        ...
        JobType: this.jobTypes[this.currentJobData.JobType].DisplayDesc,
        ...
    });
}
5
John

Utilisez comparer avec la fonction telle quelle ...

Étape 1: mettre la balise [compareWith] telle qu'elle est affichée 

<mat-form-field>
  <mat-select placeholder="Pick item..." formControlName="selectedItem" 
    [compareWith]="compareFn">
    <mat-option *ngFor="let item of items">
        {{item.name}}
    </mat-option>
  </mat-select>
</mat-form-field>
<button (click)="changeValue()">Change value</button>

Stet 2: déclarer la variable compareFn et la fonction compareByValue comme indiqué ci-dessous, aucune modification requise

compareFn: ((f1: any, f2: any) => boolean) | null = this.compareByValue;

compareByValue(f1: any, f2: any) { 
  return f1 && f2 && f1.name === f2.name; 
}
0
thakkar sagar