Form Validation Fix
March 20, 2025 ยท AI Conversations
<script>
import { ref,inject,onMounted } from "vue";
import Google from '@/assets/images/auth/social-google.svg';
import { useAuthStore } from '@/stores/auth';
import { useLoadingStore } from '@/stores/loading';
import { useRouter } from 'vue-router';
import { Form } from 'vee-validate';
import publicApi from '@/publicApi';
const apiUrl = inject('apiUrl');
const loadingStore = useLoadingStore();
const authStore = useAuthStore();
const router = useRouter();
const alertMessage=ref("");
const alertColor=ref("");
const checkbox = ref(false);
const valid = ref(false);
const show1 = ref(false);
//const logform = ref();
const password = ref('');
const username = ref('');
const passwordRules = ref([
(v: string) => !!v || 'Password is required',
(v: string) => (v && v.length <= 10) || 'Password must be less than 10 characters'
]);
const emailRules = ref([(v: string) => !!v || 'E-mail is required', (v: string) => /.+@.+..+/.test(v) || 'E-mail must be valid']);
/* eslint-disable @typescript-eslint/no-explicit-any */
const submit = async () => {
loadingStore.setLoading(true);
alertMessage.value = "";
alertColor.value = "";
try {
const response = await publicApi.post(`${apiUrl}/login`, {
email: username.value,
password: password.value
});
console.log(response);
if (response.data.success) {
alertMessage.value = "Login successful!";
alertColor.value = 'success';
authStore.setUser(response.data.user, response.data.token);
router.push('/dashboard');
} else {
console.log(response.data);
alertMessage.value = response.data.message;
alertColor.value = 'error';
console.error("Login failed:", response.data.message);
}
} catch (error: any) {
console.log(error);
alertMessage.value =error.response?.data.message;
alertColor.value = 'error';
console.error("Error during login:", error.response?.data.message || error.message);
} finally {
loadingStore.setLoading(false);
}
}
</script>
Sign in with Google
OR
Sign in with Email address
Forgot password?
Sign In
{{ errors.apiError }}
Don't Have an account?
<style>
.custom-devider {
border-color: rgba(0, 0, 0, 0.08) !important;
}
.googleBtn {
border-color: rgba(0, 0, 0, 0.08);
margin: 30px 0 20px 0;
}
.outlinedInput .v-field {
border: 1px solid rgba(0, 0, 0, 0.08);
box-shadow: none;
}
.orbtn {
padding: 2px 40px;
border-color: rgba(0, 0, 0, 0.08);
margin: 20px 15px;
}
.pwdInput {
position: relative;
.v-input__append {
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
}
}
.loginForm {
.v-text-field .v-field--active input {
font-weight: 500;
}
}
</style>
Uncaught (in promise) TypeError: e.preventDefault is not a function
at prevent (chunk-U3LI7FBV.js?v=63b73135:12141:21)
at cache..cache. (chunk-U3LI7FBV.js?v=63b73135:12158:20)
at vee-validate.js?v=63b73135:2246:20
on click sign in
### Possible Issues & Fixes:
#### 1. **Incorrect Usage of `@submit.prevent`**
You're using VeeValidate's “ component with `@submit.prevent="submit"`. However, VeeValidate handles form submission internally, so using `.prevent` might not be necessary.
โ **Fix: Remove `.prevent` from `@submit`**
<Form @submit="submit" class="mt-7 loginForm" v-slot="{ errors, isSubmitting }">
#### 2. **VeeValidate's Submission Handling**
The `submit` function should accept `values` from VeeValidate, instead of relying on Vue's `ref` values directly.
โ
**Fix: Update `submit` function to use `values`**
Modify the `submit` function to accept `values` from VeeValidate:
const submit = async (values: { email: string; password: string }) => {
loadingStore.setLoading(true);
alertMessage.value = "";
alertColor.value = "";
try {
const response = await publicApi.post(`${apiUrl}/login`, {
email: values.email, // Use values from VeeValidate
password: values.password
});
console.log(response);
if (response.data.success) {
alertMessage.value = "Login successful!";
alertColor.value = 'success';
authStore.setUser(response.data.user, response.data.token);
router.push('/dashboard');
} else {
alertMessage.value = response.data.message;
alertColor.value = 'error';
console.error("Login failed:", response.data.message);
}
} catch (error: any) {
alertMessage.value = error.response?.data.message;
alertColor.value = 'error';
console.error("Error during login:", error.response?.data.message || error.message);
} finally {
loadingStore.setLoading(false);
}
};
#### 3. **Update the “ Component**
Pass field values properly via `v-slot="{ values }"` in “:
<Form @submit="submit" class="mt-7 loginForm" v-slot="{ errors, isSubmitting, values }">
<v-text-field
v-model="values.email"
:rules="emailRules"
label="Email Address / Username"
class="mt-4 mb-8"
required
density="comfortable"
hide-details="auto"
variant="outlined"
color="primary"
></v-text-field>
<v-text-field
v-model="values.password"
:rules="passwordRules"
label="Password"
required
density="comfortable"
variant="outlined"
color="primary"
hide-details="auto"
:append-icon="show1 ? '$eye' : '$eyeOff'"
:type="show1 ? 'text' : 'password'"
@click:append="show1 = !show1"
class="pwdInput"
></v-text-field>
<v-btn color="secondary" :loading="isSubmitting" block class="mt-2" variant="flat" size="large" type="submit">
Sign In
</v-btn>
</Form>
#### 4. **Use `valid` Correctly**
The `valid` ref is currently unused, but if you want to disable the submit button when the form is invalid, update it dynamically:
<v-btn color="secondary" :loading="isSubmitting" block class="mt-2" variant="flat" size="large"
:disabled="Object.keys(errors).length > 0" type="submit">
Sign In
</v-btn>
—
### Summary of Fixes:
– **Remove `.prevent`** from `@submit.prevent="submit"`.
– **Modify `submit` function** to accept `values` from VeeValidate.
– **Update “ to use `v-slot="{ values }"`**.
– **Fix button disable logic** using `Object.keys(errors).length > 0`.
Try these fixes, and your issue should be resolved! ๐
### ๐ง Fixes:
1. **Ensure Fields are Registered with `Field` from VeeValidate**
– Instead of using `v-model`, use “ components from VeeValidate to register fields properly.
– This ensures validation is correctly applied before submission.
2. **Ensure `errors` Object is Used Correctly**
– Use `errors.email` and `errors.password` to display validation messages and disable the submit button accordingly.
—
### โ **Updated Code with Proper Validation Handling**
#### **Step 1: Import Required Components**
Modify your script section to include `Field` from VeeValidate:
<script setup lang="ts">
import { ref, inject } from "vue";
import { Form, Field } from 'vee-validate';
import * as yup from 'yup';
import { useAuthStore } from '@/stores/auth';
import { useLoadingStore } from '@/stores/loading';
import { useRouter } from 'vue-router';
import publicApi from '@/publicApi';
const apiUrl = inject('apiUrl');
const loadingStore = useLoadingStore();
const authStore = useAuthStore();
const router = useRouter();
const alertMessage = ref("");
const alertColor = ref("");
/* Validation Schema using Yup */
const validationSchema = yup.object({
email: yup.string().required('E-mail is required').email('E-mail must be valid'),
password: yup.string().required('Password is required').max(10, 'Password must be less than 10 characters'),
});
/* Submit Function */
const submit = async (values: { email: string; password: string }) => {
loadingStore.setLoading(true);
alertMessage.value = "";
alertColor.value = "";
try {
const response = await publicApi.post(`${apiUrl}/login`, {
email: values.email, // Use values from VeeValidate
password: values.password
});
if (response.data.success) {
alertMessage.value = "Login successful!";
alertColor.value = 'success';
authStore.setUser(response.data.user, response.data.token);
router.push('/dashboard');
} else {
alertMessage.value = response.data.message;
alertColor.value = 'error';
}
} catch (error: any) {
alertMessage.value = error.response?.data.message || "Login failed.";
alertColor.value = 'error';
} finally {
loadingStore.setLoading(false);
}
};
</script>
—
#### **Step 2: Update Your “ in the Template**
Now, update your “ to properly use `Field` components from VeeValidate.
<template>
<v-btn block color="primary" variant="outlined" class="text-lightText googleBtn">
<img :src="Google" alt="google" />
<span class="ml-2">Sign in with Google</span>
</v-btn>
<v-row>
<v-col class="d-flex align-center">
<v-divider class="custom-devider" />
<v-btn variant="outlined" class="orbtn" rounded="md" size="small">OR</v-btn>
<v-divider class="custom-devider" />
</v-col>
</v-row>
<h5 class="text-h5 text-center my-4 mb-8">Sign in with Email address</h5>
<Form @submit="submit" :validation-schema="validationSchema" v-slot="{ errors, isSubmitting }" class="mt-7 loginForm">
<!-- Email Input -->
<Field name="email" v-slot="{ field }">
<v-text-field
v-bind="field"
label="Email Address / Username"
class="mt-4 mb-8"
required
density="comfortable"
hide-details="auto"
variant="outlined"
color="primary"
:error-messages="errors.email"
></v-text-field>
</Field>
<!-- Password Input -->
<Field name="password" v-slot="{ field }">
<v-text-field
v-bind="field"
label="Password"
required
density="comfortable"
variant="outlined"
color="primary"
hide-details="auto"
:append-icon="show1 ? '$eye' : '$eyeOff'"
:type="show1 ? 'text' : 'password'"
@click:append="show1 = !show1"
class="pwdInput"
:error-messages="errors.password"
></v-text-field>
</Field>
<!-- Remember Me Checkbox -->
<div class="d-sm-flex align-center mt-2 mb-7 mb-sm-0">
<v-checkbox v-model="checkbox" label="Remember me?" color="primary" class="ms-n2" hide-details></v-checkbox>
<div class="ml-auto">
<a href="javascript:void(0)" class="text-primary text-decoration-none">Forgot password?</a>
</div>
</div>
<!-- Submit Button -->
<v-btn color="secondary" :loading="isSubmitting" block class="mt-2" variant="flat" size="large"
:disabled="Object.keys(errors).length > 0" type="submit">
Sign In
</v-btn>
<!-- Alert Messages -->
<v-alert v-if="alertMessage" :color="alertColor" class="mt-2">
{{ alertMessage }}
</v-alert>
</Form>
<div class="mt-5 text-right">
<v-divider />
<v-btn variant="plain" to="/register" class="mt-2 text-capitalize mr-n2">Don't Have an account?</v-btn>
</div>
</template>
—
### โ
**Why This Works**
โ Uses `Field` components from VeeValidate to manage input values properly.
โ Uses `yup` for schema validation instead of manual rules.
โ Prevents submission when there are validation errors.
โ Displays error messages dynamically under each field.
โ Uses `Object.keys(errors).length > 0` to disable the **Sign In** button if validation fails.
๐ **Now, your form will NOT submit when blank fields are entered, and validation will work correctly!** Let me know if you need further refinements! ๐ฏ