Creating Mat-Option Elements with ngFor When List Initialized Empty

Creating Mat-Option Elements with ngFor When List Initialized Empty

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'

1

3 Answers

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>

1

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;
    }
}

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.

2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Maya Lin-Takahashi
Author

Maya Lin-Takahashi

Maya is a hardware enthusiast who tests and reviews smart home devices, smartphones, wearables, and audio gear. She focuses on practical consumer value and build quality.