vue.jsauthenticationvue-material

@submit.prevent not working on vue md-input


when I click 'login button' even I don't fill data in md-input it still running, I test my onSubmit() method by login with my user and it works! I don't think I do thing wrong in the method so I guess that my form is incorrect. here is my code :

my form

 <form @submit.prevent="onSubmit">
    <login-card header-color="green">
      <h4 slot="title" class="title">CCRP Sign On</h4>
      <p slot="description" class="description">IT solution by เจ้เก๋ IT-PM</p>
      <md-field class="md-form-group" slot="inputs">
        <md-icon>account_box</md-icon>
        <label>ID...</label>
        <md-input v-model.trim="userId" type="text"></md-input>
      </md-field>
      <md-field class="md-form-group" slot="inputs">
        <md-icon>lock_outline</md-icon>
        <label>Password...</label>
        <md-input v-model.trim="password" type="password"></md-input>
      </md-field>
      <md-field class="md-form-group">
        <md-icon>announcement</md-icon>
        <label>Password...</label>
      </md-field>
      <md-button slot="footer" class="md-simple md-success md-lg" type="submit">Login</md-button>
    </login-card>
  </form>

in scrpit methods

async onSubmit() {
      const authData = {
        userId: this.userId,
        password: this.password
      };
      await this.login(authData).then(() => {
        if (this.isAuthenticated) {
          this.$router.push("dashboard");
        } else {
          console.log("err");
        }
      });
    },

can you help me solve this?


Solution

  • Your understanding of "prevent" key is quite incorrect. All it does is not reload the form after submit action. However the submit action will be called irrespective of whether the prevent is used or not. It is just preventing the default functionality of form getting reloaded after each submit.

    On the other hand what you need to do is validate your form before actually submitting it.

    Example :

    //- Requires "vuelidate" - npm install vuelidate
    <script>
    
    import { validationMixin } from "vuelidate";
    import { required, email } from "vuelidate/lib/validators";
    
    export default {
      name: "FormValidation",
      mixins: [validationMixin],
      data: () => ({
        form: {
          email: null,
          password: null
        },
        userSaved: false,
        sending: false,
        lastUser: null
      }),
      validations: {
        form: {
          email: {
            required,
            email
          },
          password: {
            required
          }
        }
      },
      methods: {
        getValidationClass(fieldName) {
          const field = this.$v.form[fieldName];
    
          if (field) {
            return {
              "md-invalid": field.$invalid && field.$dirty
            };
          }
        },
        clearForm() {
          this.$v.$reset();
          this.form.email = null;
          this.form.password = null;
        },
        saveUser() {
          this.sending = true;
    
          // Instead of this timeout, here you can call your API
          window.setTimeout(() => {
            this.lastUser = `${this.form.email}`;
            this.userSaved = true;
            this.sending = false;
            this.clearForm();
          }, 1500);
        },
        validateUser() {
          this.$v.$touch();
    
          if (!this.$v.$invalid) {
            this.saveUser();
          }
        }
      }
    };
    </script>
    <style lang="scss" scoped>
    .md-progress-bar {
      position: absolute;
      top: 0;
      right: 0;
      left: 0;
    }
    </style>
    <template>
      <div>
      <!-- Calling validateUser insted of submit action -->
        <form novalidate class="md-layout" @submit.prevent="validateUser">
          <md-card class="md-layout-item md-size-50 md-small-size-100">
            <!-- Title of the form -->
            <md-card-header>
              <div class="md-title">Login</div>
            </md-card-header>
    
          <!-- Inputs for the form -->
            <md-card-content>
              <md-field :class="getValidationClass('email')">
                <label for="email">Email</label>
                <md-input
                  type="email"
                  name="email"
                  id="email"
                  autocomplete="email"
                  v-model="form.email"
                  :disabled="sending"
                />
                <span class="md-error" v-if="!$v.form.email.required">The email is required</span>
                <span class="md-error" v-else-if="!$v.form.email.email">Invalid email</span>
              </md-field>
    
              <md-field :class="getValidationClass('password')">
                <label for="password">Password</label>
                <md-input
                  type="password"
                  name="password"
                  id="password"
                  autocomplete="password"
                  v-model="form.password"
                  :disabled="sending"
                />
              <!-- to show errors in case validation fails -->
                <span class="md-error" v-if="!$v.form.password.required">The email is required</span>
                <span class="md-error" v-else-if="!$v.form.email.email">Invalid email</span>
              </md-field>
            </md-card-content>
    
            <md-progress-bar md-mode="indeterminate" v-if="sending"/>
    
            <md-card-actions>
              <md-button type="submit" class="md-primary" :disabled="sending">Create user</md-button>
            </md-card-actions>
          </md-card>
    
          <md-snackbar :md-active.sync="userSaved">The user {{ lastUser }} was saved with success!</md-snackbar>
        </form>
      </div>
    </template>