skip to Main Content

I’m creating my own role/rights system because the ones that are available for Vue don’t work.

I now hide the element when a user does not have the appropriate role. But what I actually want is to not render the component at all. But I don’t know how to achieve that.

I have the following code:

app.directive('hasRole', hasRole)
import {useUserStore} from "@/stores/UserStore.js";

export default {
    // called before bound element's attributes
    // or event listeners are applied
    created(el, binding, vnode, prevVnode) {
        //console.log(el, binding, vnode, prevVnode)
    },
    // called right before the element is inserted into the DOM.
    async beforeMount(el, binding, vnode, prevVnode) {
        const userStore = useUserStore()
        await userStore.fill()
        console.log(userStore.getUser.roles.includes(binding.value))
        if (!userStore.getUser.roles.includes(binding.value)) {
            // el.style.display = 'none'; <---- this hides the element, so that works.
            vnode = null
            return el = null;
            el.style.display = 'none';
        }
    },
    // called when the bound element's parent component
    // and all its children are mounted.
   mounted(el, binding, vnode, prevVnode) {
        //console.log(el, binding, vnode, prevVnode)
    },
    // called before the parent component is updated
    beforeUpdate(el, binding, vnode, prevVnode) {
        //console.log(el, binding, vnode, prevVnode)
    },
    // called after the parent component and
    // all of its children have updated
    updated(el, binding, vnode, prevVnode) {
        //console.log(el, binding, vnode, prevVnode)
    },
    // called before the parent component is unmounted
    beforeUnmount(el, binding, vnode, prevVnode) {
        //console.log(el, binding, vnode, prevVnode)
    },
    // called when the parent component is unmounted
    unmounted(el, binding, vnode, prevVnode) {
        //console.log(el, binding, vnode, prevVnode)
    }
}

How can I prevent the render of the component?

3

Answers


  1. I think that using directives for this purpose, is not the right way, in order to avoid component rendering.

    To avoid a component to be rendered you should, insted, use the v-if condition.

    To share the logic of hasRole between your component, you can use mixins, or just write a small plugin you can add to Vue app.

    Login or Signup to reply.
  2. Here is the corrected code I have.

    import {useUserStore} from "@/stores/UserStore.js";
    
    export default {
      inserted(el, binding, vnode) {
        const { value } = binding
        const super_admin = "admin";
        const userStore = useUserStore()
        await userStore.fill()
        const roles = userStore.getUser.roles
    
        if (value && value instanceof Array && value.length > 0) {
          const roleFlag = value
    
          const hasRole = roles.some(role => {
            return super_admin === role || roleFlag.includes(role)
          })
    
          if (!hasRole) {
            el.parentNode && el.parentNode.removeChild(el)
          }
        } else {
          throw new Error(`Missing role value"`)
        }
      }
    }
    
    Login or Signup to reply.
  3. You already have a user store that can be injected into any component.

    I suggest computing often-used keys like isAdmin, isSuperAdmin in the store:

    
    const isAdmin computed(() => hasRole('admin'))
    
    

    In your components, you can use the following pattern to conditionally render items:

    <template>
    <div v-if="isAdmin">
      <h1>Super Secret Stuff</h1>
    </div>
    </template>
    
    <script setup>
    const { isAdmin } = useUserStore()
    </script>
    

    This circumvents direct DOM manipulation, which is always a pain and often a bad practice.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search