No person shown after selecting ALL genders from a dropdown

The minimal code to produce the issue can be seen at here.

Objective: Showing a list of persons based on the selected gender. If All is selected then all persons are shown.

Issue:

  • When the page is first loaded, All is selected by default. All persons are shown. It works as expected.

  • Selecting male shows a list of male persons. It works as expected.

  • But if I reselect All, no person is shown. It is the unexpected result.

enter image description here

Code Snippet:

<div>
  <select [(ngModel)]="selectedFilter">
    <option [value]="undefined">All</option>
    <option *ngFor="let gender of ['male','female']" [value]="gender">
      {{gender}}
    </option>
  </select>
  <ul>
    <li *ngFor="let person of peopleByGender">
      {{person.name}}
    </li>
  </ul>
</div>
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html'
})
export class AppComponent {
  selectedFilter?: "male" | "female";

  people: { name: string; gender: "male" | "female"; }[] = [
    { name: "Anton", gender: "male" },
    { name: "Bob", gender: "male" },
    { name: "Cindy", gender: "female" }
  ];


  get peopleByGender(): readonly { name: string; gender: "male" | "female"; }[] {
    return this.people
      .filter(x => this.selectedFilter == undefined || x.gender == this.selectedFilter);
  }

}

Question

What causes this issue? And how to solve it?

Note: Using type or interface are intentionally ignored to focus on the main issue.

Logging

get peopleByGender(): readonly { name: string; gender: "male" | "female"; }[] 
{
  console.log(

  `Selected Filter: ${this.selectedFilter}. 
   Is it undefined? ${this.selectedFilter == undefined}`

  );

 // ... others
}

enter image description here

>Solution :

<option> values must be convertible to strings, because behind the scenes they’re getting represented as HTML DOM.

DOM Representation

So when a user selects the "All" option, they’re not changing the value to undefined: they’re changing it to "undefined".

Instead of trying to use undefined, use a special string value. For example, you could use "All", or you could just use an empty string:

  <option value="">All</option>
export class AppComponent {
  selectedFilter: "male" | "female" | "" = "";

  people: { name: string; gender: "male" | "female"; }[] = [
    { name: "Anton", gender: "male" },
    { name: "Bob", gender: "male" },
    { name: "Cindy", gender: "female" }
  ];


  get peopleByGender(): readonly { name: string; gender: "male" | "female" | ""; }[] {
    return this.people
      .filter(x => this.selectedFilter === "" || x.gender == this.selectedFilter);
  }

Leave a Reply