<style type="text/css" media="screen"> .container { margin: 0px auto; max-width: 600px; } Talk to me <input type="text" name="name" placeholder="Your name" v-validate="'required'" :class="{ 'has-error': errors.has('name') }"> <span v-if="errors.has('name')" v-cloak>${ errors.first('name') }</span> <input type="text" name="email" placeholder="Your email" v-validate="'required|email'" :class="{ 'has-error': errors.has('email') }"> <span v-if="errors.has('email')" v-cloak>${ errors.first('email') }</span> <textarea name="message" onkeyup="adjust_textarea(this)" placeholder="Your message" v-validate="'required'" :class="{ 'has-error': errors.has('message') }"></textarea> <span v-if="errors.has('message')" v-cloak>${ errors.first('message') }</span> <button type="submit">Send</button> </fieldset> </form> <script type="text/javascript"> function adjust_textarea(h) { h.style.height = "200px"; h.style.height = (h.scrollHeight)+"px"; } <script src="https://unpkg.com/vue@2.4.2"> <script src="https://unpkg.com/vee-validate@2.0.0-rc.8"> <script type="text/javascript"> Vue.use(VeeValidate); const dictionary = { en: { custom: { name: { required: "Name is required" }, email: { required: "Email is required", email: "Email is invalid" }, message: { required: "Message is required" } } } }; VeeValidate.Validator.updateDictionary(dictionary); VeeValidate.Validator.setLocale("en"); new Vue({ el: '#form', delimiters: ['${', '}'], methods: { validateBeforeSubmit: function () { this.$validator.validateAll(); if (!this.errors.any()) { this.$refs.contact.submit(); } } } });