# Interaction Outside
@vue-cdk/interaction-outside
makes it easy to detect user–interactions that happen outside of a specific element/component.
# Installation
The @vue-cdk/interaction-outside
package can be installed via NPM/Yarn:
$ npm install @vue-cdk/interaction-outside --save
# Usage
@vue-cdk/interaction-outside
exposes a Vue plugin that you can use like this:
import InteractionOutside from '@vue-cdk/interaction-outside'
import Vue from 'vue'
Vue.use(InteractionOutside)
The plugin makes a component called CInteractionOutside
globally available.
Just wrap any element or component with CInteractionOutside
. CInteractionOutside
will listen for events and once user–interaction outside of the wrapped element/component is detected CInteractionOutside
emits the detected
–event.
# Examples
# Hello World
Show Code
<template>
<div class="outside" :class="outsideClasses">
{{ outsideText }}
<CInteractionOutside @detected="outside = true">
<div class="inside" :class="insideClasses" @click="outside = false">
{{ innerText }}
</div>
</CInteractionOutside>
</div>
</template>
<script>
export default {
data() {
return {
outside: null,
}
},
computed: {
innerText() {
const { outside } = this
switch (outside) {
case null: {
return 'This is the inside. Click here.'
}
case false: {
return 'Now click anywhere – just not here.'
}
case true: {
return 'Click outside of this element detected.'
}
default: {
throw Error('invalid state')
}
}
},
outsideText() {
return this.outside === false ? 'You can click here or anywhere else.' : ''
},
insideClasses() {
return {
'is-active': this.outside === false,
}
},
outsideClasses() {
return {
'is-active': this.outside === true,
}
},
},
}
</script>
<style scoped>
.inside {
text-align: center;
border: 1px solid #cccccc;
margin: 1rem;
padding: 1rem;
background-color: white;
}
.inside.is-active {
background-color: rgb(210, 253, 255);
}
.outside {
text-align: center;
background-color: white;
border: 1px solid #cccccc;
margin: 1rem;
padding: 1rem;
}
.outside.is-active {
background-color: rgb(210, 253, 255);
}
</style>
# Ignoring Elements
You can disable the detection of outside interaction for specific elements. Simply set ignored
to a method that returns an array of HTMLElement
s that should be ignored.
Show Code
<template>
<div class="outside" :class="outsideClasses">
<CInteractionOutside :ignored="ignored" @detected="outside = true">
<div class="inside" :class="insideClasses" @click="outside = false">
{{ innerText }}
</div>
</CInteractionOutside>
<div v-show="outside === false" ref="ignored" class="ignored">
Clicks here are ignored. Try it!
</div>
</div>
</template>
<script>
export default {
data() {
return {
outside: null,
}
},
computed: {
innerText() {
const { outside } = this
switch (outside) {
case null: {
return 'This is the inside. Click here.'
}
case false: {
return 'Now click anywhere – just not here.'
}
case true: {
return 'Click outside of this element detected.'
}
default: {
throw Error('invalid state')
}
}
},
outsideText() {
return this.outside === false ? 'You can click here or anywhere else.' : ''
},
insideClasses() {
return {
'is-active': this.outside === false,
}
},
outsideClasses() {
return {
'is-active': this.outside === true,
}
},
},
methods: {
ignored() {
return [this.$refs.ignored]
},
},
}
</script>
<style scoped>
.inside {
text-align: center;
border: 1px solid #cccccc;
margin: 1rem;
padding: 1rem;
background-color: white;
}
.ignored {
text-align: center;
border: 1px solid #cccccc;
margin: 1rem;
padding: 1rem;
color: rgb(173, 2, 2);
font-weight: bold;
background-color: white;
}
.inside.is-active {
background-color: rgb(210, 253, 255);
}
.outside {
text-align: center;
background-color: white;
border: 1px solid #cccccc;
margin: 1rem;
padding: 1rem;
}
.outside.is-active {
background-color: rgb(210, 253, 255);
}
</style>
# Activating and Deactivating
By default CInteractionOutside
is active. An active CInteractionOutside
will listen for events and try to detect interaction outside of it. You can disable the detection of outside–interaction by setting active
to false
. This is useful if you want to temporary disable any accidental actions.
Show Code
<template>
<div class="outside" :class="outsideClasses">
{{ outsideText }}
<button @click="active = !active">
{{ active ? 'Deactivate' : 'Activate' }} CInteractionOutside
</button>
<CInteractionOutside :active="active" @detected="outside = true">
<div class="inside" :class="insideClasses" @click="outside = false">
{{ innerText }}
</div>
</CInteractionOutside>
</div>
</template>
<script>
export default {
data() {
return {
outside: null,
active: false,
}
},
computed: {
innerText() {
const { outside } = this
switch (outside) {
case null: {
return 'This is the inside. Click here.'
}
case false: {
return 'Now click anywhere – just not here.'
}
case true: {
return 'Click outside of this element detected.'
}
default: {
throw Error('invalid state')
}
}
},
outsideText() {
return this.outside === false ? 'You can click here or anywhere else.' : ''
},
insideClasses() {
return {
'is-active': this.outside === false,
}
},
outsideClasses() {
return {
'is-active': this.outside === true,
}
},
},
}
</script>
<style scoped>
.inside {
text-align: center;
border: 1px solid #cccccc;
margin: 1rem;
padding: 1rem;
background-color: white;
}
.inside.is-active {
background-color: rgb(210, 253, 255);
}
.outside {
text-align: center;
background-color: white;
border: 1px solid #cccccc;
margin: 1rem;
padding: 1rem;
}
.outside.is-active {
background-color: rgb(210, 253, 255);
}
</style>