Search code examples
javascriptformsvue.jsjoi

How can I use field validation in my Vue wizard form?


In an example of a Vue wizard form I tried to add form validation with Joi. How do I set this up logically? The goal is to controll the fields before moving to the second and last page with the next() method. Because of the simplicity of this wizard form, I don't want to change to VueFormWizard. To increase the code I erased a lot of fields etc..

<template>
  <div>
    <div v-if="errorMessage" class="alert alert-danger" role="alert">
      {{errorMessage}}
    </div>
    <form>
      <div v-if="step ===1 ">
        <div class="form-group">
          <label for="title">Title</label>
          <input v-model="example.title"
                 type="text"
                 class="form-control"
                 id="title" />
         </div>
      <button @click.prevent="next()">Next step</button>
      </div>
      <div v-if="step === 2">
        <div class="form-group">
          <label for="userName">Email.</label>
          <input v-model="example.userName"
                 type="email"
                 class="form-control"
                 id="userName" />         
         </div>       
        <button @click.prevent="prev()">Go back</button>
        <button @click.prevent="createExample" type="submit" class="btn btn-primary">Submit</button>
      </div>
    </form>
  </div>
</template>

<script>
import Joi from 'joi'

const schema = Joi.object().keys({
  title: Joi.string().alphanum().min(2).max(40).required(),  
  userName: Joi.string().email(),
  })

export default {
  data: () => ({
    step: 1,
    errorMessage: false,
    example: {
      title: '',
      userName: ''
    }
  }),
  watch: {
    example: {
      handler () {
        this.errorMessage = ''
      },
      deep: true
    }
  },
  methods: {
    prev () {
      this.step--
    },
    next () {
      this.step++
      if (this.validUser()) {
           return false
      }
    },
    createExample () {
     // Post request
    },
    validUser () {
      const result = Joi.validate(this.huismap, schema)     
		return true
	if (result.error.message.includes('title')) {
    this.errorMessage = 'Vul een titel in van min 2 karakters'
    return false
    }
  }
}
</script>


Solution

  • You can make use of browser validation if you set it up like this:

    <form @submit.prevent="submitMyForm">
        <input v-model="form.title" required minlength="4" maxlength="20" />
    
        <button type="submit">Submit</button>
    </form>
    

    Now your browser will prevent you from submitting the form if title is empty, if the length is less than 4 or greater than 20.

    This solution can do a lot of stuff, even regex checking:

    https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Form_validation#Validating_against_a_regular_expression

    However this is limited to a small set of checks and is not supported by older browsers. If you need very specific validation you'd have to use a custom solution, which is described here https://v2.vuejs.org/v2/cookbook/form-validation.html.