25

I'm trying to add a contact form with simple validation on a website built with Vue.js using a Vuetify.js example. I'm a newbie, so I'm not sure how it should be implemented in a Vue component.


I want to achieve a simple client side form validation and make it work with a https://getform.org/ form.


UPDATED:

Code | Contact.vue

(taken from Vuetify.js form example)

<v-form v-model="valid">
      <v-text-field
        label="Name"
        v-model="name"
        :rules="nameRules"
        :counter="10"
        required
        name="Name"
      ></v-text-field>

      <v-text-field
        label="E-mail"
        v-model="email"
        :rules="emailRules"
        required
        name="Email"
      ></v-text-field>

      <v-btn
          @click="submit"
          :disabled="!valid"
      >submit</v-btn>
  </v-form>

  <form method="post" action="https://www.getform.org/f/[MY_ID_HERE]" id="nativeForm"></form>

Script

<script>
export default {
  name: 'contact',

  data () {
    return {
      snackbar: true, 
      valid: false,
        name: '',
        nameRules: [
          (v) => !!v || 'Name is required',
          (v) => v.length <= 10 || 'Name must be less than 10 characters'
        ],
        email: '',
        emailRules: [
          (v) => !!v || 'E-mail is required',
          (v) => /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(v) || 'E-mail must be valid'
        ]
      }
    },
    methods: {
      submit() {
        nativeForm.submit()
      }
    }
  }
</script>
Bhuwan
  • 16,525
  • 5
  • 34
  • 57
Un1
  • 3,874
  • 12
  • 37
  • 79
  • well seems like you don't have `http://localhost:8080/api/submit` route? you need serverside route. your port `8080` is used for client side (i.e. vuejs) i presume, thus you need serverside routes for form submit – Traxo Dec 31 '17 at 13:48
  • @Traxo yeah, but, do I have to just create it in order for the form to work? Or it's not that simple? – Un1 Dec 31 '17 at 13:49
  • For form validation, you don't need routes, but for submiting your data, you probably do. – Traxo Dec 31 '17 at 13:50
  • see basic example where form is validated on client side without submit https://github.com/vuetifyjs/vuetifyjs.com/blob/master/examples/forms/basicValidation.vue https://codepen.io/anon/pen/ppPqQx – Traxo Dec 31 '17 at 13:58
  • @Traxo thanks, I've seen this example, but I didn't understand that it's what I needed (updated question). But now I'm getting `message: null, email: null` from the getform API (code updated in the question). **In case** you know how to pass the data to the second form so it wouldn't sent out `null` please post the answer I'll accept it – Un1 Dec 31 '17 at 14:18
  • @Traxo sorry to bother, I've just realized how to do it, I should've used 1 form instead. I suppose the problem is solved – Un1 Dec 31 '17 at 14:30
  • yeah :P was just in the midst of explaining but nvm – Traxo Dec 31 '17 at 14:32
  • @Traxo yeah, sorry, being a newbie sucks. Even simple things take hours to solve and understand...Thank you for the suggestions though, it helps..If it wasn't for your comment, I would still be trying to understand how to use this Axios API. Turns out I wanted a Client side validation – Un1 Dec 31 '17 at 14:35
  • Note that for client side validation you don't need getform service. – Traxo Dec 31 '17 at 14:39
  • @Traxo well, I use this service as a simple way to receive messages from the contact form on the site, without doing some PHP magic myself :) – Un1 Dec 31 '17 at 14:44
  • Why not a simple html form? no need for external libraries, validty checks in controllers etc https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Your_first_HTML_form. You can still catch the event, use v-model etc – phil294 Aug 30 '18 at 17:12

2 Answers2

13

Managed to make it work by using just 1 form:

<v-form method="post" action="https://www.getform.org/f/[YOUR-FORM-ID]" id="nativeForm" v-model="valid">

      <v-text-field
        label="Name"
        v-model="name"
        :rules="nameRules"
        :counter="10"
        required
        name="message"
      ></v-text-field>
      <v-text-field
        label="E-mail"
        v-model="email"
        :rules="emailRules"
        required
        name="mail"
      ></v-text-field>

      <v-btn @click="submit" :disabled="!valid">submit</v-btn>
 </v-form>

script

 <script>
    export default {
      name: 'contact',

      data () {
         return { 
            valid: false,
            name: '',
            nameRules: [
              (v) => !!v || 'Name is required',
              (v) => v.length <= 10 || 'Name must be less than 10 characters'
            ],
            email: '',
            emailRules: [
              (v) => !!v || 'E-mail is required',
              (v) => /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(v) || 'E-mail must be valid'
            ]
          }
        },
        methods: {
          submit() {
            nativeForm.submit()
          }
        }
      }
  </script>

Don't forget:

To add name attributes. Getform needs them.

Un1
  • 3,874
  • 12
  • 37
  • 79
6

const app = new Vue({
  el:'#app',
  data:{
    errors:[],
    name:null,
    age:null,
    movie:null
  },
  methods:{
    checkForm:function(e) {
      if(this.name && this.age) return true;
      this.errors = [];
      if(!this.name) this.errors.push("Name required.");
      if(!this.age) this.errors.push("Age required.");
      e.preventDefault();
    }
  }
})
input,select {
  margin-left: 10px;
}
<script src="https://unpkg.com/vue@2.5.13/dist/vue.js"></script>
<form id="app" @submit="checkForm" action="/something" method="post">
  
  <p v-if="errors.length">
    <b>Please correct the following error(s):</b>
    <ul>
      <li v-for="error in errors">{{ error }}</li>
    </ul>
  </p>
  
  <p>
    <label for="name">Name<label>
    <input type="text" name="name" id="name" v-model="name">
  </p>

  <p>
    <label for="age">Age<label>
    <input type="number" name="age" id="age" v-model="age" min="0">
  </p>

  <p>
    <label for="movie">Favorite Movie<label>
    <select name="movie" id="movie" v-model="movie">
      <option>Star Wars</option>
      <option>Vanilla Sky</option>
      <option>Atomic Blonde</option>
    </select>
  </p>

  <p>
    <input type="submit" value="Submit">  
  </p>

</form>

Add some CSS and done.

Cruzer
  • 405
  • 5
  • 13
  • I've already managed to make it work (see the other answer), but I'll assign the bounty to your question for the effort and a non-Vuetify.js specific general Vue method of doing it. Thanks – Un1 Jan 07 '18 at 12:58