Reputation: 247
I have a div with a mouseenter event. Within that div there is a button with a click event. The idea is that the user hovers over the div, on the mouseenter event, the div becomes "active". If the div is active, then the button is visible and clickable.
Everything seems to work great on desktop. However, on mobile, due to the mouseenter event, if you click where the button should become visible, on an inactive div, the button is clicked.
I'd like to prevent the user from accidentally clicking the button when they think they're clicking the div to make it "active". I'm assuming this can be done with event handling https://v2.vuejs.org/v2/guide/events.html#Event-Modifiers but I cannot for the life of me work it out.
Please see the following codepen - https://codepen.io/jameshine/pen/GRNNzdq or code below.
Please note: If you test on desktop and click the button, you will still get the "clicked by mistake" error message. This codepen is for mobile view, but I'm unsure I can force it to display my problem in mobile?
<div id="app">
<div class="container mx-auto">
<div class="flex -mx-2">
<div class="w-1/2 px-2" @mouseenter="activate(key)" v-for="(item, key) in items" :key="key">
<div class="h-full p-5 rounded-lg" :class="[ active === key ? 'bg-yellow-500' : 'bg-gray-300']">
<div class="mb-10">
<p>{{ item.name }}</p>
</div>
<button class="bg-red-500 px-3 py-2 rounded" @click="alert('I\'ve been clicked by mistake')" v-if="active === key">Activate Me</button>
</div>
</div>
</div>
</div>
</div>
new Vue({
el: "#app",
data() {
return {
active: undefined,
items: [
{
name: "A"
},
{
name: "B"
}
]
};
},
methods: {
activate(key) {
this.active = key;
}
}
});
Upvotes: 0
Views: 341
Reputation: 1143
If I understand your question correctly, it sounds like you need to do something like this:
<button @click.prevent.stop="handleClick(key)">Activate me</button>
// Methods:
handleClick(key) {
if (this.active !== key) {
this.active = key;
} else {
// Do whatever the button should do here
}
}
UPDATE 1:
The issue seems to be with the mouseenter
event firing immediately before the click
event on mobile. This seems a bit hacky but I think it should work - if you had a slight delay inside your activate
method, like this:
activate(key) {
setTimeout(() => this.active = key, 50);
}
UPDATE 2:
Here's an alternative solution - add this to your parent div:
@touchstart.prevent="handleTouchStart($event, key)"
Then in your methods:
handleTouchStart($event, key) {
if (this.active === key) {
$event.target.click();
} else {
this.active = key;
}
}
What this does is, when a touchStart
event is registered on the parent div, if it is not currently "active", the event is cancelled but the div is made active. If it is currently active, it allows the click event to proceed as normal.
Upvotes: 1