Search code examples
angularmouseeventstoppropagationlong-press

prevent click event on long press


I have the following angular2 template:

<div (click)="foo()">
   <img (longPress)="bar(1)" (click)="foobar(1)" />
   <img (longPress)="bar(2)" (click)="foobar(2)"/>
</div>

Longpress is a custom attribute directive that triggers when you have a mousedown for 500 ms.

Click events on the <div> and <img> are handled fine. When I do a longpress on an image, the bar() function is called. However, on mouseUp (after a longpress) the click events are triggered on the <img> and the parent <div>.

How can I prevent these click events in the simplest way.

Only thing I can think of now is to write a custom attribute directive that only triggers on "clicks" that take less than 500 ms. This just seems a bit over the top to me.


Solution

  • I ended up creating a "longPress" and a "shortPress" directive. The longpress only fires after a set amount of time and the shortpres only fires below that same threshold.

    import { Directive, HostListener, Output, EventEmitter } from '@angular/core';
    
    @Directive({ selector: '[shortPress]' })
    
    export class ShortPressDirective {
    
        @Output()
        shortPress = new EventEmitter();
    
        private _timeout: any;
        private _isShort: boolean;
    
        @HostListener('mousedown') onMouseDown( e ) {
            this._isShort = true;
            this._timeout = setTimeout(() => {
                this._isShort = false;
            }, 500);
        }
    
        @HostListener('mouseup') onMouseUp( e ) {
            if (this._isShort) {
                this.shortPress.emit( e );
            }
            clearTimeout(this._timeout);
        }
    
        @HostListener('mouseleave') onMouseLeave() {
            clearTimeout(this._timeout);
        }
    }
    

    and

    import { Directive, HostListener, Output, EventEmitter } from '@angular/core';
    
    @Directive({ selector: '[longPress]' })
    
    export class LongPressDirective {
    
        @Output()
        longPress = new EventEmitter();
    
        private _timeout: any;
    
        @HostListener('mousedown') onMouseDown( e ) {
            this._timeout = setTimeout(() => {
                this.longPress.emit( e );
            }, 500);
        }
    
        @HostListener('mouseup') onMouseUp() {
            clearTimeout(this._timeout);
        }
    
        @HostListener('mouseleave') onMouseLeave() {
            clearTimeout(this._timeout);
        }
    }