Search code examples
angularangular-changedetection

filter not trigger the change event from text input


I would like to understand, why the change deduction is not works, on keyup while integrate the filter using the input value.

when the key ups, I am getting no of empty string popups to prevent the filter.

here is the code:

import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import 'zone.js';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule],
  template: `
    <p>register works!</p>
  <input aria-label="filter text" (keyup)="filterIt($event)" type="text" />
  <div *ngFor="let student of filterStudent(); trackBy:identify">{{student}}</div>
  `,
})
export class App {
  students = ['Yamini', 'Surat', 'Arif', 'Madura'];

  filterStudent(str = '') {
    console.log(str)
    const filtered = this.students.filter((student) =>
      student.toLocaleLowerCase().includes(str.toLocaleLowerCase())
    );
    return filtered;
  }

  filterIt($event: Event) {
    const event = $event.target as HTMLInputElement;
    this.filterStudent(event.value);
  }

  identify(_index: number, name: string) {
    return name;
  }
}

bootstrapApplication(App);

Live Example


Solution

  • You're always calling filterStudent() from template that always returns the same value.

    Avoid calling methods withing template.

    As an option you can create a property filteredStudents and update it on keyUp event:

    ts

    filteredStudents = this.students;
    ...
    filterIt($event: Event) {
      const event = $event.target as HTMLInputElement;
      this.filteredStudents = this.filterStudent(event.value);
    }
    

    html

    *ngFor="let student of filteredStudents; trackBy:identify">
    

    Forked Stackblitz


    Another option might be using Observable

    html

    *ngFor="let student of filteredStudents$ | async..."
    

    ts

    query$ = new BehaviorSubject('');
    
    filteredStudents$ = this.query$.pipe(
      map(query => this.filterStudent(query))
    );
    
    filterIt($event: Event) {
      const event = $event.target as HTMLInputElement;
      this.query$.next(event.value);
    }
    

    Forked Stackblitz