How to load conditional dynamic components in Vue without using v-if / v-else
When developing applications in whichever end, access management is on the forefront of every system, this determines who has access to what based on the role they have in the system. In Vuejs when it comes to showing a given component based on the user role and rights, we jump to using v-if
v-else-if
v-else
directives to pull this off.
To illustrate the above conditional statements, let us consider three user roles Admin
Guest
Distiguished
that give access to a different component given the role a user has in the system.
In the above code snippet, we see that the component visible to user is determined by the type of role this user holds. If the user has the `admin`, they will see the admin component likewise for guest and distinguished user.
The issue with this approach comes when more and more user roles are created, let’s 10 or 15 more roles are created with different access rights, you can imagine how many v-else-if or v-if
will be written to check for all the roles. This eventually will result in hard to manage components.
Note: I don’t claim in the later approach that we dont check, we do but in a better way.
Vue
has an element called component
, this with the help of computed properties provide a better and elegant alternative to v-ifs in the templates. component
is an element built-in vuejs to create dynamic components using the is
attribute to define which component to be active at a given time. — W3Schools. With the <component>
element, one is able to do all the checks on the fly in a computed property and the right component is always displayed on the screen as illustrated in a working example of the component
element below.
<component :is='computedProperty' />
In the above line, the self closed tag component
is the element and :is
is the attribute used to dynamically load the vue components, (:is is shortened from v-bind:is)
As mentioned, how do we use component
with computed properties
to to attain the same functionality as the v-if statements in the template. For that, we shall create three separate components to represent:
- Admin User
- Distinguished User
- Guest User
- And an extra select component to switch between the users
The Admin Component
In this admin component we take in a required property of a message, have a slot for other components and some styles. The same goes for the Guest and Distinguished User. What differentiates them is the background and text color when displayed.
The Guest Component
The Distinguished Component
The Select Component
In the Select component above, we have a Select element that binds with the user
property and whenever a change happens in the Select, the user
value also changes. The Select component then emits
an event change-user
to the parent component with the new user value. But before we look at using the component element, let us first look at the implementation where we use the v-if v-else-if v-else
directives. This is the same example I started with in the v-if
section.
Here we notice that whenever a value is changed in the Select Component, a change-user
event is emitted and it triggers a method setUserChange
that sets the user
property to the selected option. Then the right component is rendered to the screen through the v-if v-else-if v-else
checks.
Having looked at this, let’s see how we can avoid the v-if v-else-if v-else
blocks and still achieve the same output but in an elegant way.
In the above code snippet we use the component
element in the template
instead of v-if v-else-if v-else
statements.
First we import all the required components as well as ref
and computed
from vue since we are using the composition api. We register the SelectItem
component that we later use in the template
to switch the user components that show on the screen based on the selected user.
We then create a computed property called changeComponent
and inside this computed property, we use an object with the roles as the key and the components as the value and we return the component from the computed property based on what has been selected.
<component :is='changeComponent' :msg='message'/>
When using the component
element, we use the is
attribute to load the returned component from the computed property by passing changeComponent
as the value to is
attribute. You notice that we are also able to pass a prop
to the component
element and this prop
is the prop name used in the components that are dynamically loaded when a new selection is made, this changes the message based on the selected component.
Still we can pass in other components to the component
element to load in the respective slot
of a component.
<component :is='changeComponent' :msg='message'>
<p style"width:200px; height: 4vh">I am a {{ user }} user</p>
</component>
The component passed to the slot
in this case is the paragraph in the middle of the component
tags.
Note: we can use if
statements or switch
statement instead of the object in the computed property.
Lastly we use the components in our home view. Here we have it folks.
Below is a screenshot of the screen, all code snippets and a link to the github repo for the code
If you liked or learnt something, feel free to subscribe or connect with me on my socials, Linkedin or Twitter