Reputation: 3146
I may just be thinking about this wrong because I'm doing it in Angular and over complicating, but what I'm trying to do is setup my click event so it only triggers when an element is clicked, but not it's child. I'm trying to setup a modal, where if you click the background overlay it closes, but obviously I don't want it closing if the user interacts with the modal.
<div class="overlay">
<div class="modal">
</div>
</div>
So far, I've created this:
@HostListener('document:click', ['$event.target']) public onClick(targetElement: HTMLElement) {
const clickedInside = this._elementRef.nativeElement.contains(targetElement);
if (!clickedInside && targetElement.class.indexOf('overlay') && targetElement.parentElement.tagName === 'GP-MODAL') {
//do stuff
}
}
Where _elementRef
is the Angular ElementRef
. The problem is it feels like an inefficient way of doing it: trigger on any click, only continue on certain elements. It feels more ideal to trigger a click on .overlay
and then somehow not have it go off in .wrapper
, but I can't think of how to do it. Any advice?
Upvotes: 1
Views: 2163
Reputation: 3146
I came up with two possible methods, depending on selection criteria.
The first is just Javascript: If you know a specific attribute of the clicked element you can check on, create a click event on the element you want to track, bound to:
clickedOverlay(event) {
if (event.target.parentElement.tagName === 'GP-MODAL') {
// Do stuff
}
}
A more Angular focused answer:
@ViewChild('target') targetRef: ElementRef;
clickedOverlay(event: MouseEvent) {
if (this.targetRef.nativeElement === event.target) {
// Do stuff
}
}
It's more explicit, and less prone to false positives, but more verbose.
Not suggesting these are the best answers, but my preference right now.
Upvotes: 1
Reputation: 176
I think what you are looking for is the stopPropagation method, which resides in the event object
(function () {
var app = angular.module('app', []);
app.controller('MainCtrl', MainController);
MainController.$inject = [];
function MainController () {
var vm = this;
vm.onClick = function (event) {
event.stopPropagation();
alert('Child clicked');
};
vm.parentOnClick = function (event) {
alert('Parent clicked');
};
}
}) ();
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular.min.js"></script>
<body ng-app="app" ng-controller="MainCtrl as vm">
<div ng-click="vm.parentOnClick($event)" style="height: 400px; width: 400px; background: red;">
<div ng-click="vm.onClick($event)" style="position: absolute; top: 100px; left: 100px; background: blue; height: 200px; width: 200px;">
</div>
</div>
</body>
Upvotes: 2