Restricting HTTP requests to once every 200 milliseconds in Angular 4 with filtering in place

In my current project, I am working on a page that utilizes an ngFor to display an array of objects. One of the features I want to implement is the ability for users to filter these objects by entering specific keywords in an input field.

Since the data filtering needs to be done server side, I have set up a method in my service to handle this functionality:

public searchProperties(query: string): Observable<IProperty[]> {
    console.log('SERVICE: query: ' + query);
    let params = new HttpParams();

    params = params.append('q', query);

    return this.http.get<IProperty[]>(this.baseUrl+'/api/property', {params: params})
    .do( response => {
      console.log('Successfully retrieved the search response');
    }).catch((error: HttpErrorResponse) => {
      console.log('Something went wrong while retrieving the search response');
      return Observable.throw(error);
    })
  }

To use this method, I have created a custom pipe as shown below:

  transform(items: IProperty[], searchText: string): any[] {
    if(!items) return [];
    if(!searchText) return items;

    console.log('PIPE: Amount of items in items array BEFORE: ' + items.length);

    this.propertyService.searchProperties(searchText).subscribe(
      result => {
        items = result;
      }, error => {
        console.log('Failed to retrieve the properties that were searched for');
        return items;
      },
      () => {
        console.log('PIPE: Amount of items in items array AFTER: ' + items.length);
        return items;
      }
    )
  }

After creating the pipe, I implemented it in my HTML like this:

 <div class="col-md-4" *ngFor="let property of properties | property_filter : searchText ; let i=index">

However, I encountered two issues with my current implementation:

  1. When I type keywords in the input field, the HTTP call is made and returns a response to the pipe, but the ngFor remains empty until I clear the input field.

  2. The HTTP call should only be triggered every 200 milliseconds instead of with every change event.

Any help or guidance would be greatly appreciated!

UPDATE:

As a temporary solution, I have removed the pipe and moved the call to the component, which successfully updates the list of objects.

One question still remains: How can I limit the responses to one every 200 milliseconds?

Answer №1

To trigger an event after a certain delay following a change, you can utilize the debounceTime function from RxJs. Here's how you can implement it:

<input type="text" [ngModel]="term" (ngModelChange)="change($event)"/>

import { Subject } from 'rxjs/Subject';
import { Component }   from '@angular/core';
import 'rxjs/add/operator/debounceTime';

export class AppComponent {
    term: string;
    modelChanged: Subject<string> = new Subject<string>();

    constructor() {
        this.modelChanged
       .debounceTime(300)
       .distinctUntilChanged()
       .subscribe(model => this.model = model);
    }

    change(text: string) {
        this.modelChanged.next(text);
       // code for filtering goes here 
    }
}

____

Below is the code snippet I've used to filter incoming email addresses from the server and it's functioning properly:

Pipe.ts

import { Pipe, PipeTransform } from '@angular/core';
import { ReportService } from './ReportService';
import { Observable } from 'rxjs/Observable';

@Pipe({
  name: 'filter'
})

export class MyFilter implements PipeTransform {
  emails: Array<string>= new Array<string>();
  constructor(private reportservice :ReportService) {}

    transform(items: any[], term: string): any {
      debugger;
      if (!term) 
        return items;
       this.reportservice.GetAllEmails().subscribe(e=> this.emails = e);
       return this.emails.filter(item => item.indexOf(term) > -1);
    }
}

App.Component.Html

<form id="filter">
  <label>Searching for email</label>
  <input type="text" name="termtext" [(ngModel)]="term" />
</form>

<ul *ngFor="let email of emails| filter:term">
    {{email}}
</ul>

App.component.ts

term:string;
emails: Array<string> = new Array<string>();
constructor()
{
this.term="test";
}

Initially, there might be a delay as data is fetched from the server, but subsequent searches work smoothly.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Node.js: The choice between returning the original Promise or creating a new Promise instance

Currently, I am in the process of refactoring a codebase that heavily relies on Promises. One approach I am considering is replacing the new Promise declaration with simply returning the initial Promise instead. However, I want to ensure that I am correctl ...

How can the map function be executed sequentially every second, using async functions, fetch API, and promises, without running in parallel?

I am facing an issue with my map function, as it needs to fetch data from an online API that only allows one request per second. I attempted to solve this problem by implementing the following code: const sleep = (ms: number) => { return new Promise(( ...

By default, all groups in the Kendo UI Angular 2 Grid are collapsed

Just started using the new Kendo UI for Angular 2 Grid and I have a question - is it possible to collapse all groups by default when grouping data? I noticed there is a method called collapseGroup(), but it's unclear how to use it or if there's ...

Angular patch value not functioning properly after initial use

Whenever I click on the edit icon, I want the form field to populate. It works correctly the first time, but subsequent clicks on different icons do not update it. However, if I hit the cancel button and then click on any edit button again, it works fine. ...

Can we replace node_module imports with a different module (e.g. swapping lodash with lodash-es)?

Currently in the process of upgrading from angular 9 to angular 10 within my mono-repo. Encountering numerous warnings like the ones below: WARNING in \libs\global-search\src\lib\components\status\status.component.ts depe ...

Troubleshooting: HTTP client post request working with body.set but not with formData.append for sending data to API

I am in the process of updating the UX for an older application with APIs developed in ASP.NET When I make a POST request as shown below, everything works perfectly. The data is received: var APIURL = sessionStorage.getItem('endpoint') + "/ ...

Issues with exporting function and interface have been identified

When exporting a function and type from the library in the convertToUpper.ts file, I have the following code: export function Sample() { console.log('sample') } export type IProp = { name: string age: number } The index.ts file in my lib ...

Handling errors in nested asynchronous functions in an express.js environment

I am currently developing a microservice that sends messages to users for phone number verification. My focus is on the part of the microservice where sending a message with the correct verification code will trigger the addition of the user's phone n ...

Guide on dividing a URL string in Angular framework

Is there a way to include a value directly in the URL, like so: http://example.com/component/july2021 I need to extract july2021 from the component and separate it into "july" and "2021". How can I achieve this? ...

The Angular Reactive Forms error message indicates that attempting to assign a 'string' type to an 'AbstractControl' parameter is invalid

While attempting to add a string value to a formArray using material forms, I encountered the following error message: 'Argument of type 'string' is not assignable to parameter of type 'AbstractControl'.' If I try adding a ...

React-snap causing trouble with Firebase

I'm having trouble loading items from firebase on my homepage and I keep running into an error. Does anyone have any advice on how to fix this? I've been following the instructions on https://github.com/stereobooster/react-snap and here is how ...

Verify whether a component is a React.ReactElement<any> instance within a child mapping operation

I am facing a challenge with a component that loops through children and wraps them in a div. I want to exclude certain elements from this process, but I am struggling to determine if the child is a ReactElement or not (React.ReactChild can be a string or ...

Definition for TypeScript for an individual JavaScript document

I am currently attempting to integrate an Ionic2 app within a Movilizer HTML5 view. To facilitate communication between the Movilizer container client and the Ionic2 app, it is crucial to incorporate a plugins/Movilizer.js file. The functionality of this f ...

The type 'RefObject<HTMLDivElement>' cannot be matched with type 'RefObject<HTMLInputElement>' in this context

Encountered an error message: Issue with assigning types: Type '{ placeholder: string | undefined; autoComplete: string | undefined; "data-testid": string | undefined; onChange?: ChangeEventHandler<HTMLInputElement | HTMLTextAreaElement&g ...

Creating consistent div sizes for varying image and title lengths in bootstrap

In my angular project, I am receiving data in the form of image, title, and location. Despite my efforts to create a responsive div, I have been unsuccessful in achieving uniform sizes. <div *ngFor="let company of companies" class=" ...

ng2 inherits from component and expands upon the parent template

I have a component that inherits from a base component. Now, I would like to expand on the template of the base component within the derived component. For example: Template in base component: <div> <button>1</button> </div> ...

Pass on only the necessary attributes to the component

I have a simple component that I want to include most, if not all, of the default HTML element props. My idea was to possibly extend React.HTMLAttributes<HTMLElement> and then spread them in the component's attributes. However, the props' ...

Dockerized Angular CLI app experiencing issues with hot reload functionality

My existing angular cli application has been dockerized with the following setup: Dockerfile at root level: # Create a new image from the base nodejs 7 image. FROM node:7 # Create the target directory in the imahge RUN mkdir -p /usr/src/app # Set the cr ...

A guide on incorporating jQuery alert messages into Angular 2

Whenever I submit a form by clicking on the "send message" button, I want to display an Alert message using jQuery. However, currently, I have to double click for the alert message to appear. How can I make it so that the alert message is shown with just o ...

"Effortlessly sending emails using the power of Angular 7 and SpringBoot

One of the challenges I'm facing is sending emails with SpringBoot using hardcoded data successfully. However, I am encountering an error 500 when attempting to retrieve data from my Angular form and call the API with that data. Can someone pinpoint ...