javascriptvue.jsvuejs3vue-directives

Vue directive don't render element if condition is false


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?


Solution

  • 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.