Choosing numerous values ought to activate the service only once at a set time interval

I have a dropdown box with a select event (selectionChange) implemented as shown below:

<mat-select #segmentSelector [formControlName]="filter.VAL" multiple placeholder="Select" (selectionChange)="someMethod($event.value, filter.VAL)">
     <div class="custom-panel">
         <ng-container *ngFor="let option of getFilterDropdownOptions(filter.VAL)">
             <mat-option *ngIf="!!option"  [value]="option" [value]="option">
                 {{ option }}
             </mat-option>
         </ng-container>
     </div>
     <footer class="select-box-footer">
         <a class="select-box-footer-btn" (click)="$event.preventDefault();segmentSelector.close();">Done</a>
     </footer>
 </mat-select>

The selectionChange event works correctly when the value in the dropdown is changed:

someMethod(val: any, columnName: any) {
console.log(val);

    var obj = val as [];

    if (columnName === "CUST_ID") {
      this.aLogData.customerId = [];

      for (var i = 0; i < obj.length; i++) {
        console.log(obj[i]);

        this.aLogData.customerId.push(obj[i]);
      }
    }

    if (columnName === "CUST_NAME") {
      this.aLogData.customerName = [];

      for (var i = 0; i < obj.length; i++) {
        console.log(obj[i]);

        this.aLogData.customerName.push(obj[i]);
      }
    }

    var searchLocationInput = ((document.getElementById("searchLocationInput") as HTMLInputElement).value);
    console.log(this.aLogData);
    console.log(searchLocationInput);

    this.aLogData.searchItem = searchLocationInput;
    this.statusTwo = true;

    setTimeout(() => this.delaySomeMthod(this.aLogData), 10000); //Attempting to delay sending data once
  }

  delaySomeMthod(aLogData: LogData) {
    console.log("Called after 10 secs.");
    this.locationService.setLogData(aLogData).subscribe();
  } 

However, I am facing an issue where the controller is called every time the dropdown data changes. I tried adding a timer but it seems like I need to control sending requests to the controller at specific intervals.

My requirement is to allow selecting and changing values in the dropdown multiple times, but only calling the service or controller once after a certain period, for example, 10 seconds, as I am updating an array. Is this achievable?

Answer №1

Alright, let's delve into a potential solution:

  1. Begin by adding new variables at the class level:
  • intervalCallsService: (interval) initialized as null;
  • newSelectedData: Set, array, or object (depending on the type of value selected in dropdowns);
  1. Implement the callServiceAndHandleData method:
  • Start by calling the service with newSelectedData as a parameter,
  • Then clear the newSelectedData (or set it to null),
  • Finally, set intervalCallsService to null;
  1. Update the Dropdown changed method:
  • Add the received value to newSelectedData [refer to the note below: crucial];
  • Check if intervalCallsService is null: if so, initiate it (set it to an interval of 10 seconds that will call the callServiceAndHandleData method;

Here's how the scenario unfolds:

  1. Upon changing the dropdown value, the new value is appended to newSelectedData (currently the first and only element) and since it's the initial change, it triggers intervalCallsService (initiates an interval).

  2. The interval commences counting.

  3. If the dropdown is altered again, newSelectedData gains another element, but as intervalCallsService is not null, it won't be restarted.

  4. When the interval reaches its end, it executes the callServiceAndHandleData method, sending newSelectedData through the service, resetting intervalCallsService, and clearing newSelectedData.

  5. Thus, when the user switches the dropdown value once more, return to step 1.

Crucial: Only add a new value to newSelectedData if it isn't already present: for primitive values, a Set would be preferable over an array, while for non-primitive ones, an object may be the better choice. If your setup isn't entirely dynamic, consider using object keys corresponding to each dropdown to ensure each value is added just once as a value for the appropriate key.

Answer №2

If you want to add a delay before firing a method, consider creating a decorator that can handle this for you. By using a decorator, the method will wait until the specified time has passed before executing. It's a good practice to keep the decorator in a separate TypeScript file so you can easily reuse it across your application.

export function ngDebounce(timeout: number) {
  // Store timeout value to cancel the timeout
  let timeoutRef = null;

  return function(target, propertyKey: string, descriptor: PropertyDescriptor) {
    // Store original function for future use
    const original = descriptor.value;
    // Override original function
    descriptor.value = function(...args) {
      // Clear previous timeout
      clearTimeout(timeoutRef);
      // Schedule timer
      timeoutRef = setTimeout(() => {
        // Call original function
        original.apply(this, args);
      }, timeout);
    }
    // Return descriptor with new value
    return descriptor;
  }
}

Learn more about implementing debounce decorator

Usage:

@ngDebounce(10000)
delaySomeMthod(aLogData: LogData) {
  console.log("Called after 10 secs.");
  this.locationService.setLogData(aLogData).subscribe();
} 

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

Cross-site request forgery (CSRF) vulnerability spanning multiple applications

I am managing 2 separate applications under the same domain. One is hosted on a PHP 5.6 server with a Laravel 5.2 backend and an Angular2 frontend, while the other is on a PHP 5.3 server with a custom framework and a flat JavaScript frontend. Both applicat ...

Create an entity with a field that holds a value type based on the value of another key field

Essentially, I am looking to create a customized "Pair" data type For example: type Pair<T extends Record<string, string | number>, K extends keyof T> = { field: K, value: T[K] } So, if we have: type Rabbit = { name: string, a ...

Tips for integrating Ava with an Angular/CLI setup for your TypeScript project

Currently working on a project, I have set up an angular/cli typescript project. We are using the karma testing framework but considering switching to AVA. I have installed AVA with npm install --save-dev ava and checked out the typescript setup in the AV ...

Collaborate and reuse Typescript code across various Node projects

Imagine we have a project structured like this: webapps ProjectA SomeClass.ts Package.json ProjectB SomeClass.ts Package.json Common LoggingClass.ts Package.json The Common "LoggingClass" needs to import a module from NPM. Let's say that ...

Leveraging WebStorm's TypeScript support in conjunction with node_modules

Attempting to set up a TypeScript project in WebStorm to import a Node.js module has been a struggle. I made sure to download the necessary TypeScript definition in settings and specified --module commonjs in the compiler settings. However, I keep running ...

Determining the size of a custom-typed array in Typescript

Can anyone explain how to find the length of a custom typed array? For example: type TMyArray = IProduct[] interface IProduct { cost: number, name: string, weight: number } So, how can we determine the length in this case: const testArr: TMyArray ...

What is the best way to ensure synchronous function execution in Angular?

Consider the following scenario: ServiceA is accessed by two components with inputs. ComponentA contains a textArea while ComponentB has a toggle button. Whenever these components are changed, ServiceA.save() is triggered, which subsequently makes an HTTP ...

Looking for guidance on how to deploy a Node server with TypeScript on Vercel

I keep encountering a Code: NOT_FOUND error on my server while running the endpoint. The issue seems to be related to the configuration setup of my TypeScript-based Node server, and I've been struggling with it for quite some time now. Additionally, ...

Troubleshooting the creation of migration paths in NestJS with TypeORM

After diligently studying the NestJS and TypeORM documentation, I have reached a point where I need to start generating migrations. While the migration itself is creating the correct queries, it is not being generated in the desired location. Currently, m ...

Initiate a button press upon pressing the space bar

Currently, I am only able to use the click function on the button. However, I am also interested in incorporating the enter key and space bar for this action. Button (click)="ShuffleClick()" ...

What is the best way to include an Observable in this function?

Every time I send a set of credentials to my API and receive the data that needs to be stored, I encounter an error during the login process. Error: TypeError: You have provided an invalid object when a stream was expected. You can provide an Observable ...

Typescript hack: Transforming read-only arrays into tuple types with string literals

My configuration object looks like this: const config = { envs: ['dev', 'test', 'prod'], targets: ['> 2%'] }; Currently, the TypeScript compiler interprets the type of this object as: type IConfig = { envs: str ...

I am facing an issue in Angular2 where my component is unable to bind to the model and show the data in the HTML

This is the module I am working with: import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { BrowserModule } from ...

React-aria | Encountering a typescript error with input fields/textfields

Seeking assistance with using react-aria, specifically the useTextField feature. Despite following the documentation available at , I encountered an error related to the input element. Any help would be appreciated. Code import { AriaTextFieldOptions, use ...

Tips for enhancing a TypeScript interface for a React component in (Material-UI) by utilizing styled-components

I've been struggling to find a solution for this overload issue with no luck so far. My stack includes Typescript, Styled-components, and Material-UI. I am utilizing styled(MUIButton) to extend the default Button from MUI. While my props are being pas ...

Active Angular component utilizing *ngIf during the programmatically lazy loading of a Module

I find myself in a situation where I need to load numerous components on a specific route within my application. These components are controlled by a logic with *ngIf directives that allow me to show or hide them dynamically. For instance: <div *ngIf=& ...

Using an Angular HttpClient to authenticate with an API by utilizing a token for

I am currently attempting to fetch data from my Jenkins JSON API via HTTPClient. The data I need access to is restricted, so I must authenticate against Jenkins. To do this, I have generated an API Token. However, I am unsure of how to authenticate myself ...

Creating a TypeScript generic type for the "pick" function to define the types of values in the resulting object

I am facing an issue while writing the type for the pick function. Everything works smoothly when picking only one key or multiple keys with values of the same type. However, if I attempt to pick a few keys and their values are of different types, I encoun ...

Tips for creating an interface that dynamically expands according to a component's properties

Imagine having a custom Button component along with its corresponding ButtonProps interface. interface ButtonProps { component?: ComponentType; label: ReactNode; onClick?: (evt: React.MouseEvent<HTMLButtonElement>) => void; } Is there a wa ...

Best practices for implementing "Event Sourcing" in the NestJS CQRS recipe

I've been exploring the best practices for implementing "Event Sourcing" with the NestJS CQRS recipe (https://docs.nestjs.com/recipes/cqrs). After spending time delving into the features of NestJS, I have found it to be a fantastic framework overall. ...