Search code examples
javascriptvue.jsbulma

VueJS binding class in template not working


I'm learning VueJS and I want to make tab components. I have a main.js and index.html file as follows:

Vue.component('tabs', {
  template: "<div><div class='tabs is-medium'><ul><li v-for='tabb in tabs' :class='{'is-active': tabb.selected}'><a href='#'>{{ tabb.name }}</a></li></ul></div><div class='tabs-details'> <slot></slot></div></div>",
  data() {
    return {tabs: []};
  },

  created() {
    this.tabs = this.$children;
  }
});

Vue.component('tab', {
  template: '<div><slot></slot></div>',
  props: {
    name: {required: true },
    selected: { default: false }
  }

})

new Vue({
  el: '#root'

});
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title></title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.5/css/bulma.min.css">

  </head>
  <body>
  
    <div id="root">

      <tabs>
        <tab name="Tab1" :selected="true">
          <h1>Tab1 content</h1>
        </tab>

        <tab name="Tab2">
          <h1>Tab2 content</h1>
        </tab>

        <tab name="Tab3">
          <h1>Tab3 content</h1>
        </tab>

      </tabs>
   </div>


  <script src="https://unpkg.com/vue@2.6.10/dist/vue.js"></script>

  </body>
</html>

The problem is in class binding part (:class='{'is-active': tabb.selected}'). The code works when it's removed or when the binding is not used and class value remains the same (class='is-active'). I was wondering why the binding class is not working ?

Note: Single quotes are used everywhere in template because it's (apparently) the only way I can keep everything in template (thus between " ") in the editor Atom.


Solution

  • You cannot write this:

    :class='{'is-active': tabb.selected}'
    

    You're using single quotes for two different purposes. As soon as Vue encounters that second ' it is going to think that the attribute value has ended. This ends up being equivalent to:

    :class='{'
    

    The usual convention is to use backticks (not to be confused with single-quotes) for templates, like this:

    template: `
      <div>
        <div class="tabs is-medium">
          <ul>
            <li v-for="tabb in tabs" :class="{'is-active': tabb.selected}">
              <a href="#">{{ tabb.name }}</a>
            </li>
          </ul>
        </div>
        <div class="tabs-details">
          <slot></slot>
        </div>
      </div>
    `,
    

    If you really can't use backticks then just escape some double-quotes. So either one of these:

    :class=\"{'is-active': tabb.selected}\"
    

    or:

    :class='{\"is-active\": tabb.selected}'