Passing boolean Vue prop value in HTML

Vuejs2

Vuejs2 Problem Overview


I am fairly new to Vue and have started with a project with vue-cli.

I am looking into conditional rendering based on a prop sent from parent.

Home.vue (parent)

<template>
    <Header have-banner="true" page-title="Home">

    </Header>
</template>

<script>
    import Header from "./Header";

    export default {
	    components: {
		    Header,
	    },
	    name: "Home",
	    data() {
		    return {
			    header: "Hello Vue!",
		    };
	    },
    };
</script>

Header.vue (child)

<template>
    <header>
	    <div v-if="haveBanner == 'true'">
            ...
	    </div>
	        ...
    </header>
</template>

I have looked at another conventional way to achieve this but vue-cli renders templates differently.

As passing the prop in the HTML markup, the prop haveBanner evaluates as a string and, therefore, even if I did:

Parent

<Header have-banner="false"></Header>

Child

<div v-if="haveBanner"`>
    ...
</div>

That <div> would still display and, because of this, I am having to do an explicit check to see if it evaluates to 'true'. I am not a fan of this due to possible issues with type coercion and I am thrown a warning with a type check (===) saying:

> Binary operation argument type string is not compatible with type string

Is there a way to for either the child to evaluate this prop as a boolean or for the parent to pass it as a boolean in the markup?

Vuejs2 Solutions


Solution 1 - Vuejs2

If passing in JS keywords such as boolean values or references to variables, you will need to use v-bind (or :), i.e.:

<Header v-bind:have-banner="true" page-title="Home">

This will have the effect of binding the boolean true to the prop, not a "true" string. If you are not using v-bind, the haveBanner prop will always be truthy because it is a string of non-zero length, no matter if you assign "true" or "false" to it.

Friendly hint: HTML tags are not case-sensitive, so you might want to use custom-header or my-header-component instead of Header:

<custom-header v-bind:have-banner="true" page-title="Home">

See proof-of-concept:

Vue.component('custom-header', {
  template: '#customHeader',
  props: {
    haveBanner: Boolean,
    pageTitle: String
  }
});

new Vue({
  el: '#app'
});

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.15/vue.min.js"></script>

<div id="app">
  <custom-header v-bind:have-banner="true" page-title="Home"></custom-header>
  <custom-header v-bind:have-banner="false" page-title="Home"></custom-header>
</div>
 
<script type="text/x-template" id="customHeader">
    <header>
        <div v-if="haveBanner">
          <code>haveBanner</code> is true!
        </div>
        <div v-else>
          <code>haveBanner</code> is false!
        </div>
    </header>
</script>

Pro tip: Use : shorthands to make your template more readable, i.e.:

<custom-header :have-banner="true" page-title="Home">

Solution 2 - Vuejs2

To use a Boolean type as a prop, you have to use v:bind

<Header v-bind:have-banner="true" page-title="Home">

or using a short syntax

<Header :have-banner="true" page-title="Home">

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionwmashView Question on Stackoverflow
Solution 1 - Vuejs2TerryView Answer on Stackoverflow
Solution 2 - Vuejs2decpkView Answer on Stackoverflow