Angular - Implementing a debounce feature for event handling

Currently, I am utilizing the mouseenter and mouseleave events to control the opening and closing of my sidenav within the app. However, I have encountered issues because when hovering over the container quickly, these events are triggered multiple times, resulting in unexpected behavior with the sidenav. Is it possible to incorporate debounce into these events? If so, how can this be achieved?

Answer №1

To enhance your button, create a reference variable like this:

<button #btn>Click me</button>

Access the button in your component using @ViewChild:

@ViewChild('btn') btn: ElementRef;

Utilize fromEvent from rxjs to monitor the click action and apply the debounceTime operator:

ngAfterViewInit() {
    fromEvent(this.btn.nativeElement, 'click').pipe(
      debounceTime(2000) // 2 seconds
    ).subscribe(() => {
      // do whatever you need
    });
  }

Answer №2

RXJS offers a handy function called FromEvent to convert events into streams. You need to create two streams, one for when the mouse enters and another for when it leaves.

To ensure the correct sequence of true false or false true is emitted, consider using both debounceTime and distinctUntilChanged.

@ViewChild('sizeMenu')
  setSizeMenu(sizeMenu: ElementRef) {
    let mouseEnter$ = fromEvent(sizeMenu.nativeElement, 'mouseenter').pipe(
     mapTo(true));

     let mouseLeave$ = fromEvent(sizeMenu.nativeElement, 'mouseleave').pipe(
     mapTo(false));


     this.mouseEvents$ = mouseLeave$.pipe(merge(mouseEnter$), debounceTime(this.DebounceTime), distinctUntilChanged());
  };

Check out this example on stackblitz for reference.

Answer №3

If you want to implement a directive for debouncing events in Angular, you can create a custom directive like the one below. This example demonstrates how to debounce click events, but you can adapt it for any other type of event.

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

@Directive({
    selector: '[debounceClick]'
})

export class DebounceClickDirective implements OnInit, OnDestroy {

    @Input()
    public debounceClickTime = 500;

    @Output()
    public debounceClick = new EventEmitter();

    private clicks = new Subject();
    private subscription: Subscription;

    constructor() { }

    public ngOnInit() {
        this.subscription = this.clicks.pipe(debounceTime(this.debounceClickTime)).subscribe((e: Event) =>
            this.debounceClick.emit(e));
    }

    public ngOnDestroy() {
        this.subscription.unsubscribe();
    }

    @HostListener('click', ['$event'])
    public clickEvent(event: Event) {
        event.preventDefault();
        event.stopPropagation();

        this.clicks.next(event);
    }

}

To use this directive in your HTML template, follow the example below:

<input type="text" (debounceClick)="yourMethod()" debounceClickTime="1000" />

The debounceClickTime attribute is optional. If not specified, the default debounce time is set to 500ms.

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

Tips for getting Angular Ivy and Angular Universal up and running together

I'm encountering a problem while attempting to incorporate Ivy + Angular Universal into my project. This issue only arises when I enable Ivy mode in Angular (disabling it allows me to successfully build my application). Below are the steps to replic ...

Retrieve the object from the data received from the HTTP GET API call

I have a question that has been asked before, but I am unable to achieve the desired result with my current approach. When my service retrieves data from an API, it returns results in the following format: { "nhits": 581, "paramete ...

Is there a way to execute Angular code synchronously similar to how it is done in C#?

Trying to replicate a C# application in Angular is proving to be challenging for me, particularly when it comes to ensuring that the code runs synchronously. Consider the following example: private void doChecks() { if (isInvoiced()) return; ...

How to format decimals in Typescript/Angular with a pipe: comma or dot?

I've recently developed a custom pipe and I'm looking to enhance it by adding commas or periods to thousands values. For instance, 1000 should be displayed as either 1,000 or 1.000. Here is the code snippet for my custom pipe: import { Pipe, Pi ...

Customize Angular Material styles uniquely across various components

Within my application, I am utilizing two components that contain tab groups. The first component serves as the main page, where I have adjusted the CSS to enlarge the labels by using ViewEncapsulation.None. The second component is a dialog, and I aim to m ...

The Angular 13 application encounters a "moment is not a function" error after importing an Angular 13 package

Upgrading a private library named privLib to Angular 13 has been my recent task in order to facilitate the migration of all other projects. However, an issue arises when this library is imported into another project where one of the services utilizes momen ...

Encountering the error message "Uncaught Promise (SyntaxError): Unexpected end of JSON input"

Below is the code snippet I am using: const userIds: string[] = [ // Squall '226618912320520192', // Tofu '249855890381996032', // Alex '343201768668266496', // Jeremy '75468123623614066 ...

The validator is incorrectly diagnosing the input as 'invalid' when in reality it is not

Currently, I am working on creating a text field that must not be empty and should also not start with a specific set of characters (let's say 'test'). For example, I want testxyz or an empty field to be considered invalid, while anything e ...

Angular2 - Utilizing Promises within a conditional block

I'm currently facing an issue where I need to await a response from my server in order to determine if an email is already taken or not. However, I am struggling to achieve this synchronously. TypeScript is indicating that the function isCorrectEmail( ...

What could be causing the countdown timer to speed up unexpectedly?

Currently, I am developing a quiz application. At the moment, I need to implement the following features: Countdown timer Questions Question Choices The countdown timer for each question functions properly as long as the answer button is not clicked or ...

Reducing the amount of text displayed on ion-text to a minimum

HTML: <ion-list *ngFor="let message of messages"> <ion-item lines="none" type="button" button="true"> <ion-grid> <ion-row> <ion-col class="message"> <ion-text> ...

What is the best approach for declaring helper functions and constants within nest.js?

Currently, I am delving into the world of nest.js and building an API using it. However, I have hit a roadblock when it comes to defining constants and helper functions. Like many APIs, some of my endpoints require pagination, and I want to set a default ...

Embracing the power of Typescript with Node and Express?

While trying out the TypeScript Node Starter project from Microsoft, I found myself intrigued. Is it really possible to use TypeScript instead of Node on the server? There are a number of server-side tasks where TypeScript excels: - Building a web API ser ...

What is the reason the server is not receiving the cookie?

I am currently running a nodejs express application on a server with two endpoints: POST /session - used to send back the cookie GET /resource - used to check if the cookie is sent back, returning 401 not found if it's not On the frontend, hosted on ...

Merging Two Individual Applications into a Single Application Using Angular 8

Recently started learning Angular as a beginner. I am currently working on developing an application and opted to utilize the Angular Multikart ecommerce template. This template comes with separate front-end and admin-end sections, which I can currently ...

Tips for programmatically choosing dropdown menus in Angular 5

Trying to set up a dropdown select option in Angular 5 that dynamically changes based on the backend's input. Keep in mind that both select boxes are identical, only the options inside them vary. selector.html <html> ... <select> ...

Combining the output of several components across different services in Angular

In my current situation, I am dealing with two child components within the app component. Each of these child components relies on a different service for their results. I aim to execute these services in the onInit method of each respective component an ...

tslint is flagging an error related to cyclomatic complexity

Within my Angular 8 project, the following dependencies are utilized: "codelyzer": "^5.1.0", "ts-node": "~8.3.0", "tslint": "~5.19.0", Upon executing: ng lint myapp --fix=true An error is raised stating: ERROR: ...html:428:106 - The cyclomatic complex ...

Unexpected patterns observed when utilizing parent/child routing files

I am working with a Node/Express backend that is implemented using TypeScript. Whenever I make changes to a file and save it, if I test the root route in Postman localhost:8000/, I receive the expected response. However, when I test localhost:8000/user af ...

Retrieving selected values from a dynamic Primeng checkbox component

Within my Angular app, I am managing an array of questions. Each question includes a text field and an array of string options to choose from. The questions are retrieved dynamically from a service and can be updated over time. To allow users to select mul ...