Vue OTP Password Reset
March 11, 2025 · AI Conversations
<script>
import { ref, inject, onMounted } from "vue";
import { useForm, useField } from "vee-validate";
import { useAuthStore } from "@/stores/auth";
import { useRouter } from "vue-router";
import publicApi from "@/publicApi";
import SingleColumn from "@/layouts/SingleColumn.vue";
const authStore = useAuthStore();
const router = useRouter();
const apiUrl = inject<string>("apiUrl");
const showPassword = ref(false);
const alertMessage = ref("");
const alertColor = ref("");
const step = ref(1);
const loading = ref(false);
const otp = ref("");
const items = ["Forget Password", "Reset Password"];
onMounted(() => {
if (authStore.isAuthenticated) {
router.push("/dashboard"); // Redirect if already logged in
}
});
// **Email Form Validation**
const { handleSubmit, handleReset } = useForm({
validationSchema: {
email(value: string) {
return /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$/i.test(value) || "Must be a valid e-mail.";
},
},
});
const email = useField("email");
const password = useField("password");
const confirmPassword = useField("confirmPassword");
// **Submit Forgot Password**
const submit = handleSubmit(async (values) => {
loading.value = true;
alertMessage.value = "";
alertColor.value = "";
try {
const response = await publicApi.post(`${apiUrl}/send-otp-password`, {
email: values.email,
});
loading.value = false;
if (response.data.success) {
alertMessage.value = "OTP has been sent successfully!";
alertColor.value = "success";
step.value = 2;
} else {
alertMessage.value = response.data.message;
alertColor.value = "error";
}
} catch (error: any) {
loading.value = false;
alertMessage.value = error.response?.data.message || "Error sending OTP.";
alertColor.value = "error";
}
});
</script>
Forget Password
Submit
Clear
Verify Your Account
We sent a verification code to {{ email.value.value || "your email" }}.
Please check your email and paste the code below.
Verify
Didn't receive the code? Resend
also add password and conform password in second step with otp and
<script>
nimport { ref, inject, onMounted } from "vue";nimport { useForm, useField } from "vee-validate";nimport { useAuthStore } from "@/stores/auth";nimport { useRouter } from "vue-router";nimport publicApi from "@/publicApi";nimport SingleColumn from "@/layouts/SingleColumn.vue";nnconst authStore = useAuthStore();nconst router = useRouter();nconst apiUrl = inject<string>("apiUrl");nnconst showPassword = ref(false);nconst alertMessage = ref("");nconst alertColor = ref("");nconst step = ref(1);nconst loading = ref(false);nconst otp = ref("");nnconst items = ["Forget Password", "Reset Password"];nnonMounted(() => {n if (authStore.isAuthenticated) {n router.push("/dashboard"); // Redirect if already logged inn }n});nn// **Email Form Validation**nconst { handleSubmit, handleReset } = useForm({n validationSchema: {n email(value: string) {n return /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/i.test(value) || "Must be a valid e-mail.";n },n },n});nconst email = useField("email");nn// **Password Reset Form Validation**nconst { handleSubmit: handleResetSubmit } = useForm({n validationSchema: {n password(value: string) {n return value.length >= 6 || "Password must be at least 6 characters long.";n },n confirmPassword(value: string) {n return value === password.value.value || "Passwords do not match.";n },n otp(value: string) {n return value.length === 6 || "OTP must be 6 digits.";n },n },n});nnconst password = useField("password");nconst confirmPassword = useField("confirmPassword");nconst otpField = useField("otp");nn// **Submit Forgot Password**nconst submit = handleSubmit(async (values) => {n loading.value = true;n alertMessage.value = "";n alertColor.value = "";nn try {n const response = await publicApi.post(`${apiUrl}/send-otp-password`, {n email: values.email,n });nn loading.value = false;n if (response.data.success) {n alertMessage.value = "OTP has been sent successfully!";n alertColor.value = "success";n step.value = 2;n } else {n alertMessage.value = response.data.message;n alertColor.value = "error";n }n } catch (error: any) {n loading.value = false;n alertMessage.value = error.response?.data.message || "Error sending OTP.";n alertColor.value = "error";n }n});nn// **Submit OTP and Reset Password**nconst resetPassword = handleResetSubmit(async (values) => {n loading.value = true;n alertMessage.value = "";n alertColor.value = "";nn try {n const response = await publicApi.post(`${apiUrl}/reset-password`, {n email: email.value.value,n otp: values.otp,n password: values.password,n confirmPassword: values.confirmPassword,n });nn loading.value = false;n if (response.data.success) {n alertMessage.value = "Password reset successfully!";n alertColor.value = "success";n router.push("/login");n } else {n alertMessage.value = response.data.message;n alertColor.value = "error";n }n } catch (error: any) {n loading.value = false;n alertMessage.value = error.response?.data.message || "Error resetting password.";n alertColor.value = "error";n }n});n
</script>
nnn n nn n n n n Forget Passwordnn n n nn Submit n Clear n n n n nn n n n Verify Your Accountnn n We sent a verification code to {{ email.value.value || "your email" }}. n Please check your email and paste the code below.n nn n n n {{ otpField.errorMessage.value }}n n nn nn n Verifyn n n n n n nn n n"}
– Step 1: Email submission for OTP
– Step 2: OTP verification along with password reset fields
– Validation for email, OTP, and password fields
– Dynamic alert messages and loading states
Let me know if you need any modifications! 🚀
at password (ForgetPasswordView.vue:43:20)
### ✅ Fix:
Make sure you're properly handling `password` and `confirmPassword` fields.
#### **1️⃣ Correct way to initialize fields:**
Modify how you're defining `password` and `confirmPassword` using `useField`. Update your script to ensure that they are initialized properly:
const password = useField<string>("password");
const confirmPassword = useField<string>("confirmPassword");
Then, update your bindings:
<v-text-field
v-model="password.value.value"
:error-messages="password.errorMessage.value"
label="Password"
></v-text-field>
<v-text-field
v-model="confirmPassword.value.value"
:error-messages="confirmPassword.errorMessage.value"
label="Confirm Password"
></v-text-field>
—
#### **2️⃣ Check for `undefined` before using `.length`**
If you’re using `.length` on `password.value.value`, make sure to check if it's defined:
if (password.value.value && password.value.value.length < 8) {
alertMessage.value = "Password must be at least 8 characters.";
}
—
#### **3️⃣ Ensure you have the validation schema for password**
If you're using `validationSchema`, add password validation:
const { handleSubmit } = useForm({
validationSchema: {
email(value: string) {
return /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$/i.test(value) || "Must be a valid email.";
},
password(value: string) {
return value?.length >= 8 || "Password must be at least 8 characters.";
},
confirmPassword(value: string) {
return value === password.value.value || "Passwords must match.";
}
}
});
This should resolve the **TypeError**. Let me know if you need more help! 🚀