Detect Click Outside Element

How do I detect a click outside an element?

Note: Using stopPropagation is something that should be avoided as it breaks normal event flow in the DOM. See this CSS Tricks article for more information. Consider using this method instead.

Attach a click event to the document body which closes the window. Attach a separate click event to the container which stops propagation to the document body.

$(window).click(function() {
//Hide the menus if visible
});

$('#menucontainer').click(function(event){
event.stopPropagation();
});

Detect click outside React component

The following solution uses ES6 and follows best practices for binding as well as setting the ref through a method.

To see it in action:

  • Hooks Implementation
  • Class Implementation After React 16.3
  • Class Implementation Before React 16.3

Hooks Implementation:

import React, { useRef, useEffect } from "react";

/**
* Hook that alerts clicks outside of the passed ref
*/
function useOutsideAlerter(ref) {
useEffect(() => {
/**
* Alert if clicked on outside of element
*/
function handleClickOutside(event) {
if (ref.current && !ref.current.contains(event.target)) {
alert("You clicked outside of me!");
}
}
// Bind the event listener
document.addEventListener("mousedown", handleClickOutside);
return () => {
// Unbind the event listener on clean up
document.removeEventListener("mousedown", handleClickOutside);
};
}, [ref]);
}

/**
* Component that alerts if you click outside of it
*/
export default function OutsideAlerter(props) {
const wrapperRef = useRef(null);
useOutsideAlerter(wrapperRef);

return <div ref={wrapperRef}>{props.children}</div>;
}

Class Implementation:

After 16.3

import React, { Component } from "react";

/**
* Component that alerts if you click outside of it
*/
export default class OutsideAlerter extends Component {
constructor(props) {
super(props);

this.wrapperRef = React.createRef();
this.handleClickOutside = this.handleClickOutside.bind(this);
}

componentDidMount() {
document.addEventListener("mousedown", this.handleClickOutside);
}

componentWillUnmount() {
document.removeEventListener("mousedown", this.handleClickOutside);
}

/**
* Alert if clicked on outside of element
*/
handleClickOutside(event) {
if (this.wrapperRef && !this.wrapperRef.current.contains(event.target)) {
alert("You clicked outside of me!");
}
}

render() {
return <div ref={this.wrapperRef}>{this.props.children}</div>;
}
}

Before 16.3

import React, { Component } from "react";

/**
* Component that alerts if you click outside of it
*/
export default class OutsideAlerter extends Component {
constructor(props) {
super(props);

this.setWrapperRef = this.setWrapperRef.bind(this);
this.handleClickOutside = this.handleClickOutside.bind(this);
}

componentDidMount() {
document.addEventListener("mousedown", this.handleClickOutside);
}

componentWillUnmount() {
document.removeEventListener("mousedown", this.handleClickOutside);
}

/**
* Set the wrapper ref
*/
setWrapperRef(node) {
this.wrapperRef = node;
}

/**
* Alert if clicked on outside of element
*/
handleClickOutside(event) {
if (this.wrapperRef && !this.wrapperRef.contains(event.target)) {
alert("You clicked outside of me!");
}
}

render() {
return <div ref={this.setWrapperRef}>{this.props.children}</div>;
}
}

Detect click outside element

Keep in attention that this solution only works with Vue 1.

Can be solved nicely by setting up a custom directive once:

Vue.directive('click-outside', {
bind () {
this.event = event => this.vm.$emit(this.expression, event)
this.el.addEventListener('click', this.stopProp)
document.body.addEventListener('click', this.event)
},
unbind() {
this.el.removeEventListener('click', this.stopProp)
document.body.removeEventListener('click', this.event)
},

stopProp(event) { event.stopPropagation() }
})

Usage:

<div v-click-outside="nameOfCustomEventToCall">
Some content
</div>

In the component:

events: {
nameOfCustomEventToCall: function (event) {
// do something - probably hide the dropdown menu / modal etc.
}
}

Working Demo on JSFiddle with additional info about caveats:

https://jsfiddle.net/Linusborg/yzm8t8jq/

Detect click outside div using javascript

It depends on the individual use case but it sounds like in this example there are likely to be other nested elements inside the main div e.g. more divs, lists etc. Using Node.contains would be a useful way to check whether the target element is within the div that is being checked.

window.addEventListener('click', function(e){   
if (document.getElementById('clickbox').contains(e.target)){
// Clicked in box
} else{
// Clicked outside the box
}
});

An example that has a nested list inside is here.

Detect click outside element (vanilla JavaScript)

Add an event listener to document and use Node.contains() to find whether the target of the event (which is the inner-most clicked element) is inside your specified element. It works even in IE5

const specifiedElement = document.getElementById('a')

// I'm using "click" but it works with any event
document.addEventListener('click', event => {
const isClickInside = specifiedElement.contains(event.target)

if (!isClickInside) {
// The click was OUTSIDE the specifiedElement, do something
}
})

var specifiedElement = document.getElementById('a');

//I'm using "click" but it works with any event
document.addEventListener('click', function(event) {
var isClickInside = specifiedElement.contains(event.target);
if (isClickInside) {
alert('You clicked inside A')
} else {
alert('You clicked outside A')
}
});
div {
margin: auto;
padding: 1em;
max-width: 6em;
background: rgba(0, 0, 0, .2);
text-align: center;
}
Is the click inside A or outside?
<div id="a">A
<div id="b">B
<div id="c">C</div>
</div>
</div>

How to detect click outside of an element in Angular?

Here is the link to the working demo: Stackblitz Demo

I would do this by using the Angular recommended approach which is also easy to develop apps in environments with no DOM access, I mean Renderer 2 class which is an abstraction provided by Angular in the form of a service that allows manipulating elements of your app without having to touch the DOM directly.

In this approach, you need to inject Renderer2 into your component constructor, which the Renderer2 lets us to listen to triggered events elegantly. It just takes the element you're going to listen on as the first argument which can be window, document, body or any other element reference. For the second argument it takes the event we're going to listen on which in this case is click, and the third argument is actually the callback function which we do it by arrow function.

this.renderer.listen('window', 'click',(e:Event)=>{ // your code here})

The rest of the solution is easy, you just need to set a boolean flag which keeps the status of the menu (or panel) visibility, and what we should do is to assign false to that flag when it's clicked outside of the menu.

HTML

<button #toggleButton (click)="toggleMenu()"> Toggle Menu</button>

<div class="menu" *ngIf="isMenuOpen" #menu>
I'm the menu. Click outside to close me
</div>

app.component.ts

    export class AppComponent {
/**
* This is the toogle button elemenbt, look at HTML and see its defination
*/
@ViewChild('toggleButton') toggleButton: ElementRef;
@ViewChild('menu') menu: ElementRef;

constructor(private renderer: Renderer2) {
/**
* This events get called by all clicks on the page
*/
this.renderer.listen('window', 'click',(e:Event)=>{
/**
* Only run when toggleButton is not clicked
* If we don't check this, all clicks (even on the toggle button) gets into this
* section which in the result we might never see the menu open!
* And the menu itself is checked here, and it's where we check just outside of
* the menu and button the condition abbove must close the menu
*/
if(e.target !== this.toggleButton.nativeElement && e.target!==this.menu.nativeElement){
this.isMenuOpen=false;
}
});
}

isMenuOpen = false;

toggleMenu() {
this.isMenuOpen = !this.isMenuOpen;
}
}

Again, if you like to see the working demo, use this link: Stackblitz Demo

How do you handle click-outside of element properly in vuejs?

After struggling with this and searching about this, i found how to solve this problem using vuejs directive without bleeding:

1. using libraries:

v-click-outside is a good one,

https://www.npmjs.com/package/v-click-outside

2. without a library:

```
//main.js
import '@/directives';
......

// directives.js
import Vue from "vue";
Vue.directive('click-outside', {
bind: function (element, binding, vnode) {
element.clickOutsideEvent = function (event) { // check that click was outside the el and his children
if (!(element === event.target || element.contains(event.target))) { // and if it did, call method provided in attribute value
vnode.context[binding.expression](event);
// binding.value(); run the arg
}
};
document.body.addEventListener('click', element.clickOutsideEvent)
},
unbind: function (element) {
document.body.removeEventListener('click', element.clickOutsideEvent)
}
});
```

use it every-where you want with v-click-outside directive like below:

//header.vue
<div class="profileQuickAction col-lg-4 col-md-12" v-click-outside="hidePopUps">
...
</>

you can check this on

How do I detect a click outside an element?

Note: Using stopPropagation is something that should be avoided as it breaks normal event flow in the DOM. See this CSS Tricks article for more information. Consider using this method instead.

Attach a click event to the document body which closes the window. Attach a separate click event to the container which stops propagation to the document body.

$(window).click(function() {
//Hide the menus if visible
});

$('#menucontainer').click(function(event){
event.stopPropagation();
});


Related Topics



Leave a reply



Submit