Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create a custom conditional render directive in Vue.js

I'm trying to work out how I can make a custom Vue conditional directive. I know I could just write a global method and call it inside a v-if, but for code clarity I'd like to have a custom directive.

The aim is to decorate an element with the directive and pass a Guid to it (it's all for handling conditional rednering depending on user permissions): v-permission="'4ECE1FD4-4019-4CA2-AB9E-0A555CCBDB5B'"

At the moment, I just add display: none to the element in the directive's bind method and this is fine for hiding the content but it would be better performance wise if the element was never rendered.

Any ideas how I can achieve this?

Current directive code is as follows:

import Vue from 'vue'

Vue.directive('permission', {
  bind: function (el, binding, vnode) {
    if (binding.value) {
      let hasPermission = 
vnode.context.$store.getters.hasApiPermission(binding.value)
      if (!hasPermission) {
        el.style.display = 'none'
      }
    } else {
      console.error('You must specify a permission ID')
    }
  }
})
like image 740
Geek Josh Avatar asked Mar 08 '23 11:03

Geek Josh


1 Answers

Well it is possible using inserted hook:

inserted: called when the bound element has been inserted into its parent node.

example code snip:

Vue.directive('permission', {
  inserted: function (el, binding, vnode) {
    if (binding.value) {
      let hasPermission = 
vnode.context.$store.getters.hasApiPermission(binding.value)
      if (!hasPermission) {
        el.parentNode.removeChild(el)
      }
    } else {
      console.error('You must specify a permission ID')
    }
  }
})

However, it is still much more better to use the built-in v-if directive. Since Vue 2 is base on virtual DOM it will never render if the statement returns false. In this custom directive case it will be rendered firstly and removed afterwards.

like image 70
wxsm Avatar answered Mar 17 '23 00:03

wxsm