NerdSoup
NerdSoup

Reputation: 173

Vue.js: prevent user clicking on element while it is being transitioned with Vue <transition>

I'm working on a Vue.js project, and when I click on an element, I'm using the Vue transition tag to fade it out. The problem is that as the element is in the process of being faded out, it is still clickable, which in my application can cause issues.

My question is: how can I make an element unclickable during a transition, so that users don't click it multiple times before the transition finishes?

I've already tried applying a css class with point-events: none; to the element right when the transition starts, but it didn't stop clicks during transition.

Example:

<transition name="fade">
  <div v-if="shouldShow" @click="doSomeAction">Example text</div>
</transition>

(where doSomeAction sets shouldShow to false).

Upvotes: 2

Views: 3630

Answers (3)

Cathy Ha
Cathy Ha

Reputation: 1677

Vue has event modifiers that might help with that. The specific one which might be helpful to you is @click.once. If you add this to the click event the user will only be able to click it once. Documentation for it is here.

Upvotes: 1

NerdSoup
NerdSoup

Reputation: 173

Update

If you also need to ensure that users can immediately click "through" the element that is being faded out to items behind it, you can add a class with pointer-events: none; to the element, and then do this:

this.$nextTick(() => {
  this.shouldShow = false;
});

This will make sure the fade doesn't happen until the class has been added. this.$nextTick is a Vue function that waits for the dom to update (which in this case is adding the pointer-events class) before running a callback: https://v2.vuejs.org/v2/api/#Vue-nextTick

Note that pointer-events: none; doesn't work on some very old browsers (IE < 10)

Upvotes: 0

Andrew Vasylchuk
Andrew Vasylchuk

Reputation: 4779

If you are using Vue.js 2.6+ you can do it with ease. In this minor realse Dynamic directive arguments was added, so you can conditionally bind desired event name, or in you case disable it (passing null).

Dynamic argument values are expected to be strings. However, it would be convenient if we allow null as a special value that explicitly indicates that the binding should be removed. Any other non-string values are likely mistakes and will trigger a warning.

Reference.

// using computed property
<transition name="fade">
  <div v-if="shouldShow" @[event]="doSomeAction">Example text</div>
</transition>

export default {
  data() {
    return {
       shouldShow: true
     }
  },
  computed: {
    event() {
      return this.shouldShow ? "click" : null;
    }
  }
}

// using object
<transition name="fade">
  <div v-if="shouldShow" v-on="{ [shouldShow ? 'click' : null]: doSomeAction }">Example text</div>
</transition>

Upvotes: 1

Related Questions