Search code examples
vue.jsvuejs2vuelidate

Is it possible to bind a class to an element based on a boolean expression?


I want to bind a class to an element based on the result of a boolean expression. For example:

<input type="email" :class="{ invalid: submitted && $v.email.$error }">

But the "invalid" class is not added to the element if I evaluate both conditions; it only works when I evaluate one or the other, for example:

<input type="email" :class="{ invalid: submitted }">

or

<input type="email" :class="{ invalid: $v.email.$error }">

work just fine. I realize I could use computed properties for this, but I'd have to create a computed property for each field in my web form and that seems redundant. Is there a better way?


Solution

  • I think I've found a pretty good solution. I used a method with an argument instead of computed properties:

    <template>
      <form @submit.prevent="onSubmit" novalidate>
        <input
          type="email"
          :class="{ invalid: isInvalid($v.email.$error) }"
          v-model.lazy="email">
        <button type="submit">Submit</button>
      </form>
    </template>
    
    <script>
    import { required, email } from 'vuelidate/lib/validators'
    
    export default {
      data () {
        return {
          email: '',
          submitted: false
        }
      },
      validations: {
        email: {
          required,
          email
        },
      },
      methods: {
        isInvalid (val) {
          return val && this.submitted
        },
        onSubmit () {
          this.submitted = true
          if (!this.$v.$invalid) {
            // do something with the email address
          }
        }
      }
    }
    </script>