4

How can I prevent the click event from dispatching from a mousedown/mouseup event in the same element?

I already tried with both evt.preventDefault and evt.stopPropagation, but it doesn't seem to work. See example plunker here

<div>
  <h2 (click)="onClickToBePrevented()" mouseEvents>
    Click Here
  </h2>
</div>

Directive mouseevents:

@(host: {
    '(mousedown)': "preventClick($event)",
    '(mouseup)': "preventClick($event)"
})
preventClick(evt){
    evt.preventDefault();
    evt.stopPropagation();

    return false;
}
olivarra1
  • 3,269
  • 3
  • 23
  • 34
  • Read the answers here http://stackoverflow.com/questions/8643739/cancel-click-event-in-the-mouseup-event-handler , it will give you an idea of what's happening. – Eric Martinez Feb 29 '16 at 23:05

2 Answers2

1

Your directive effectively prevents click bubbling to parent elements, but not to the SAME element. Thus, you can use the same directive -or a trimmed version of it-, on a child component of the element that you want the click to be prevented.

Directive:

@Directive({
  selector: '[preventClick]',
  host: {
    '(click)': "preventClick($event)"
  }
})
class PreventClick {
  preventClick(evt){
    evt.stopPropagation();
    console.log('Click prevented!');
  }
}

Component:

@Component({
  selector: 'my-app',
  providers: [],
  template: `
    <div>
      <h2 (click)="onClick()">
        <span preventClick>Hello {{name}}</span>
      </h2>
      <div>{{clickResult}}</div>
    </div>
  `,
  directives: [PreventClick]
})
export class App {
  private preventResult:string;
  private clickResult:string;

  constructor() {
    this.name = 'Angular2'
    this.clickResult = "Try clicking the header"
  }

  onClick(){
    this.clickResult = "No, it doesn't work :(";
  }
}

See plunker: http://plnkr.co/edit/9Cpt6N?p=preview

Juangui Jordán
  • 6,091
  • 2
  • 35
  • 31
  • BTW I removed (mouseup) and (mousedown) host event bindings because they didn't trigger click, but they can be used, the only effect is that the directive will be called more than once. – Juangui Jordán Oct 24 '17 at 16:00
0

What do you want to do? If you want to show a message box for confirmation your solution works, cos after showing message box by mousedown, Click event not fired and you can fire it manually. You don't need to call any method to prevent it. Example plunker here

@Component({
  selector: 'app',
  template: ` 
 <div   (click)="onClick()" [confirm]="onClick"   
     confirmMessage="Are you ready!">click me!</div>
     `
})
export class AppComponent {
   onClick() {
   console.log('Everything you can do');
   }
}

///

@Directive({
selector: `[confirm]`
    host:{
    "(mousedown)":"confirmFirst()",
  }
})
export class ConfirmDirective {
  @Input('confirm') onConfirmed: Function = () => {};
  @Input() confirmMessage: string = 'Are you sure you want to do this?';

  confirmFirst() {
    const confirmed = window.confirm(this.confirmMessage);

    if(confirmed) {
      this.onConfirmed();
    }
  }
}
M_Farahmand
  • 954
  • 2
  • 9
  • 21