Creating mat-option elements with ngFor when list initialized empty

15,996

Solution 1

It is not that complex. Use below code(Make your adjustments accordingly).

    <form #f="ngForm">
  <select name="selectedCompetence" [(ngModel)]="selectedCompetence">
    <option *ngFor="let item of competences" [ngValue]="item">{{item.name}}</option>
  </select>

  <br />

  <select  name="selectedSpl" [(ngModel)]="selectedSpl">
    <option *ngFor="let item1 of selectedCompetence.specialisation_list" [value]="item1">{{item1}}</option>
  </select>

  <pre>{{f.value | json}}</pre>
</form>

Solution 2

In Angular 7 it is better to use a formGroup in the forms because you can add many validators at same time for each value. To use them

  1. You must define it at the typescript file. In this example, check the field isn´t empty. (Validators.required)
export class GeneratePnjComponent implements OnInit {

    formGroup: FormGroup;

    ngOnInit() {
      this.formGroup = new FormGroup({
      'name': new FormControl(null, [Validators.required]),
      'specialisation_1': new FormControl(null, [Validators.required]),
      });
    }
}
  1. Change your html code to use formgroup instead of ngModel and select the value with tag [value]
<form (ngSubmit)="doSomething()">
  [...]
  <mat-form-field>
    <mat-select name="competence_1_name" formControlName="name">
      <mat-option>-- Faites un choix --</mat-option>
      <mat-option *ngFor="let competence of competences"
                  [value]="competence.name">{{competence.name}}</mat-option>
    </mat-select>
    <mat-label>Compétence</mat-label>
  </mat-form-field>
  [...]
  <mat-form-field>
    <mat-select name="competence_1_spe_1" formControlName="specialisation_1">
      <mat-option>-- Faites un choix --</mat-option>
      <mat-option *ngFor="let specialisation of competence_1.specialisation_list"
                  [value]="specialisation">{{specialisation}}</mat-option>
    </mat-select>
    <mat-label>Spécialisation</mat-label>
  </mat-form-field>
  <br>
  [...]
</form>
  1. Copy the values of formGroup into your entity
export class GeneratePnjComponent implements OnInit {
    [...]

    doSomething() {
      this.competence_1.name = this.formGroup.get('name').value;
      this.competence_1.specialisation_1 = this.formGroup.get('specialisation_1').value;
    }
}

Solution 3

Possible duplicate of this

You need to use this syntax, [value]="competence.name" but I do not know if you can pipe | lowercase.

You might consider replacing [(ngModel)] with FormControls, FormGroups or FormBuilder. This will give you a lot more flexibility.

Share:
15,996
S. Miranda
Author by

S. Miranda

Live by the sword, write by the code

Updated on June 15, 2022

Comments

  • S. Miranda
    S. Miranda almost 2 years

    I would like to update values in the "specialisation" mat-select" when I select a skill in my "competence" mat-select. I linked my var with the model using [(ngModel)] but it won't update the list.

    I tried to use ngModel, with angular & material 7.

    HTML:

    <mat-form-field>
      <mat-select name="competence_1_name" [(ngModel)]="competence_1.name">
        <mat-option>-- Faites un choix --</mat-option>
        <mat-option *ngFor="let competence of competences" value="{{competence.name | lowercase}}">{{competence.name}}</mat-option>
      </mat-select>
      <mat-label>Compétence</mat-label>
    </mat-form-field>
    [...]
    <mat-form-field>
      <mat-select name="competence_1_spe_1" [(ngModel)]="competence_1.specialisation_1">
        <mat-option>-- Faites un choix --</mat-option>
        <mat-option *ngFor="let specialisation of competence_1.specialisation_list" value="{{specialisation | lowercase}}">{{specialisation}}</mat-option>
      </mat-select>
      <mat-label>Spécialisation</mat-label>
    </mat-form-field><br>
    

    main class:

    export class GeneratePnjComponent implements OnInit {
    
        competences: Array<Competence>;
        masteries: Array<string>;
        competence_1 = new Competence("");
        competence_2 = new Competence("");
        competence_3 = new Competence("");
        name: string;
        cost: number;
        time: number;
        ...
    }
    

    Class for a skill:

    export class Competence {
        name: string;
        mastery: string;
        specialisation_1: string;
        specialisation_2: string;
        specialisation_list: Array<string>;
    
        constructor(name: string) {
            this.name = name;
            this.specialisation_list = new Array<string>();
        }
    }
    

    Expected result: the list 'competence_1_spe_1' update when I choose a value on the list 'competence_1_name'

    Actual result: No value in the list 'competence_1_spe_1' even if I choose a value in the list 'competence_1_name'

  • S. Miranda
    S. Miranda almost 5 years
    I tried and can pipe with this syntax. However, the second part of the form still doesn't update after I choose the competence. The list for specialisations is still empty. I'll try to implement FormControls tomorrow and will keep you and igm1990 updated :)
  • Ben Hulan
    Ben Hulan almost 5 years
    Yes, igm1990's answer to use a FormGroup is more thorough than my link to FormControls but we are both saying roughly the same thing.
  • S. Miranda
    S. Miranda almost 5 years
    Yes ! I used the name of the competence instead of the full object, hence the problem.