Reputation: 1488
I need to capture all click events triggered by the user inside my Vue.js application. My first step was to add an onclick listener to the #app
div:
<div id="app" @click="onClickApp"></div>
// ...
<script>
export default {
methods: {
onClickApp() {
// increment counter in vuex store
}
}
</script>
This captures all click events happening directly inside the App component. The issue is that I'm using a Bootstrap Modal (provided via BootstrapVue) and I need to capture the clicks inside it as well. This is not working at the moment, even if I set another @click listener on the <b-modal></b-modal>
component (syntax for vue-cli).
This is what I also tried (in main.js
):
new Vue({
router,
store,
render: h => h(App),
mounted: function() {
this.$el.addEventListener('click', this.onClickVue)
},
beforeDestroy: function () {
this.$el.removeEventListener('click', this.onClickVue)
},
methods: {
onClickVue: function (e) {
this.$store.commit(mutationTypes.INCREMENT_CLICKS)
}
});
Same problem, clicks inside the Bootstrap Modals are not firing a click event.
Upvotes: 5
Views: 9011
Reputation: 8548
I could only get this to work by using the mouseup
event..
CodePen mirror: https://codepen.io/oze4/pen/PgKWRW?editors=1010
new Vue({
el: "#app",
data: {
modalShow: false
},
mounted() {
document.addEventListener("mouseup", e => {
let m = `x: ${e.clientX} | y: ${e.clientY}`;
console.log(m);
})
}
});
<script src="https://unpkg.com/[email protected]/dist/vue.min.js"></script>
<script src="https://unpkg.com/[email protected]/dist/bootstrap-vue.min.js"></script>
<link href="https://unpkg.com/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://unpkg.com/[email protected]/dist/bootstrap-vue.css" rel="stylesheet" />
<div id="app">
<div style="margin: 5px 0px 0px 40px">
<b-button @click="modalShow = !modalShow">Open Modal</b-button>
<b-modal v-model="modalShow">Hello From Modal!</b-modal>
</div>
</div>
Upvotes: 4
Reputation: 1030
I couldn't find a way to test with Bootstrap Vue, but this might do.
TLDR: Create a plugin which will run whenever any of your components are instantiated. Put a listener on the root element.
https://codesandbox.io/s/kxwz85pl65
const MyPlugin = {
install(Vue, options) {
Vue.mixin({
mounted() {
setTimeout(() => {
let cb = this.$root.$el.onclick;
this.$root.$el.onclick = (e) => {
alert("element clicked");
if (cb) {
cb(e);
}
};
}, 10);
}
});
}
};
EDIT:
As of writing this Vue Bootstrap
doesn't seem to allow click events for the modal itself, though elements inside of it can be clicked.
https://codesandbox.io/embed/kxwz85pl65
EDIT again, you can use set timeout if you really want to. It's a bit of a hack though.
Upvotes: 0
Reputation: 496
A better answer is just adding ev to onClickApp, so do onClickApp(ev) inside your methods.
Now, you have access to the click event.
Upvotes: 1
Reputation: 4484
This should work ;-)
- <div id="app" @click="onClickApp"></div>
+ <div id="app"></div>
// ...
<script>
export default {
methods: {
onClickApp() {
// increment counter in vuex store
}
},
+ mounted() {
+ window.document.addEventListener('click'), this.onClickApp)
+ },
+ beforeDestroy() {
+ window.document.removeEventListener('click'), this.onClickApp)
+ }
</script>
Upvotes: 0