javascriptcssvue.jsvuejs2vue-component

How to get CSS Modules to work in Vue class binding?


Google already can't help me.

I have template in Vue like this:

<template>
    <button
        :class="{ 'button-selected': isSelected }">
    </button>
</template>

Everything works great until I try to use CSS Modules:

<template>
    <button
        :class="{ styles['button-selected']: isSelected }">
    </button>
</template>

...

import styles from "./Button.scss"

...

data () {
    return {
        styles
    }
}

Sure. I can't use it, since

let obj = { style['button-selected']: this.isSelected }

are also invalid expression.

I found temporary solution:

<template>
    <button
        :class="classes">
    </button>
</template>
...
computed: {
    classes () {
        let obj = {}
        obj[this.styles['button-selected']] = this.isSelected
        return obj
    }
}

But since I use this pattern I need to create a computed prop for each element.
I'm trying to find another way to do it.

Thanks for your help in advance.


Solution

  • You can use es6 computed property names:

    <button :class="{ [styles['button-selected']]: isSelected }">
    

    The outer brackets around styles['button-selected'] evaluate that expression as a property name.

    new Vue({
      el: "#app",
      data() {
        return {
          isSelected: true,
          styles: {
            'button-selected': 'redclass'
          }
        }
      }
    });
    .redclass {
      background: red;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
    <div id="app">
      <button :class="{ [styles['button-selected']]: isSelected }">
      asdf
      </button>
    </div>

    You could also use a ternary:

    <button :class="isSelected ? styles['button-selected'] : ''">