rival-black
rival-black3mo ago

How can I change data before initializing the form in Edit scenario

Hello, I am currently switching from react-admin and I am loving Refine so far. I am looking to the the reverse of "How can I change the form data before submitting it to the API" which is shown here. https://refine.dev/docs/packages/react-hook-form/use-form/#how-can-i-change-the-form-data-before-submitting-it-to-the-api In Edit scenario, (I am using Edit from @refinedev/mui), my API is returning a field called dueDate which is string but I have to turn it into a Dayjs to to initialize the DatePicker properly. Also, there might be other cases for transforming the data coming from the API before the form can be initialized. Any pointers will be appreciated.
useForm | Refine
useForm is used to manage forms. It returns the necessary properties and methods to control the element. It has been developed by using useForm imported from the @refinedev/core package.
11 Replies
kapa.ai
kapa.ai3mo ago
Hi @Milan Nankov. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- I'm glad to hear that you're enjoying using Refine! To transform the data coming from the API before initializing the form, you can use the onSuccess callback of the useForm hook. This callback is called after the data is fetched from the API and before the form is initialized. You can modify the data in this callback. Here's an example of how you can do this:
import { Edit, useForm } from "@refinedev/mui";
import { DatePicker } from "@material-ui/pickers";
import dayjs from "dayjs";

export const PostEdit: React.FC = () => {
const { formProps, saveButtonProps } = useForm({
resource: "posts",
id: "1",
onSuccess: (data) => {
return {
...data,
dueDate: dayjs(data.dueDate),
};
},
});

return (
<Edit saveButtonProps={saveButtonProps}>
<DatePicker
{...formProps.getFieldProps("dueDate")}
label="Due Date"
format="DD/MM/YYYY"
/>
</Edit>
);
};
import { Edit, useForm } from "@refinedev/mui";
import { DatePicker } from "@material-ui/pickers";
import dayjs from "dayjs";

export const PostEdit: React.FC = () => {
const { formProps, saveButtonProps } = useForm({
resource: "posts",
id: "1",
onSuccess: (data) => {
return {
...data,
dueDate: dayjs(data.dueDate),
};
},
});

return (
<Edit saveButtonProps={saveButtonProps}>
<DatePicker
{...formProps.getFieldProps("dueDate")}
label="Due Date"
format="DD/MM/YYYY"
/>
</Edit>
);
};
In this example, the onSuccess callback is used to convert the dueDate field from a string to a Dayjs object before initializing the form. Please note that this is a hypothetical example and the actual implementation may vary based on your specific use case and the structure of your data. Unfortunately, I couldn't find a direct link in the provided knowledge sources that explains this. However, you can refer to the Refine documentation (https://refine.dev/docs) for more information on how to use the useForm hook and other features of Refine. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@1153414607545839696> kapa.ai is still learning and improving, please let us know how it did by reacting below
rival-black
rival-black3mo ago
On success does not seem to exist on useForm. @kapa.ai On success does not seem to exist on useForm.
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- I apologize for the confusion. You're correct, the onSuccess callback does not exist on the useForm hook in Refine. I made an error in my previous response. In Refine, the useForm hook provides onMutationSuccess and onLiveEvent callbacks, but these are triggered after a mutation (like a form submission) or when new events from a subscription arrive, respectively. They are not designed to modify data before form initialization. Currently, Refine does not provide a built-in way to modify the data before initializing the form in the useForm hook. You might need to fetch the data separately using useGet or useQuery, modify the data as needed, and then pass it to the form. I'm sorry for the inconvenience. I recommend checking the Refine documentation (https://refine.dev/docs) for more information on how to use the hooks and other features of Refine. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@1153414607545839696> kapa.ai is still learning and improving, please let us know how it did by reacting below
rival-black
rival-black3mo ago
@kapa.ai How can I do that using useGet to setup my edit form?
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- Sure, you can use the useGet hook to fetch the data, modify it as needed, and then initialize the form with the modified data. Here's an example of how you can do this:
import { useGet } from "@refinedev/react-query";
import { Edit, useForm } from "@refinedev/mui";
import { DatePicker } from "@material-ui/pickers";
import dayjs from "dayjs";
import { useEffect } from "react";

export const PostEdit: React.FC = () => {
const { data: apiData } = useGet({
resource: "posts",
id: "1",
});

const {
form,
formProps,
saveButtonProps,
} = useForm({
resource: "posts",
id: "1",
initialValues: {
...apiData,
dueDate: dayjs(apiData?.dueDate),
},
});

useEffect(() => {
if (apiData) {
form.reset({
...apiData,
dueDate: dayjs(apiData.dueDate),
});
}
}, [apiData, form]);

return (
<Edit saveButtonProps={saveButtonProps}>
<DatePicker
{...formProps.getFieldProps("dueDate")}
label="Due Date"
format="DD/MM/YYYY"
/>
</Edit>
);
};
import { useGet } from "@refinedev/react-query";
import { Edit, useForm } from "@refinedev/mui";
import { DatePicker } from "@material-ui/pickers";
import dayjs from "dayjs";
import { useEffect } from "react";

export const PostEdit: React.FC = () => {
const { data: apiData } = useGet({
resource: "posts",
id: "1",
});

const {
form,
formProps,
saveButtonProps,
} = useForm({
resource: "posts",
id: "1",
initialValues: {
...apiData,
dueDate: dayjs(apiData?.dueDate),
},
});

useEffect(() => {
if (apiData) {
form.reset({
...apiData,
dueDate: dayjs(apiData.dueDate),
});
}
}, [apiData, form]);

return (
<Edit saveButtonProps={saveButtonProps}>
<DatePicker
{...formProps.getFieldProps("dueDate")}
label="Due Date"
format="DD/MM/YYYY"
/>
</Edit>
);
};
In this example, the useGet hook is used to fetch the data. The useEffect hook is then used to reset the form with the modified data when the fetched data changes. The form.reset method is used to set the initial values of the form. Please note that this is a hypothetical example and the actual implementation may vary based on your specific use case and the structure of your data. Unfortunately, I couldn't find a direct link in the provided knowledge sources that explains this. However, you can refer to the Refine documentation (https://refine.dev/docs) for more information on how to use the useGet hook and other features of Refine. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@1153414607545839696> kapa.ai is still learning and improving, please let us know how it did by reacting below
rival-black
rival-black3mo ago
@kapa.ai Is there a callback that I can use to determine when useForm has fetched the record being edited from my API when in Edit scenario?
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- In the useForm hook of Refine, there isn't a direct callback that gets triggered when the record being edited is fetched from the API. However, you can use the queryResult returned by useForm to determine the loading state of the data fetch operation. The queryResult object contains a isLoading property that indicates whether the data is currently being fetched. You can use this property to determine when the data has been fetched. Here's an example:
import { useForm } from "@pankod/refine";

const { queryResult } = useForm({
resource: "posts",
id: "1",
});

console.log(queryResult.isLoading); // true when data is being fetched, false otherwise
import { useForm } from "@pankod/refine";

const { queryResult } = useForm({
resource: "posts",
id: "1",
});

console.log(queryResult.isLoading); // true when data is being fetched, false otherwise
In this example, queryResult.isLoading will be true while the data is being fetched and false once the data has been fetched. Please note that this is a hypothetical example and the actual implementation may vary based on your specific use case. For more information, you can refer to the Refine documentation (https://refine.dev/docs/packages/react-hook-form/use-form#formloading) on the useForm hook. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@1153414607545839696> kapa.ai is still learning and improving, please let us know how it did by reacting below