Create a debounce click directive for buttons in a TypeScript file

I'm facing an issue with implementing debounce click on a dynamically added button using TypeScript. I need help with the correct syntax to make it work.

    private _initActionsFooter(): void {
        this.actionsFooterService.add([
            {
                label: 'AMBUSH.SHARED.FOOTER.HISTORY',
                click: () =>
                    this.dialogService.open(DialogHistoryAmbushComponent, {
                        context: {ambush: this.ambush}
                    }),
                outline: true,
                position: 'left',
                class: ['mr-3']
            },
            {
                label: 'AMBUSH.SHARED.FOOTER.DOCUMENTS',
                click: () => {
                    this.router.navigate([
                        'appostamenti',
                        this.route.snapshot.data.ambush.id,
                        'documenti'
                    ]);
                },
                outline: true,
                position: 'left',
                class: ['ml-3']
            },
            {
                label: 'AMBUSH.SHARED.FOOTER.REFRESH',
                click : () => this._save,
                disabled:
                    this.accessChecker.isGranted('view', 'only-view-atc') ||
                    this.ambushTabsStoreService.allFormsInvalid$,
                position: 'center',
                icon: 'save-outline',
            }
        ]);
        if (this.ambush?.fixedCabinOverId) {
            this.service
                .getDetail(this.ambush.fixedCabinOverId)
                .pipe(
                    catchError(() => {
                        return of(null);
                    })
                )
                .subscribe((res: Ambush) => {
                    this.cancellationReason = res.cancellationReason.value;
                });
        }
    }

These are the buttons, specifically interested in utilizing the function for the button labeled 'AMBUSH.SHARED.FOOTER.REFRESH'

This is my directive file which has been made accessible throughout the application

import {
  Directive,
  EventEmitter,
  HostListener,
  OnInit,
  Output
} from '@angular/core';
import { Subject } from 'rxjs';
import { debounceTime } from 'rxjs/operators';

@Directive({
  selector: '[appDebounceClick]'
})
export class DebounceClickDirective implements OnInit {
  @Output() debounceClick = new EventEmitter();
  private clicks = new Subject();

  constructor() {}

  ngOnInit() {
    this.clicks
      .pipe(debounceTime(500))
      .subscribe(e => this.debounceClick.emit(e));
  }

  @HostListener('click', ['$event'])
  clickEvent(event) {
    event.preventDefault();
    event.stopPropagation();
    this.clicks.next(event);
  }
}

Answer №1

Discovering the simplicity of debounce...:) and no need for rxjs in your directive

Simply put, when you interact or move around, reset the timeout

But if there's a pause, let the timeout run to execute your function...

1- Save the timeout in a variable

let timeoutId: ReturnType<typeof setTimeout>

2- Reset or leave the timeout

@HostListener('click', ['$event'])
clickEvent(e) {
  e.preventDefault();
  // Clear the one second timeout every click
  clearTimeout(timeoutId)
  timeoutId = setTimeout(() => {
    // do what you need to
  }, 1000)

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

Improving the utilization of services in Angular

I have a DatesService that handles date manipulation. Additionally, I have two services that require date manipulation - EventsService and CalendarService. The CalendarService utilizes the EventsService. My query is: what would be more efficient (in terms ...

Using a union type annotation when passing into knex will result in the return of an unspecified

Knex version: 2.5.1 Database + version: postgres15 When passing a union typescript definition into knex as a type annotation, it returns the type any. However, by using type assertion as UserRecord, we can obtain the correct UserRecord type. It is my un ...

Is there a way to receive a comprehensive report in case the deletion process encounters an error?

Currently, I am performing a delete operation with a filter based on 2 fields: const query = await Flow.deleteOne({ _id: flowId, permissions: currentUser!.id, }); After executing the delete operation, I inspect the query object to determine its su ...

What is the best way to receive a notification once the final observable has completed emitting its values?

In the past, we only made one call to the API reqFinanceDataWithFilters(req): Observable<any> { return this.http.post(env.baseUrl + req.url, req.filters) .pipe(map(this.extractResults)); } However, the response from this single request was a ...

Pinia is having trouble importing the named export 'computed' from a non-ECMAScript module. Only the default export is accessible in this case

Having trouble using Pinia in Nuxt 2.15.8 and Vue 2.7.10 with Typescript. I've tried numerous methods and installed various dependencies, but nothing seems to work. After exhausting all options, I even had to restart my main folders on GitHub. The dep ...

What is the process for transforming a multi-dimensional array containing strings into a multi-dimensional array containing numbers?

I've got a unique structure of data composed of arrays with strings as seen below: [ 0: Array(1) 0: Array(6) 0: [5.379856, 43.252967] 1: [5.422988, 43.249466] 2: [5.425048, 43.245153] 3: [5.383804, 43.239 ...

Adjustable image within a div based on the length of the title when viewed in Edge browser

I am facing an issue with a div element. Here is the code snippet: <div fxLayout="column" fxLayoutGap="20px"> <h1 class="mat-display-1">Welcome to $TITLE$</h1> <img *ngIf="logoData" [src]="logoData" class="logo" alt="logo"/> &l ...

Angular 2 Directive for Ensuring Required Conditions

Is there a way to make form fields required or not based on the value of other fields? The standard RequiredValidator directive doesn't seem to support this, so I've created my own directive: @Directive({ selector: '[myRequired][ngControl ...

The system encountered an error while trying to access the property 'enabled' of an undefined object

When working on a reactive form in my code, I need to ensure the values are properly set for the controls. ngDoCheck() { setControlValues(); } ngChanges(changes: SimpleChanges): void { setControlValues(); } private setControlValues() { try { ...

Effectively enhance constructor by incorporating decorators

Is it possible to properly extend a class constructor with decorators while maintaining the original class name and static attributes and methods? Upon reading the handbook, there is a note that cautions about this scenario: https://www.typescriptlang.or ...

Utilize Ionic Auth Connect to establish the currentSession and currentAuthenticatedUser on AWS Amplify

Problem with Amplify Configuration In the process of developing a new ionic app, our team decided to utilize AWS Amplify as our backend solution. To interact effectively with various services, we opted to use both "AMAZON_COGNITO_USER_POOLS" and "API_KEY" ...

Implementing a class addition on focus event using Angular 2

Currently, I am in the process of upgrading an Angular 1 application to Angular 2 and encountering an issue with one of my existing directives. The task at hand is straightforward. When an input field is focused, a class should be added (md-input-focus) a ...

Prisma causing a compiler error

Currently, I am in the process of developing a project that integrates a GraphQL server and utilizes Prisma to establish a connection with the database. Additionally, I have chosen to implement this project using TypeScript. Unfortunately, as I compile my ...

When using the router to send state, it returns as undefined

My scenario involves a component that utilizes the router to navigate to another component using a boolean variable in the URL: this.router.navigate(['/consume/course/' + this.id, {state: { isFirst }} ], { replaceUrl: true }); In the destination ...

Exploring Page Navigation Techniques in Angular 2

Exploring the world of Angular 2, I've come across a task to implement pagination. In my research, it led me to realize that the pagination logic must be coded in systems.config.js. My query now is locating the elusive file systems.config.js. What pur ...

Angular 2 partial static routing parameters with customizable features

Can an angular 2 routing configuration include a partial-static parameter? Currently, I am using a classic parameter setup like this: const routes: Routes = [ { path: ':type/fine.html', pathMatch: 'full', redirectTo: &ap ...

Adjust the size of a map on an HTML page after it has

Currently, I am utilizing Angular 2 to create a simple webpage that includes a Google 'my map' displayed within a modal. <iframe id="map" class="center" src="https://www.google.com/maps/d/u/0/embed?mid=1uReFxtB4ZhFSwVtD8vQ7L3qKpetdMElh&ll ...

Compiling an Angular project with an external library in AOT mode using angular-cli is causing issues and not compiling successfully

Embarking on a fresh new project, I utilized angular-cli 8.1.2 for the generation process. The goal is to establish a shared library that caters to multiple microservices (apps). This particular library should remain separate from the applications folder, ...

Discovering an entry that lacks a specific value within an array in the records

Currently, I am utilizing sequelize along with typescript in a node environment (with a postgresql database). Here is the model that I have defined: id: number, someField: string, arr1: number[], arr2: number[] My objective is to retrieve all records wher ...

A: TypeScript Error TS7006: Parameter implicitly has an 'any' type

TS7006: The parameter 'port' is implicitly assigned an 'any' type. constructor(port) { TS7006: The parameter 'message' is implicitly assigned an 'any' type. Emit(message) { I'm confused because all the other r ...