Search code examples
vue.jsvalidationvuejs2vuetify.js

How can I prevent a Vue 2/Vuetify form submitting if required fields are empty?


I have a contact form I built in Vue 2/Vuetify 2 for a site I'm building. The form submits to Strapi (the CMS I'm using) no problem. However, even with setting rules/validation, it will still submit with empty fields.

The furthest I've been able to get is to where it won't submit at all without an email. However, if I just put an email into the form, it'll still submit with all the other fields empty.

How can I make sure it properly validates and then clears on submission? Below I have the code for the form.

Any and all help is greatly appreciated.

Vue Form

<template>
  <v-dialog persistent v-model="show" max-width="650px">
    <v-card class="px-9 py-5" color="#EEF8FF">
      <div class="d-flex justify-end">
        <div
          style="color: #020659"
          class="d-flex align-center cursor-pointer p-5 mb-5"
          @click.stop="show = false"
        >
          Close
          <v-icon color="#020659" class="">mdi-close</v-icon>
        </div>
      </div>
      <v-card class="px-11 no-bottom-border" elevation="1">
        <!-- <div v-if="error">
          {{ error }}
        </div> -->
        <v-form v-on:submit="handleSubmit" v-model="valid">
          <div class="pt-3" v-if="errors.length">
            <b>Please correct the following error(s):</b>
            <ul>
              <li v-for="error in errors" :key="error">{{ error }}</li>
            </ul>
          </div>

          <v-row>
            <v-col cols="12" class="">
              <h2 class="themepurple my-3">Contact Us</h2>
            </v-col>
          </v-row>
          <v-card-text>
            <v-row>
              <v-col cols="6">
                <v-text-field
                  color="#020659"
                  label="Name*"
                  required
                  name="name"
                  v-model="name"
                  :rules="nameRules"
                ></v-text-field>
              </v-col>
              <v-col cols="6">
                <v-text-field
                  color="#020659"
                  label="E-Mail*"
                  required
                  name="email"
                  v-model="email"
                  type="email"
                  :rules="emailRules"
                ></v-text-field>
              </v-col>
            </v-row>
            <v-row>
              <v-col>
                <v-select
                  v-model="subject"
                  required
                  name="subject"
                  label="Subject*"
                  :items="[
                    'Account Creation or Login Issue',
                    'Not a 501c3 - Requesting an Exception',
                    'Can\'t Find the Information I am Looking For',
                    'Suggestion for Future Content',
                    'Website Issue',
                    'Service Directory Edits',
                    'Other',
                  ]"
                  variant="underlined"
                  color="#020659"
                  :rules="subjectRules"
                ></v-select>
              </v-col>
            </v-row>
            <v-row>
              <v-col>
                <v-textarea
                  v-model="message"
                  name="message"
                  required
                  color="#020659"
                  label="How Can We Help?*"
                  :rules="messageRules"
                >
                </v-textarea>
              </v-col>
            </v-row>
            <v-row>
              <v-col>
                <v-btn type="submit" block class="mt-2 submit-button">
                  Submit</v-btn
                >
              </v-col>
            </v-row>
          </v-card-text>
        </v-form>
      </v-card>
    </v-card>
  </v-dialog>
</template>

Script

<script>
import axios from "axios";

export default {
  name: "ContactUs",
  props: {
    value: Boolean,
  },
  data() {
    return {
      valid: false,
      name: "",
      nameRules: [(v) => !!v || "Name is required"],
      email: "",
      emailRules: [
        (v) => !!v || "E-mail is required",
        (v) => /.+@.+/.test(v) || "E-mail must be valid",
      ],
      subject: "",
      subjectRules: [(v) => !!v || "Subject is required"],
      message: "",
      messageRules: [(v) => !!v || "Message is required"],
      // error: null,
      errors: [],
    };
  },
  methods: {
    handleSubmit: async function (e) {      
      e.preventDefault();

      try {
        const response = await axios.post(
          "https://api-next.impact-hq.org/api/contacts",

          {
            data: {
              name: this.name,
              email: this.email,
              subject: this.subject,
              message: this.message,
            },
          }
        );

        console.log(response);
      } catch (error) {
        // this.error = error;
        if (this.name && this.email && this.subject && this.message)
          return true;
        this.errors = [];
        if (!this.name) this.errors.push("Name required.");
        if (!this.email) this.errors.push("Valid email required.");
        if (!this.subject) this.errors.push("Subject required.");
        if (!this.message) this.errors.push("Message required.");
        
      }

      
       
    },

    // checkForm: function (e) {
     
    //   e.preventDefault();
    // },
  },
  computed: {
    show: {
      get() {
        return this.value;
      },
      set(value) {
        this.$emit("input", value);
      },
    },
  },
};
</script>

Solution

  • You can make the button disabled if the rules aren't met so the user cannot even try to submit the form.

    To reset the validations you can add a ref attribute to the v-form.

    <v-form ref="myForm" v-on:submit="handleSubmit" v-model="valid">
    

    And add this code snippet to your handling method.

    this.$refs.myForm.reset()