0

I have a form with 4 select inputs. When one value is selected it should not be shown in other select inputs. I have created a working solution. But when an option is selected it is not shown in the select text, it stays empty. it occurs when a *ngFor directive is used along with an *ngIf directive. As alternative solution I removed the if directive and added a [hidden] with a function that does the same check.

Code that is working properly:


<div>
    <mat-form-field class="full-width">
      <mat-label>Player 1</mat-label>
      <mat-select [(ngModel)]="selectedPlayers[1]">
            <mat-option [value]="player" [hidden]="isSelected(player)" *ngFor="let player of players">
              {{ player.name }}
            </mat-option>
      </mat-select>
    </mat-form-field>
  <div>
    <mat-form-field class="full-width">
      <mat-label>Player 2</mat-label>
      <mat-select [(ngModel)]="selectedPlayers[2]">
          <mat-option [value]="player" [hidden]="isSelected(player)" *ngFor="let player of players">
            {{ player.name }}
          </mat-option>
      </mat-select>
    </mat-form-field>
  </div>
  <div>
    <mat-form-field class="full-width">
      <mat-label>Player 3</mat-label>
      <mat-select [(ngModel)]="selectedPlayers[3]" >
          <mat-option [value]="player" [hidden]="isSelected(player)" *ngFor="let player of players">
            {{ player.name }}
          </mat-option>
      </mat-select>
    </mat-form-field>
  </div>
  <div>
    <mat-form-field class="full-width">
      <mat-label>Player 4</mat-label>
      <mat-select [(ngModel)]="selectedPlayers[4]" >
          <mat-option [value]="player" [hidden]="isSelected(player)" *ngFor="let player of players">
            {{ player.name }}
          </mat-option>
      </mat-select>
    </mat-form-field>
  </div>
  
  <div mat-dialog-actions>
    <button mat-raised-button mat-dialog-close>No Thanks</button>
    <button mat-raised-button mat-dialog-close>Start</button>
  </div>

Code that works, but doesn't show the selected option text in the select (same structure as above, but only select part as example):

<mat-select [(ngModel)]="selectedPlayers[3]">
   <ng-container *ngFor="let player of players">
      <mat-option [value]="player" *ngIf="!selectedPlayers.includes(player)">
            {{ player.name }}
      </mat-option>
   </ng-container>
</mat-select>

I want to know why the combination of the ngFor and ngIf is preventing the select text being set when an option is selected?

Ps. I'm new to Angular and could not find a clear answer behind this process.

Edit:

Below is the used .ts file:

import { Component } from '@angular/core';

export interface Player {
  name: string;
}

@Component({
  selector: 'app-new-game-dialog',
  templateUrl: './new-game-dialog.component.html',
  styleUrls: ['./new-game-dialog.component.css'],
})
export class NewGameDialogComponent {
  players: Player[] = [
    { name: 'Brian'},
    { name: 'Clement'},
    { name: 'Jordy'},
    { name: 'Mitchel'},
    { name: 'Nicky'},
  ];
  selectedPlayers: Player[] = [];

  isSelected(player: Player) {
    return this.selectedPlayers.includes(player)
  }

  
}

Visual example:

hidden with function show select text

Here you can see a dialog that has four select inputs. On the first one "brian" is selected. In the third select brian is not available anymore. This is working correctly. But if I use the second snippet with the *ngIf directive instead of the [hidden] function, the text 'brian' is not visible in the select input.

below is a screenshot where I selected brian in the first select. It is not available in the third select, but the text 'brian' itself is not visible in the first select

ngIf used not showing select text

brian
  • 3
  • 3
  • can you also share the isSelected(player) method? – Nathan T. May 12 '23 at 11:37
  • Hi @brian! I have some suspicions about the reason for this, but could you please post a bit more code illustrating your problem? I'm particularly interested in how the model (`selectedPlayers` array) is set up in the `.ts` file, and how exactly do you render your expected output in `.html`. And also - could you explain a bit more clearly what is the expected outcome here, and what is the actual outcome you're getting? I've read your question 3 times, but I'm still not entirely sure what you wanted to accomplish : ) – JoannaFalkowska May 12 '23 at 11:37
  • I've edited my question, hope it's clear now, let me know if additional information is needed :) trying to understand the process behind this and why it's not working with the *ngIf directive. – brian May 12 '23 at 12:51

1 Answers1

1

It comes down to the difference between what *ngIf and hidden do. When *ngIf is false, it actually removes the element from the DOM. hidden just makes it invisible in the UI. What is the difference between *ngIf and [hidden]?

mat-select looks for a mat-option element with a value equal to its [(ngModel)] value. *ngIf is removing that option, so there will never be an option that matches.

jbsiefken
  • 26
  • 2
  • That makes sense, if mat-select looks for the mat-option and it is not in the DOM it has nothing to show as text! – brian May 12 '23 at 13:29