Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent/stop propagation of default event (click) in directive (vue 2.x)

Tags:

vue.js

vuejs2

Vue.directive('login-to-click', {
  bind (el) {
    const clickHandler = (event) => {
      event.preventDefault()
      event.stopImmediatePropagation()
      alert('click')
    }
    el.addEventListener('click', clickHandler, true)
  }
})

usage

<button @click="handleClick" v-login-to-click>CLICK</button>

handleClick is always triggered. How I can prevent that from directive? Tried with/without addEventListener "capture" flag without any luck.


For now I ended up with following solution:

Vue.prototype.$checkAuth = function (handler, ...args) {
  const isLoggedIn = store.getters['session/isLoggedIn']
  if (isLoggedIn) {
    return handler.apply(this, args)
  } else {
    router.push('/login')
  }
}

And then in component

<button @click="$checkAuth(handleClick)">CLICK</button>
like image 521
user606521 Avatar asked Aug 01 '17 13:08

user606521


People also ask

How do you stop event propagation in Vue?

preventDefault() or event. stopPropagation() inside event handlers. It is always better to have your methods deal purely with data logic instead of having to deal with DOM event details. Vue provides us with some event modifiers for the v-on.

Does prevent default stop propagation?

preventDefault() prevents the default browser behavior for a given element. stopPropagation() stops an event from bubbling or propagating up the DOM tree. Whereas, return false is a combination of both preventDefault() and stopPropagation() .

What is prevent in Vue?

Prevent default behaviorTo prevent an event's default behavior, we can call the . prevent modifier in Vue, which calls the native event. preventDefault() method. This series of steps prevents the event from reloading the page after the form is submitted.

What does event not stop propagation do?

stopPropagation() The stopPropagation() method of the Event interface prevents further propagation of the current event in the capturing and bubbling phases. It does not, however, prevent any default behaviors from occurring; for instance, clicks on links are still processed.


3 Answers

From my understanding those are two different event handlers, you are only preventing the default event of the one bound in the directive, this has no influence on @click however, because you are not overwriting the click listener but adding a second one. If you want the default of your @click binding to be prevented you can use @click.prevent="handleClick".

I don't think there's any way to do it from the directive, since you explicitly add another listener by binding @click to the button.

like image 195
Philip Feldmann Avatar answered Nov 15 '22 18:11

Philip Feldmann


in my app I have many buttons (follow/like/add to watchlist/block etc) that require user to be logged in to click on them

As with many things in Vue 2, this is a bad use case for a directive, but a very good use case for a component.

Here is a button that is only clickable when the user is authorized.

console.clear()

const AuthenticatedButton = {
  props:["onAuth", "onNonAuth", "disable", "auth"],
  template: `
    <button @click="onClick" 
            :disabled="disableWhenNotAuthorized">
      <slot>{{this.auth}}</slot>
    </button>`,
  computed:{
    disableWhenNotAuthorized(){
      return this.disable && !this.auth
    }
  },
  methods:{
    onClick(){
      if (this.auth && this.onAuth) this.onAuth()
      if (!this.auth && this.onNonAuth) this.onNonAuth()      
    }
  }
}

new Vue({
  el:"#app",
  data:{
    loggedIn: false
  },
  methods:{
    onClick(){
      alert("User is authenticated")
    },
    notAuthorized(){
      alert("You are not authorized.")
    }
  },
  components:{
    "auth-btn": AuthenticatedButton
  }
})
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<div id="app">
  <h3>User is {{!loggedIn ? 'Not Authorized' : 'Authorized'}}</h3>
  <auth-btn :auth="loggedIn" 
            :on-auth="onClick"
            :on-non-auth="notAuthorized">
    Executes non auth handler when not authorized
  </auth-btn> <br>
  <auth-btn :auth="loggedIn" 
            :on-auth="onClick"
            :disable="true">
    Disabled when not authorized
  </auth-btn> <br><br>
  <button @click="loggedIn = true">Authenicate User</button>
</div>

With this button you can set an authorized handler and a non-authorized handler. Additionally, you can just disable the button if the user is not authorized.

In this component the authorized state is passed in through a property, but if you were using some form of state management (like Vuex) you could just as easily use that instead.

like image 38
Bert Avatar answered Nov 15 '22 18:11

Bert


https://v2.vuejs.org/v2/guide/events.html#Event-Modifiers

There are a couple modifiers. .prevent is what I was looking for

<a href="#" @click.prevent="sendMessage('just one click');">
like image 40
Michael Cole Avatar answered Nov 15 '22 18:11

Michael Cole