Vue: Class binding - can't pass string of classes when mixing array with object definition

Created on 16 Apr 2016  ·  11Comments  ·  Source: vuejs/vue

Vue.js version

1.0.21

Reproduction Link

http://www.webpackbin.com/4kszqXok-

Steps to reproduce

Try to bind multiple classes like this :class="['class-1 class-2', { 'class-3': true }]"

What is Expected?

Be be able to bind classes like I described above.

What is actually happening?

Getting console error:

Uncaught InvalidCharacterError: Failed to execute 'add' on 'DOMTokenList': The token provided ('color-green text-uppercase') contains HTML space characters, which are not valid in tokens

Is this bug or am i doing it right wrong?

Most helpful comment

As far as I'm aware, it's already fixed in dev: https://github.com/vuejs/vue/pull/2678

All 11 comments

Hello @sqal
Why would you pass a static class name in the binding? you should add class-1 and class-2 directly on the class attribute

I'm pretty sure the feature is really easy to add but adding static class names on the class binding doesn't look right to me. Have you taken a look at the guide section concerning class bindings? It may help you http://vuejs.org/guide/class-and-style.html#ad

As far as I'm aware, it's already fixed in dev: https://github.com/vuejs/vue/pull/2678

@posva Hi. I have dropdown component and I want to bind some custom classes from options prop and also some additional classes if some of the options are true e.g.

...
<div v-show="open" class="dropdown-menu" :class="[options.menuClasses, { 'dropdown-menu-right': options.right }]" :transition="options.effect">
  <slot name="dropdown-content"></slot>
</div>
...

name: 'Dropdown',
props: {
  open: {
    type: Boolean,
    twoWay: true,
    default: false,
  },
  options: {
    type: Object,
    coerce(options) {
      return Object.assign({}, dropdownDefaults, options);
    },
  },
},
...

I see, I didn't know it was already supported :sweat_smile:
I'd have created an array with a computed property

Since it's already fixed I'm closing the issue. If you see the problem appears in the new release, feel free to open the issue again.

Just a heads up, that use isn't actually in dev.

@sqal is doing:

:class="['class-1 class-2', { 'class-3': true }]"

but

:class="['class-1', 'class-2', { 'class-3': true }]"

is what would work in dev.

Wait... I'm sorry. I'm wrong. You can close it again. Long day. I even wrote that test.

In case it helps, might be too new @ Vue, but I couldn't get the above "static" example working when that static value is coming from the Vuex "store" property. It seems to always lag 1 "commit" behind.

<template>
  <div id="app" :class="[this.$store.state.bodyColor, { 'nav-is-open': this.$store.state.menu }]">
    <span>{{this.$store.state.bodyColor}}</span>
  </div>
</template>

in the above example, the is updated, but the classes are not, whenever the store changes.

@bensmeets it probably doesn't work because you use this inside the template. Never do this!

:class="[$store.state.bodyColor, { 'nav-is-open': $store.state.menu }]">

Tnx @sqal, I tried that, but the behaviour is the same. It doesn't update in the class, but it does in the span.

@sqal Doh... found out what it was. It was an issue with Safari not updating the dev-tools. In Chrome it does, and there everything it works fine. It seems either Safari or the combination of Vue's Dom with Safari makes it not showing the actual DOM in the inspector.

In this example, you could make a computed property returning array, instead. Like this:

computedClass() {
  let res = this.$store.state.bodyColor

  if (this.$store.state.menu) {
    res.push('nav-is-open')
  }

  return res
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

aviggngyv picture aviggngyv  ·  3Comments

guan6 picture guan6  ·  3Comments

finico picture finico  ·  3Comments

loki0609 picture loki0609  ·  3Comments

seemsindie picture seemsindie  ·  3Comments