aleks
aleks

Reputation: 41

How to use debounce on List of items in angular

How to use debounce time in an angular input search while searching through the list of items.Should i use RXJS and how to put it in my function filterReports? Can you please show me in code what i should do? Code here:

protected reports: Array<ReportGroupModel> = [];
protected filteredReports: Array<ReportGroupModel> = [];

constructor(
    protected route: ActivatedRoute,
    protected httpService: HttpService
) {
    super(route);

    this.titleIcon = 'fa-bar-chart';
    this.titleSufixKey = 'reports';

    this.filterReports = debounce(this.filterReports, 500);
}

filterReports(filter: any) {

    const searchText = filter.target.value?.toUpperCase();

    if (searchText) {

        let newFilteredReports: Array<ReportGroupModel> = [];

        for (let reportGroup of this.reports) {
            let foundItems = reportGroup.items.filter(x => x.title.toUpperCase().includes(searchText));

            if (foundItems && foundItems.length > 0) {
                newFilteredReports.push(new ReportGroupModel(reportGroup.header, foundItems));
            }
        }

        this.filteredReports = newFilteredReports;
    }
    else
        this.filteredReports = this.reports;
}

ngOnInit() {
    super.ngOnInit();

    this.filteredReports = this.reports;
}

and here is html

<div class="d-flex">
    <input search="text" class="form-control mw-200p ml-auto" (keyup)="component.filterReports($event)" autofocus placeholder="{{ 'search' | translate }}"/>
</div>
<div class="d-flex flex-wrap pl-2">
    <div *ngFor="let report of component?.filteredReports" class="pr-5 pt-2" style="width: 350px;">
        <h3>{{report.header | translate}}</h3>
        <ul class="list-unstyled pl-1">
            <li *ngFor="let item of report.items">
                <i class="fa {{item.icon}} mr-h"></i>
                <a class="link" [routerLink]="item.path"> {{item.title}} </a>
                <p *ngIf="item.description" class="text-muted">{{item.description}}</p>
            </li>
        </ul>
    </div>
</div>

Upvotes: 0

Views: 1180

Answers (1)

helloworld
helloworld

Reputation: 161

The easiest way to solve this issue is to use the reactive form module. however, if you want to stick with ngModel, you can do something like this.

searchChanged = new Subject();
protected reports: Array<ReportGroupModel> = [];
protected filteredReports: Array<ReportGroupModel> = [];

and update the subject every time the keyup event update

<div class="d-flex">
    <input search="text" class="form-control mw-200p ml-auto" (keyup)="onKeyUp($event)" autofocus placeholder="{{ 'search' | translate }}"/>
</div>
//.ts
onKeyUp(value: string) {
  this.searchChanged.next(value)
}

Now, you can use searchChanged subject to debounce the event update

constructor(
    protected route: ActivatedRoute,
    protected httpService: HttpService
) {
    ...
    this.searchChanged.pipe(
        debounceTime(300)
    // You better add takeUntil or something to unsubscribe this observable when this component destroy
    ).subscribe(value => {
       this.filterReports(value);
    })
}

Upvotes: 2

Related Questions