369

What is the easiest way to stop mouse events propagation in Angular ?

Should I pass special $event object and call stopPropagation() myself or there is some other way.

For example in Meteor, I can simply return false from event handler.

15 Answers 15

368

If you want to be able to add this to any elements without having to copy/paste the same code over and over again, you can make a directive to do this. It is as simple as below:

import {Directive, HostListener} from "@angular/core";
    
@Directive({
    selector: "[click-stop-propagation]"
})
export class ClickStopPropagation
{
    @HostListener("click", ["$event"])
    public onClick(event: any): void
    {
        event.stopPropagation();
    }
}

Then just add it to the element you want it on:

<div click-stop-propagation>Stop Propagation</div>
Sign up to request clarification or add additional context in comments.

10 Comments

It does not work for me. The click event is not stopped :(
doesn't work for me, if i have the other click ... <button click-stop-propagation (click)="test($event)">test</button>
You may need to listen for a different mouse event (ie. mousedown, mouseup).
@yohosuff makes a good point. Add this method to the directive: @HostListener("mousedown", ["$event"]) public onMousedown(event: any): void { event.stopPropagation(); }
If this not works for you, try this: event.preventDefault();
|
309

The simplest is to call stop propagation on an event handler. $event works the same in Angular 2, and contains the ongoing event (by it a mouse click, mouse event, etc.):

(click)="onEvent($event)"

on the event handler, we can there stop the propagation:

onEvent(event) {
   event.stopPropagation();
}

6 Comments

In my custom directive, it doesn't work. <button confirmMessage="are you sure?" (click)="delete()">Delete</button>, and in my directive: (click)="confirmAction($event), then confirmAction(event) { event.stopPropagation(); };
Try returning false as well
seems that by the time you handle event in the handler function stopPropogation() isn't available. I had to do it right in the markup: `(click)="foo(); $event.stopPropogation()"
This does not work, at least not when placed in anchor element. Answer is wrong.
@inorganik tnx, calling it from the template worked for me.
|
212

Calling stopPropagation on the event prevents propagation: 

(event)="doSomething($event); $event.stopPropagation()"

For preventDefault just return false

(event)="doSomething($event); false"

Event binding allows to execute multiple statements and expressions to be executed sequentially (separated by ; like in *.ts files.
The result of last expression will cause preventDefault to be called if falsy. So be cautious what the expression returns (even when there is only one)

11 Comments

They are talking about preventing default action, not stepping event through parent elements what is stopPropagation is about.
return false <3
@ShadowWizard That does not necessarily mean the answer is wrong. The error could also be on your side, or that the answer could have been correct for some time and then something has changed.
@ShadowWizard there are newer answers even with more upvotes. Either try these or create a new question with full information about your use case (stackblitz reproduction, ....) instead of accusing hundred random people of upvoting for no reason.
With strict template checking you'll need to do something like (selectionChange)="selectionChange($event); $any($event).stopPropagation()", or move it to your handler.
|
56

Adding to the answer from @AndroidUniversity. In a single line you can write it like so:

<component (click)="$event.stopPropagation()"></component>

3 Comments

It shouldn't change so much from version to version since they try to keep the html templating standard :)
Works perfectly with angular 5 as well.
Just what i was looking for
16

This worked for me:

mycomponent.component.ts:

action(event): void {
  event.stopPropagation();
}

mycomponent.component.html:

<button mat-icon-button (click)="action($event);false">Click me !<button/>

2 Comments

This solution worked for me in angular 5.. Thank you.
Still works, definintely the easiest solution. Thank you sir.
14

I had to stopPropagation and preventDefault in order to prevent a button expanding an accordion item that it sat above.

So...

@Component({
  template: `
    <button (click)="doSomething($event); false">Test</button>
  `
})
export class MyComponent {
  doSomething(e) {
    e.stopPropagation();
    // do other stuff...
  }
}

Comments

11

If you're in a method bound to an event, simply return false:

@Component({
  (...)
  template: `
    <a href="/test.html" (click)="doSomething()">Test</a>
  `
})
export class MyComp {
  doSomething() {
    (...)
    return false;
  }
}

5 Comments

It does work for click events. At least in the latest version of Angular2.
Returning false calls preventDefault not stopPropagation.
Calling return false does stop propagation in the DOM. Check your facts @GünterZöchbauer It's mentioned in the ng-book.
@moeabdol a link could at least demonstrate what you claim, but actually preventDefault is called. github.com/angular/angular/blob/…, github.com/angular/angular/blob/…
Correct! @GünterZöchbauer Thank you for clarifying this. I wish I could share a link. I followed Nate Murray's advice in his book "ng-book The Complete Book on Angular 4" of returning false; at the end of a function to stop event propagation in the DOM. He describes it exactly the way you mentioned. Sorry for the misunderstanding.
3

Nothing worked for IE (Internet Explorer). My testers were able to break my modal by clicking off the popup window on buttons behind it. So, I listened for a click on my modal screen div and forced refocus on a popup button.

<div class="modal-backscreen" (click)="modalOutsideClick($event)">
</div>


modalOutsideClick(event: any) {
   event.preventDefault()
   // handle IE click-through modal bug
   event.stopPropagation()
   setTimeout(() => {
      this.renderer.invokeElementMethod(this.myModal.nativeElement, 'focus')
   }, 100)
} 

Comments

3

I just checked in an Angular 6 application, the event.stopPropagation() works on an event handler without even passing $event

(click)="doSomething()"  // does not require to pass $event


doSomething(){
   // write any code here

   event.stopPropagation();
}

2 Comments

This is because you're accessing window.event. Technically this is deprecated developer.mozilla.org/en-US/docs/Web/API/Window/event. It should work, but could in future trip you up.
in strict mode this does not work
3

I used

<... (click)="..;..; ..someOtherFunctions(mybesomevalue); $event.stopPropagation();" ...>...

in short just seperate other things/function calls with ';' and add $event.stopPropagation()

Comments

2

Disable href link with JavaScript

<a href="#" onclick="return yes_js_login();">link</a>

yes_js_login = function() {
     // Your code here
     return false;
}

How it should also work in TypeScript with Angular (My Version: 4.1.2)

Template
<a class="list-group-item list-group-item-action" (click)="employeesService.selectEmployeeFromList($event); false" [routerLinkActive]="['active']" [routerLink]="['/employees', 1]">
    RouterLink
</a>
TypeScript
public selectEmployeeFromList(e) {

    e.stopPropagation();
    e.preventDefault();

    console.log("This onClick method should prevent routerLink from executing.");

    return false;
}

But it does not disable the executing of routerLink!

Comments

1

Adding false after function will stop event propagation

<a (click)="foo(); false">click with stop propagation</a>

Comments

1

This solved my problem, from preventign that an event gets fired by a children:

doSmth(){
  // what ever
}
        <div (click)="doSmth()">
            <div (click)="$event.stopPropagation()">
                <my-component></my-component>
            </div>
        </div>

Comments

1

Try this directive

@Directive({
    selector: '[stopPropagation]'
})
export class StopPropagationDirective implements OnInit, OnDestroy {
    @Input()
    private stopPropagation: string | string[];

    get element(): HTMLElement {
        return this.elementRef.nativeElement;
    }

    get events(): string[] {
        if (typeof this.stopPropagation === 'string') {
            return [this.stopPropagation];
        }
        return this.stopPropagation;
    }

    constructor(
        private elementRef: ElementRef
    ) { }

    onEvent = (event: Event) => {
        event.stopPropagation();
    }

    ngOnInit() {
        for (const event of this.events) {
            this.element.addEventListener(event, this.onEvent);
        }
    }

    ngOnDestroy() {
        for (const event of this.events) {
            this.element.removeEventListener(event, this.onEvent);
        }
    }
}

Usage

<input 
    type="text" 
    stopPropagation="input" />

<input 
    type="text" 
    [stopPropagation]="['input', 'click']" />

Comments

-1

Most of the solutions provided are for versions above Angular 11, For Angular 11 or Below, I found a workaround that can be used:

export class UiButtonComponent implements OnInit, OnDestroy {

  @Input() disabled = false;

  clickEmitter: Subject<any> = new Subject();

  constructor(private elementRef: ElementRef) { }

  ngOnInit(): void {
    this.elementRef.nativeElement.eventListeners()
      .map(listener => this.clickEmitter.pipe(filter(event => Boolean(event))).subscribe(event => listener(event)));
    this.elementRef.nativeElement.removeAllListeners();
    this.elementRef.nativeElement.addEventListener('click', (event) => {
      if (!this.disabled) {
        this.clickEmitter.next(event);
      }
    });
  }

  ngOnDestroy(): void {
    this.clickEmitter.complete();
  }
}

I basically take every listener to the current component and put it on an Observable, then, I register only one listener and manage there the actions.

The example above is an example of disabling the click event on a button given a boolean variable.

1 Comment

Looks like you are solving different problem. There are many answers that works for Angular2+. Also you touching nativeElement. You should avoid doing this in any angular version.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.