1

I'm trying to setup an attribute directive to handle click and double click on the same element. Not sure how to make the connection to the template, I have it declared and I put ClickTwiceDirective in the HTML tag. Also if there is a better way to do this I'm interested. I thought it would be better to avoid click and double click on the same element but that is the requirement and what needs to be designed for (single click select, double click editable).

    import {Directive, ElementRef, Output, EventEmitter, HostListener} from '@angular/core';

    @Directive({
        selector: '[clickTwice]'
    })
    export class ClickTwiceDirective {
    clickedElement: number = 0;

    constructor(private _elementRef : ElementRef) {
    }

    @Output()
    public singleClick = new EventEmitter();
    public doubleClick = new EventEmitter();

    @HostListener('this._elementRef:click', ['$event.target'])
    public onClick(targetElement: any) {
        console.log('got here');
        this.clickedElement++;
        setTimeout(() =>{
          if(this.clickedElement < 2){
            this.singleClick.emit(null);
            this.clickedElement = 0;
          } else {
            this.doubleClick.emit(null);
            this.clickedElement = 0;
          }
        }, 300);
    }
}

HTML input example of how I think it is supposed to look

<input type="text" (singleClick)='func1()' (doubleClick)="func2()" clickTwice/> 
Zack Lucky
  • 671
  • 3
  • 10
  • 25

2 Answers2

1

Is there a reason you can't just use (dblclick) and (click)? https://angular.io/docs/ts/latest/guide/user-input.html

Klaas Cuvelier
  • 291
  • 1
  • 8
  • click event blocks double click on the same element – Zack Lucky Dec 12 '16 at 16:48
  • Take a look at this post by TheLarkinn: https://github.com/angular/angular/issues/6675#issuecomment-214420954 He wrote some code to create a custom event manager which supports multiple events, he wrote some blogposts about it. But I think you could just plug in his service and then use ``, then in your `handleClick` method just check the type of your event (`click` or `dblclick`) – Klaas Cuvelier Dec 12 '16 at 17:35
  • I don't know if that would work unless he made the implementation specifically for click and double click. – Zack Lucky Dec 12 '16 at 17:40
  • That would be perfect thank you, I'll let you know how implementation goes – Zack Lucky Dec 12 '16 at 18:06
  • Implementation was successful, this is exactly what I was looking for, now I have a solid example of how to write an attribute directive with user input as well – Zack Lucky Dec 12 '16 at 21:22
1

This directive, based on your opening post + this thread how to differentiate single click event and double click event? should work. Here's a plunkr with the full working example https://plnkr.co/edit/8GlMhEriNcGuKShEzL9h?p=preview

@Directive({
    selector: '[detectclick]'
})
export class DetectClickDirective {
  clickCount: number = 0;
  clickTimeout: any = null;

  @Input('detectclick') public detectclick:any;
  @Output() public singleClick = new EventEmitter();
  @Output() public doubleClick = new EventEmitter();

  constructor(private _elementRef : ElementRef) {
  }

  @HostListener('click', ['$event.target'])
  public handleClick(targetElement: any) {
    this.clickCount++;

    // Reset on every click
    if (this.clickTimeout !== null) {
      clearTimeout(this.clickTimeout);
    }

    // Detect type of click in x mili seconds
    this.clickTimeout = setTimeout(detectClickType.bind(this), 300);

    function detectClickType () {
      if (this.clickCount >= 2){
        // detected a double click
        this.doubleClick.emit();
      } 
      else {
        // detected single click
        this.singleClick.emit();
      }

      // reset after each detect
      this.clickCount = 0;
    }
  }
}
Community
  • 1
  • 1
Klaas Cuvelier
  • 291
  • 1
  • 8