Reputation: 3499
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?
Upvotes: 1
Views: 324
Reputation: 3231
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.
Upvotes: 1
Reputation: 16
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"`)
}
}
}
Upvotes: 0
Reputation: 3003
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.
Upvotes: 1