Reputation: 12147
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.
Upvotes: 369
Views: 395668
Reputation: 329
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.
Upvotes: -1
Reputation: 1314
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...
}
}
Upvotes: 14
Reputation: 40327
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>
Upvotes: 366
Reputation: 657058
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)
Upvotes: 210
Reputation: 7601
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']" />
Upvotes: 1
Reputation: 163
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/>
Upvotes: 16
Reputation: 84
I used
<... (click)="..;..; ..someOtherFunctions(mybesomevalue); $event.stopPropagation();" ...>...
in short just seperate other things/function calls with ';' and add $event.stopPropagation()
Upvotes: 3
Reputation: 11
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>
Upvotes: 1
Reputation: 2753
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();
}
Upvotes: 3
Reputation: 171
Adding false after function will stop event propagation
<a (click)="foo(); false">click with stop propagation</a>
Upvotes: 1
Reputation: 375
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)
}
Upvotes: 3
Reputation: 7418
Adding to the answer from @AndroidUniversity. In a single line you can write it like so:
<component (click)="$event.stopPropagation()"></component>
Upvotes: 56
Reputation: 2131
<a href="#" onclick="return yes_js_login();">link</a>
yes_js_login = function() {
// Your code here
return false;
}
<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!
Upvotes: 2
Reputation: 43087
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();
}
Upvotes: 309
Reputation: 202138
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;
}
}
Upvotes: 11