Estoy usando *ngFor para mostrar una colección, también tengo una input que se usará como criterio de filtro (esta input es un formControl ). Ahora he agregado un PipeTransform para filtrar mi colección en función de esa input . Todo funciona como se esperaba, pero no puedo averiguar cómo eliminar el rebote. Quiero que mi filterPipe se llame 0.5 segundos después de la última pulsación de tecla dentro de input , pero en este momento se llama instantáneamente después de cualquier cambio dentro de mi input .
HTML:
<div class="test-ctr"> <div class="form-ctr"> <form class="example-form" [formGroup]="filterForm">> <input formControlName="nick" placeholder="ex. hdw"> </form> </div> <div class="app-cards-ctr"> <div class="app-card-ctr" *ngFor="let nick of nicks | filterPipe: filterForm.get('nick')?.value"> <app-card [nick]="nick"></app-card> </div> </div> </div>Componente.ts:
import { Component, OnInit } from '@angular/core'; import { FormBuilder } from '@angular/forms'; @Component({ selector: 'app-test', templateUrl: './test.component.html', styleUrls: ['./test.component.scss'], }) export class TestComponent implements OnInit { nicks: string[] = ['Siema', 'Elo', 'Tu', 'Hdw3DCtV', 'and', 'Gównow', 'Zdzisiu11', 'Zdzisiu1','Zdzisiu2','Zdzisiu3','Zdzisiu4','Zdzisiu5']; constructor(private formBuilder: FormBuilder) {} filterForm = this.formBuilder.group({ nick: [''] }) ngOnInit(): void {} }Pipe.ts:
import { Pipe, PipeTransform } from '@angular/core'; @Pipe({ name: 'filterPipe', pure: true }) export class FilterPipe implements PipeTransform { transform(value: string[], arg: string): string[] { console.log(arg); return value.filter( (e) => e.toLowerCase().indexOf(arg.toLowerCase()) !== -1 ); } }Para mí, el mejor enfoque es usar la tubería dentro del componente y no en la plantilla.
constructor( private filterPipe: FilterPipe ) {} ngOnInit() { this.filterForm.controls.nick.valueChanges.pipe( startWith(''), debounceTime(500), map(value => { this.nicks.forEach(nick => { nick = this.filterPipe.transform(value, nick); // or what you want to do }); }) ); }Ejemplo de trabajo en Stackblitz
<h3>Filter:</h3> <form [formGroup]="filterForm"> <input type="text" formControlName="nick" /> </form> <h3>Nicks:</h3> <div *ngFor="let nick of nicks | filterPipe: (debouncedControl$ | async)"> {{ nick }} </div> @Component({ selector: 'my-app', templateUrl: './app.component.html', styleUrls: ['./app.component.css'], }) export class AppComponent { nicks: string[] = [ 'Siema', 'Elo', 'Tu', 'Hdw3DCtV', 'and', 'Gównow', 'Zdzisiu11', 'Zdzisiu1', 'Zdzisiu2', 'Zdzisiu3', 'Zdzisiu4', 'Zdzisiu5', ]; constructor(private formBuilder: FormBuilder) {} filterForm = this.formBuilder.group({ nick: [''], }); debouncedControl$ = this.filterForm.controls.nick.valueChanges.pipe( startWith(''), debounceTime(500) ); } @Pipe({ name: 'filterPipe', }) export class FilterPipe implements PipeTransform { transform(values: string[], inputValue: string): string[] { return values.filter((v) => { return ( v.toLowerCase().indexOf((inputValue || '').toLocaleLowerCase()) > -1 ); }); } }Dicho todo esto, probablemente este no sea un escenario en el que buscaría una tubería angular.
@Component({ selector: 'alternate', template: ` <form [formGroup]="filterForm"> <input type="text" formControlName="nick" /> </form> <ul> <li *ngFor="let nick of filteredNicks$ | async"> {{nick}} </li> </ul> `, }) export class AlternateSolutionComponent { constructor(private formBuilder: FormBuilder) {} nicks = ['Siema', 'Elo', 'Tu']; lowercaseIncludes(a: string, b: string): boolean { return a.toLocaleLowerCase().indexOf(b.toLocaleLowerCase()) > -1; } filterForm = this.formBuilder.group({ nick: [''] }); filteredNicks$ = this.filterForm.controls.nick.valueChanges.pipe( startWith(''), debounceTime(500), map((inputValue) => { return this.nicks.filter((nick) => this.lowercaseIncludes(nick, inputValue) ); }) ); }