68

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?

2 Answers 2

131

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">
Sign up to request clarification or add additional context in comments.

Comments

5

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">

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.