<div id='app'> 
  <div v-html='header'></div>
  
  <div :class='classes.container'>
    <div :class='classes.form'>
      <input type='email' v-model='form.email' placeholder='Email Field' />
      <input type='password' v-model='form.password' placeholder='Password Field' />
      <input type='password' v-model='form.password_confirmation' placeholder='Confirm Password' />
      
      <button :disabled='form.empty() || form.errors().any()' @click='submit' :class="classes.button">
          Submit
      </button>
    </div> 
    
    <transition name='slide'>
    <div :class='classes.errors' v-show='form.errors().any()'>
      <h2 :class='classes.header'>
          Failing Field Messages
      </h2>
      <transition-group name='fade'>
        <div v-if='form.errors().any()' v-for='(message, key) in form.errors().list()' :class='classes.danger' :key="`${key}.id`">
          {{ message }}
         </div>
      </transition-group>
    </div>
    </transition>
  </div>
</div>
body {
  background-color: #f5f5f5;
}
input, button {
  border: 1px solid #d5d5d5;
  border-radius: 3px;
  height: 50px;
  width: 100%;
  margin-top: 10px;
  padding: 5px;
}
.messages-container {
  padding: 10px;
  position:relative; 
  bottom: 110px;
  left: 4.45%;
  width: 51vw;
  height: 100vh!important;
  
}
button:disabled {
  opacity: 0.5 !important;
}


h1, h2 {
  color: #333333b3;
  font-weight: heavy;
}

#app {
  div.danger {
    border: 1px solid #de3618;
    background-color: #de3618;
  }
  
  padding-bottom: 15px;
}

.form {
  box-shadow: 0 0 0 3px rgba(66, 153, 225, 0.5);
}
.fade-enter-active, .fade-leave-active {
  transition: opacity .5s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
  opacity: 0;
}
.fade-enter-active, .fade-leave-active {
  transition: opacity .5s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
  opacity: 0;
}



.buttons {
  display: block;
  width: 150px;
  margin: 0 auto;
  margin-top: 20px;
}

.button, .button.disabled:hover { 
    display: block;
    margin-bottom: 20px;
    text-decoration: none;
    border:1px solid #25729a; 
    -webkit-border-radius: 3px; 
    -moz-border-radius: 3px;
    border-radius: 3px;
    font-family:arial, helvetica, sans-serif; 
    padding: 10px 10px 10px 10px; 
    text-shadow: -1px -1px 0 rgba(0,0,0,0.3);
    text-align: center; 
    color: #FFFFFF; 
    background-color: #3093c7;
    background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #3093c7), color-stop(100%, #1c5a85));
    background-image: -webkit-linear-gradient(top, #3093c7, #1c5a85);
    background-image: -moz-linear-gradient(top, #3093c7, #1c5a85);
    background-image: -ms-linear-gradient(top, #3093c7, #1c5a85);
    background-image: -o-linear-gradient(top, #3093c7, #1c5a85);
    background-image: linear-gradient(top, #3093c7, #1c5a85);filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr=#3093c7, endColorstr=#1c5a85);
}

.button:hover{
    border:1px solid #1c5675;
    background-color: #26759e;
    background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#26759e), color-stop(100%, #133d5b));
    background-image: -webkit-linear-gradient(top, #26759e, #133d5b);
    background-image: -moz-linear-gradient(top, #26759e, #133d5b);
    background-image: -ms-linear-gradient(top, #26759e, #133d5b);
    background-image: -o-linear-gradient(top, #26759e, #133d5b);
    background-image: linear-gradient(top, #26759e, #133d5b);filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr=#26759e, endColorstr=#133d5b);
}

.slide-leave-active,
.slide-enter-active {
  transition: 0.5s;
}
.slide-enter {
  transform: translate(100%, 0);
}
.slide-leave-to {
  transform: translate(100%, 0);
}

View Compiled
new Vue({
    el: '#app',
    data: () => ({
        form: form.default({
            email: '',
            password: '',
            password_confirmation: ''
        })
        .rules({
            email: 'email|min:5|required',
            password: 'required|min:5|confirmed',
            password_confirmation: 'required',
        })
        .messages({
            'email.email': ':attribute must be a valid email',
            'email.min': ':attribute may not have less than :min characters',
            'password.confirmed': "Password must have the same value as password confirmation"
        }),
   }),
    
   watch: {
       /*--------------------------------------------------------------
        | When Should Your Form "Validate", Providing Error Messages?
        |--------------------------------------------------------------
        | 
        | Form validates every time form data is updated. To
        | display errors on form submit, remove watcher &
        | move "this.form.validate()" over to submit()
        |
        */

        ['form.data']: {
            deep: true,
            immediate: false,
            handler: 'onFormChange'
        }
   },

    methods: {
        onFormChange(after, before) {
             this.form.validate()
        },
       
        submit() {
            return this.form.errors().any() ? this.failed() : this.passed();
        },

        failed() {
            console.log('errors: ', this.form.errors().all());
        },

        passed() {
            console.log('data: ', this.form.all());
            console.log('wrapped data: ', this.form.wrap('data'));
        }
    },
  
  
  
  
  
    /** Helpers stored in computed to clean up purpose of pen **/
    computed: {
      header: $this => $this.form.errors().any() 
        ? `<div class="w-full flex">${$this.npm} ${$this.github}</div><div class='w-full'>${$this.title}</div>` 
        : `<div class="w-full flex">${$this.npm} ${$this.github}</div><div><div class='w-full'>${$this.title}</div></div>`,
      
      title: $this =>`  
        <h4 class='${$this.classes.h1}'>VueForm.js Example Two (Form Validates on Every Change)</h4>
      `,
      links: $this => $this.errors().any() ? ``: `<div class="${$this.classes.banner}"> ${$this.github + $this.html}</div>`,
      
      classes: $this => ({
        h1: 'mt-8',
        h2: 'text-2sm',
        header: 'text-center mb-8 text-2xl',
        banner: 'flex w-full justiy-center mb-8',
        container: 'flex justify-around align-items-stretch',
        form: 'w-100%',
        errors: 'border border-gray-400 bg-white rounded messages-container w-100%',
        danger: 'mb-3 bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded',
        btn: 'bg-blue-500 text-white font-bold py-2 px-4 rounded-full w-100 mt-4',
        button: 'button'
      }),
      npm: () => `
        <div class="bg-red-700 text-center py-4 lg:px-4 w-1/2">
           <div class="p-2 bg-white items-center text-grey-100 leading-none lg:rounded-full flex lg:inline-flex" role="alert">
              <a href='https://www.npmjs.com/package/vuejs-form'>
                <span class="flex rounded-full b-white-500 px-2 py-1 text-xs font-bold ml-2">Npm Package</span>
  
              </a>
              <svg class="fill-current opacity-75 h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
                <path d="M12.95 10.707l.707-.707L8 4.343 6.586 5.757 10.828 10l-4.242 4.243L8 15.657l4.95-4.95z"/>
              </svg>
            </div>
        </div>
      `,
    
      github: () => `
          <div style='background-color: #24292e;' class="w-1/2 text-center py-4 lg:px-4">
            <div class="p-2 bg-white items-center text-grey-100 leading-none lg:rounded-full flex lg:inline-flex" role="alert">
              <a href='https://github.com/zhorton34/vuejs-form'>
                <span class="flex rounded-full b-white-500 px-2 py-1 text-xs font-bold ml-2">Github Repository</span>
              </a>
              <svg class="fill-current opacity-75 h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
                <path d="M12.95 10.707l.707-.707L8 4.343 6.586 5.757 10.828 10l-4.242 4.243L8 15.657l4.95-4.95z"/>
              </svg>
          </div>
        </div>
      `,
    }
 });

View Compiled

External CSS

  1. https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/1.4.6/tailwind.min.css

External JavaScript

  1. https://unpkg.com/vuejs-form@latest/build/vuejs-form.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js