Search code examples
vue.jsrestvee-validatezod

Update Vee Validate after successful submission but API returns bad request


This is my component: SignupButton.vue

<script setup>

import { Form, Field, ErrorMessage } from 'vee-validate';
import { toTypedSchema } from '@vee-validate/zod';
import { z } from 'zod';


const alphaCharsPattern = /^[A-Za-z]+$/;
const keyboardCharsPattern = /^[ -~]+$/;

const validationSchema = toTypedSchema(z.object({
    email: z.string().min(1).email(),
    username: z.string().min(3).regex(alphaCharsPattern, {
        message: "Username may only contain alphabetic characters"
    }),
    password: z.string().min(8).regex(keyboardCharsPattern, {
        message: "Password may only contain keyboard printable characters"
    })
}));

const submitHandler = async (formValues) => {
    const response = await fetch('http://localhost:8000/register', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify(formValues),
        mode: "cors"
    });

    try {
        if (!response.ok) {
            throw new Error('Network response was not ok');
        }
        
        const data = await response.json();
        console.log(data);

        alert("Form Submitted!");
    } catch (error) {
        console.error("Error fetching data: ", error);
    }
}

</script>
<template>
    <Form :validation-schema="validationSchema" @submit="submitHandler">
        <Field type="text" name="email" />
        <ErrorMessage name="email" />

        <Field type="text" name="username" />
        <ErrorMessage name="username" />

        <Field type="password" name="password" />
        <ErrorMessage name="password" />
        
        <button>Submit</button>
    </Form>
</template>

Currently, it will validate an email-username-password and then send this to the submitHandler. This function will send a fetch request to my backend then await the response. If the response is ok, data will be logged (just prints a small object), and the user will get an alert. Otherwise, an error will be thrown and caught where it will be logged.

What I wish to do is instead of logging the error, I want to communicate to VeeValidate that there's a new error. This error is commonly going to be "user, someRandomUserName, already exists." I would want to send some VeeValidate error message for the username field.

I looked into a similar question but it had but one response

I know there are some ways to get this desired behavior with useForm but I like the structure of components.

How can I achieve this desired behavior? Should I make a pre-submit function and a new API view that checks if the username already exists?


Solution

  • I believe you can use setFieldError or setErrors from Form component Slot.

    example: <Form :validation-schema="validationSchema" @submit="submitHandler" v-slot="{ setErrors }">. and you can pass those function to submitHandler.

    for me it's more simpler if you use useForm() hooks instead of Component