classbindingvuejs3prop

Vue 3 : conditional class binded with a prop not working


I created a vue3 component with the option API. The class "logo dark" is applied no matter the value of the prop DARK_MODE. I'd like the dark class to be added only if DARK_MODE is set to true. I don't understand what i did wrong ?

Here is the Logo2 component :

<template>
    <div class="logo" :class="{dark:DARK_MODE}">
        {{ DARK_MODE }}
    </div>
</template>

<script>
export default {
    name:"Logo2",
    props: {
        DARK_MODE : { type: Boolean, default: false},
    }
}
</script>

Which I call this way from App.vue :

<script>
import Logo2 from './components/Logo2.vue'
export default {
  name:"App",
  components: {
    Logo2
  }
}
</script>

<template>
  <Logo2 DARK_MODE="false"></Logo2>
  <Logo2 DARK_MODE="true"></Logo2>
</template>

Both tries end up with the right DARK_MODE text being displayed, but always the dark class applied.

Thank you !


Solution

  • If you look into the console, you'll see the following relevant warning:

    Invalid prop: type check failed for prop "DARK_MODE". Expected Boolean, got String with value "true".
     at <Logo2DARK_MODE="true">
     ...
    

    In order to pass true or false as Booleans, you have a few options:

    a) v-bind:LOGO_DARK (docs)

    <Logo2 v-bind:DARK_MODE="false" /> // false (Boolean)
    

    b) :LOGO_DARK (: is shorthand for v-bind:):

    <Logo2 :DARK_MODE="false" /> // false (Boolean)
    

    c) LOGO_DARK (without a value); evaluates to true because Vue mimics HTML native behavior for boolean props - e.g: disabled, readonly, etc...) 1:

    <Logo2 DARK_MODE /> // true (Boolean)
    

    d) absence of LOGO_DARK attribute; evaluates to default value, in your case false

    <Logo2 /> // false (Boolean)
    

    If you pass it a string (e.g: <Logo2 DARK_MODE="false" />), which is how Vue interprets any custom attribute value passed without the v-bind: prefix (or its shorthand :), it will always evaluate to true. That's because if the string is not empty casting it to Boolean evaluates to true. And if the string is empty (<Logo2 DARK_MODE="" /> Vue interprets it as verbose syntax for <Logo2 DARK_MODE /> and you're in case c) above.

    Additionally Vue will throw a warning when run in dev mode about any property value which doesn't match its declared type, pointing you to the component where it happened.


    See all cases in Vue SFC playground.

    1 - this rule only applies for Boolean props.