DEV Community

Cover image for An introduction to Vue.js - Chapter 5 - Conditional Rendering
Moritz Schramm
Moritz Schramm

Posted on

An introduction to Vue.js - Chapter 5 - Conditional Rendering

Series overview

Chapter 1
Chapter 2
Chapter 3
Chapter 4
Chapter 5

Foreword

I was away for some time and did not manage to write an article for you guys. But today we are continuing with our Vue.js series. Lets talk about conditional rendering in Vue and lets try to adapt our list so that we can use the list as a ordered and unordered list.

I will always upload the code to this github repository.

Conditions

We all know how we can do a conditional execution in JavaScript. Usally you have something like that:

if (a === b) {
    // Execute some code if it is true
} else {
    // Execute some code if it is false
}
Enter fullscreen mode Exit fullscreen mode

Even though some times you need something like that:

if (a === b) {
    // Execute some code if the first condition is true
} else if (b === c) {
    // Execute some code if then second condition is true
} else {
    // Execute some code if both conditions are false
}
Enter fullscreen mode Exit fullscreen mode

Now sometimes you want to render certain things only if a certain condition is true or even not. For that luckily Vue offers more directives called v-if, v-else and v-else-if.

v-if

The v-if is the most simple one. You can just add this to your corresponding DOM node that you only want to render under a certain circumstance. For example we want the possibility to differ between an ordered and unordered list. Of course we could simply duplicate our already existing list but we could also just change the rendered tag based on a boolean expression.

First I added an additional property to our list component:

import template from './list.html';

export default {
    name: 'vg-list',
    template,
    props: {
        items: {
            type: Array,
            required: true
        },
        ordered: {
            type: Boolean,
            required: false,
            default: false
        }
    }
};
Enter fullscreen mode Exit fullscreen mode

(If you do not have a clue yet about this, read the previous chapters ;))

Now we have a look at our HTML template. We want to render an ul tag if ordered === false and an ol tag if ordered === true. When you add the v-if directive to your DOM node you set the value to the boolean expression you want to check.

<ol v-if="ordered === true" class="list">
    <li v-for="item in items" class="list-element">{{ item }}</li>
</ol>
<ul v-if="ordered === false" class="list">
    <li v-for="item in items" class="list-element">{{ item }}</li>
</ul>
Enter fullscreen mode Exit fullscreen mode

Of course you could simply change the boolean to the shorthand expression

<ol v-if="ordered" class="list">
    <li v-for="item in items" class="list-element">{{ item }}</li>
</ol>
<ul v-if="!ordered" class="list">
    <li v-for="item in items" class="list-element">{{ item }}</li>
</ul>
Enter fullscreen mode Exit fullscreen mode

If you know would start the app, you should get an error since it is not allowed to have multiple root nodes within one component. At some point in the Vue history it was not possible to do such stuff without an additional container element around that. But since v2.0.1 they made it possible to have multiple root nodes when using v-if and v-else.

v-else

The v-else directive always reacts to the last v-if or v-else-if directive that was called before and on the same node level. You do not need to set any value to this new "attribute". It behaves like the usual else block in your JavaScript code.

To adapt now our code we just need to remove the second v-if directive and replace it by a v-else one.

<ol v-if="ordered" class="list">
    <li v-for="item in items" class="list-element">{{ item }}</li>
</ol>
<ul v-else class="list">
    <li v-for="item in items" class="list-element">{{ item }}</li>
</ul>
Enter fullscreen mode Exit fullscreen mode

If you now start your app it should actually work without an error message in your developer tools.

v-else-if

I could not think of any example where I would you such a thing. Actually I would prefer to rethink your component structure and maybe split them up into multiple ones (for sharing logic you could use mixins but about that we will talk later). That is why I will not go deep into that topic.

Basically it behaves like a combination of the other two. It needs to have a boolean expression as the value and it always reacts to the last v-if or v-else-if directive on the same node level.

If you want to have further reading, check the API documentation for that. ;)

Pass boolean parameters

While writing that article I noticed some missing knowledge from my side on how to pass a boolean to a component from your HTML template. Usually, I would use a property and bind that one to the component but that do not make sense at all when using such a list component. When just doing this:

<div class="app">
    <h1>Hello World</h1>
    <vg-button text="Foo bar" />
    <vg-list :items="items" ordered="true" />
    <vg-list :items="items" />
</div>
Enter fullscreen mode Exit fullscreen mode

We would get a "Expected Boolean, Got String." error. That is why I looked it up and it is actually pretty easy. You just need to bind the boolean value to the component:

<div class="app">
    <h1>Hello World</h1>
    <vg-button text="Foo bar" />
    <vg-list :items="items" :ordered="true" />
    <vg-list :items="items" />
</div>
Enter fullscreen mode Exit fullscreen mode

or

<div class="app">
    <h1>Hello World</h1>
    <vg-button text="Foo bar" />
    <vg-list :items="items" v-bind:ordered="true" />
    <vg-list :items="items" />
</div>
Enter fullscreen mode Exit fullscreen mode

That actually works because the value of the v-bind directive is executed as JavaScript code and the return value is passed to the bound component.

Done

I hope you like the guide. If you have any questions ask them on Twitter or in the comment section. I will try to answer a much as possible. I am happy about any possible feedback.

Next chapter will come in the next days.

Latest comments (0)