Server Validation only pickups the message but not each error
I'm using the simple rest data provider and I want to do server validation on create/update, but the errors are not shown in the form, just a generic "There was an error creating device (status code: 400)" the message sent from the server is there in the notification but the fields are not marked as error. this is the response I'm sending when validation fails on the server.
8 Replies
Hi @xxmelonxx. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
----------------------
To ensure that server-side validation errors are properly displayed in your form fields when using the simple REST data provider in Refine, you need to make sure that the error response from the server matches the
HttpError
interface expected by Refine's useForm
.
Here is an example of how to set up the data provider and handle server-side validation errors:
1. Define the HttpError
Interface:
Ensure that your error response matches the HttpError
interface. The errors
field should contain the specific field errors.
2. Set Up the Data Provider:
Customize your data provider to return the error response in the correct format. Here is an example:
3. Handle Errors in the Form:
Use the useForm
hook to handle the form submission and error propagation. Here is an example of how to set up the form:
```typescript
import { useForm } from "@refinedev/core";
const MyFormComponent = () => {
const {
mutationResult: { error },
formLoading,
onFinish,
} = useForm();
const { errors } = error ?? {};
return (
<div style={{ position: "relative" }}>
<form onSubmit={(event) => {
event.preventDefault();
const formData = new FormData(event.currentTarget);
const variables = Object.fromEntries(formData.entries());
onFinish(variables).catch(() => {})
}} style={{ display: "flex", flexDirection: "column", gap: "12px" }}>
<label>
<span>Name</span>
<input type="text" id="name" name="name" />
</label>
<span style={{ color: "red" }}>{errors?.name ?? ""}</span>
<label>
<span>Material</span>
<input type="text" id="material" name="material" />
</label>
<span style={{ color: "red" }}>{errors?.material ?? ""}</span>
<label>
<span>Description</span>
<textarea id="description" name="description" />
</label>
<span style={{ color: "red" }}>{errors?.description ?? ""}</span>
<button type="submit">Save</button>
</form>
{formLoading && (<div style={{
position: "absolute",
inset: 0,
width: "100%",
height: "100%",
display: "flex",
alignItems: "center",
justifyContent: "center",
backgroundColor: "rgba(255, 255, 255, 0.5)",
color: "#000",
}}>loading...</div>)}
</div>
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------<@833526940967108638> kapa.ai is still learning and improving, please let us know how it did by reacting below
deep-jade•4mo ago
@kapa.ai I'm already returning the expected Interface, but is not picking up the errors just the message
Let me check the knowledge base for you. One moment! :books:
----------------------
If you are already returning the expected
HttpError
interface but the errors are not being picked up by the form fields, you might need to ensure that the useForm
hook is correctly set up to handle and propagate these errors. Here’s a step-by-step guide to ensure everything is configured correctly:
1. Ensure Error Format:
Make sure your server response matches the HttpError
interface exactly. Here’s an example of the expected format:
2. Set Up the Data Provider:
Ensure your data provider is correctly set up to return this error format. Here’s an example:
3. Handle Errors in the Form:
Use the useForm
hook to handle the form submission and error propagation. Here’s an example of how to set up the form:
```typescript
import { useForm } from "@refinedev/react-hook-form";
import { Create } from "@refinedev/chakra-ui";
import {
FormControl,
FormErrorMessage,
FormLabel,
Input,
Textarea,
} from "@chakra-ui/react";
export const ProductCreate = () => {
const {
refineCore: { formLoading },
saveButtonProps,
register,
formState: { errors },
} = useForm();
return (
<Create saveButtonProps={saveButtonProps}>
<FormControl mb="3" isInvalid={!!errors?.ip}>
<FormLabel>IP</FormLabel>
<Input
id="ip"
type="text"
{...register("ip", { required: "IP is required" })}
/>
<FormErrorMessage>
{errors.ip?.message}
</FormErrorMessage>
</FormControl>
<FormControl mb="3" isInvalid={!!errors?.title}>
<FormLabel>Title</FormLabel>
<Input
id="title"
type="text"
{...register("title", { required: "Title is required" })}
/>
<FormErrorMessage>
{errors.title?.message}
</FormErrorMessage>
</FormControl>
<FormControl mb="3" isInvalid={!!errors?.description}>
<FormLabel>Description</FormLabel>
<Textarea
id="description"
{...register("description", { required: "Description is required" })}
/>
<FormErrorMessage>
{errors.description?.message}
</FormErrorMessage>
</FormControl>
<FormControl mb="3" isInvalid={!!errors?.price}>
<FormLabel>Price</FormLabel>
<Input
id="price"
type="number"
{...register("price", { required: "Price is required" })}
/>
<FormErrorMessage>
{errors.price?.message}
</FormErrorMessage>
</FormControl>
</Create>
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------<@833526940967108638> kapa.ai is still learning and improving, please let us know how it did by reacting below
deep-jade•4mo ago
@kapa.ai if I use the Promise.reject it works as expected, but the request will not go to the server obviously, the response from the server is the same as the interface but I'm getting an AxiosError which includes the request/response witht he expected data
Let me check the knowledge base for you. One moment! :books:
----------------------
To handle server-side validation errors properly when using Axios with Refine, you need to ensure that the error response from the server is transformed to match the
HttpError
interface expected by Refine. This can be done using Axios interceptors to transform the error before it is returned to your code.
Here’s how you can set up Axios interceptors to handle and transform the error response:
1. Set Up Axios Interceptors:
Use Axios interceptors to transform the error response to match the HttpError
interface.
2. Handle Errors in the Form:
Use the useForm
hook to handle the form submission and error propagation. Here’s an example of how to set up the form:
```typescript
import { useForm } from "@refinedev/react-hook-form";
import { Create } from "@refinedev/chakra-ui";
import {
FormControl,
FormErrorMessage,
FormLabel,
Input,
Textarea,
} from "@chakra-ui/react";
export const ProductCreate = () => {
const {
refineCore: { formLoading },
saveButtonProps,
register,
formState: { errors },
} = useForm();
return (
<Create saveButtonProps={saveButtonProps}>
<FormControl mb="3" isInvalid={!!errors?.ip}>
<FormLabel>IP</FormLabel>
<Input
id="ip"
type="text"
{...register("ip", { required: "IP is required" })}
/>
<FormErrorMessage>
{errors.ip?.message}
</FormErrorMessage>
</FormControl>
<FormControl mb="3" isInvalid={!!errors?.title}>
<FormLabel>Title</FormLabel>
<Input
id="title"
type="text"
{...register("title", { required: "Title is required" })}
/>
<FormErrorMessage>
{errors.title?.message}
</FormErrorMessage>
</FormControl>
<FormControl mb="3" isInvalid={!!errors?.description}>
<FormLabel>Description</FormLabel>
<Textarea
id="description"
{...register("description", { required: "Description is required" })}
/>
<FormErrorMessage>
{errors.description?.message}
</FormErrorMessage>
</FormControl>
<FormControl mb="3" isInvalid={!!errors?.price}>
<FormLabel>Price</FormLabel>
<Input
id="
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------<@833526940967108638> kapa.ai is still learning and improving, please let us know how it did by reacting below