id | title |
---|---|
useModalForm |
useModalForm |
import createGif from '@site/static/img/guides-and-concepts/hooks/useModalForm/create.gif'; import editGif from '@site/static/img/guides-and-concepts/hooks/useModalForm/edit.gif';
useModalForm
hook allows you manage a form within a modal. It returns Ant Design Form and Modal components props.
const { modalProps, formProps } = useModalForm<IPost>();
All we have to do is to pass the modalProps
to <Modal>
and formProps
to <Form>
components.
We'll do two examples, one for creating a post and one for editing a post. Let's see how useModalForm
is used in both.
For example, let's look at an example of creating a record with useModalForm
.
import { useModalForm, Modal, Form, Create, Radio } from "@pankod/refine";
import { IPost } from "interfaces";
export const PostList: React.FC () => {
//highlight-start
const {
modalProps,
formProps,
show,
saveButtonProps,
} = useModalForm<IPost>({
action: "create",
});
//highlight-end
return (
<>
<List
//highlight-start
createButtonProps={{
onClick: () => {
show();
},
}}
//highlight-end
>
...
</List>
//highlight-start
<Modal {...modalProps}>
<Create saveButtonProps={saveButtonProps}>
<Form {...formProps} layout="vertical">
<Form.Item label="Title" name="title">
<Input />
</Form.Item>
<Form.Item label="Status" name="status">
<Radio.Group>
<Radio value="draft">Draft</Radio>
<Radio value="published">Published</Radio>
<Radio value="rejected">Rejected</Radio>
</Radio.Group>
</Form.Item>
</Form>
</Create>
</Modal>
//highlight-end
</>
)
}
export interface IPost {
id: string;
title: string;
status: "published" | "draft" | "rejected";
}
createButtonProps
allows creating and managing a button above the table.
createButtonProps={{
onClick: () => {
show();
},
}}
This code block makes <Modal>
appear when you click the button.
saveButtonProps
allows us to manage save button in the modal.
Let's learn how to add editing capability to records that will be opening form in Modal with using action
prop.
import { useModalForm, Modal, Form, Create, Radio } from "@pankod/refine";
import { IPost } from "interfaces";
export const PostList () => {
const {
modalProps,
formProps,
show,
saveButtonProps,
//highlight-start
deleteButtonProps,
editId,
//highlight-end
} = useModalForm<IPost>({
//highlight-next-line
action: "edit",
});
return (
<>
<List>
<Table>
...
<Table.Column<IPost>
title="Actions"
dataIndex="actions"
key="actions"
render={(_value, record) => (
//highlight-start
<EditButton onClick={() => show(record.id)} />
//highlight-end
)}
/>
</Table>
</List>
<Modal {...modalProps}>
//highlight-next-line
<Edit
saveButtonProps={saveButtonProps}
//highlight-start
deleteButtonProps={deleteButtonProps}
recordItemId={editId}
//highlight-end
>
<Form {...formProps} layout="vertical">
<Form.Item label="Title" name="title">
<Input />
</Form.Item>
<Form.Item label="Status" name="status">
<Radio.Group>
<Radio value="draft">Draft</Radio>
<Radio value="published">Published</Radio>
<Radio value="rejected">Rejected</Radio>
</Radio.Group>
</Form.Item>
</Form>
</Edit>
</Modal>
</>
)
}
The saveButtonProps
and deleteButtonProps
can provides functionality to save and delete buttons in the modal.
:::important
refine doesn't automatically add a edit button by default to the each record in <PostList>
which opens edit form in <Modal>
when clicking.
So, we put the edit buttons on our list. In that way, <Edit>
form in <Modal>
can fetch data by record id
.
<Table.Column<IPost>
title="Actions"
dataIndex="actions"
key="actions"
render={(_value, record) => <EditButton onClick={() => show(record.id)} />}
/>
:::
:::caution
Don't forget to pass the record id to show
to fetch the record data. This is necessary for both edit and clone forms.
:::
Refer to codesandbox example for detailed usage. →
Key | Description | Type | Default |
---|---|---|---|
action Required |
Type of form mode | "edit" | "create" |
"create" |
autoSubmitClose | Close modal after submit | boolean |
|
form | Ant Design form instance | FormInstance<TVariables> |
|
mutationMode | Determines when mutations are executed. If not explicitly configured, it is read from the mutation mode config of the resource in current route | "pessimistic" | "optimistic" | "undoable" |
|
onMutationError | Called when mutation encounters an error | (error: TError, variables: TVariables, context: any) => void |
|
onMutationSuccess | Called when mutation is successful | (data: TData, variables: TVariables, context: any) => void |
|
redirect | Page to redirect after succesfull mutation | "show | "edit | "list" ** |
|
submit | Submit the form | (values?: TVariables) => Promise<TData> |
|
submitOnEnter | Listen Enter key press to submit form |
boolean |
false |
undoableTimeout | Duration to wait before executing mutations when mutationMode = "undoable" |
number |
5000 * |
warnWhenUnsavedChanges | Shows notification when unsaved changes exist | boolean |
false * |
*
: These props have default values inAdminContext
and can also be set on <Admin> component.useModalForm
will use what is passed to<Admin>
as default and can override locally.
**
: If not explicitly configured, default value ofredirect
depends whichaction
used. Ifaction
iscreate
,redirect
s default value isedit
(created resources edit page). Otherwise ifaction
isedit
,redirect
s default value islist
.
Key | Description | Type |
---|---|---|
show | A function that can open the modal | (id?: string) => void |
formProps | Ant Design form props | FormProps |
modalProps | Props for managed modal | ModalProps |
saveButtonProps | Props for a submit button | { disabled: boolean; onClick: () => void; loading: boolean; } |
deleteButtonProps | Adds props for delete button | DeleteButtonProps |
formLoading | Loading status of form | boolean |
submit | Submit method, the parameter is the value of the form fields | () => void |
visible | Whether the modal dialog is visible or not | boolean |
close | Specify a function that can close the modal | () => void |
defaultFormValuesLoading | DefaultFormValues loading status of form | boolean |
form | Ant Design form instance | FormInstance<TVariables> |
editId | Record id for edit action | string |
setEditId | editId setter |
Dispatch<SetStateAction< string | undefined>> |
queryResult | Result of the query of a record | QueryObserverResult<{ data: TData }> |
mutationResult | Result of the mutation triggered by submitting the form | UseMutationResult< { data: TData }, TError, { resource: string; values: TVariables; }, unknown> |
setCloneId | cloneId setter |
Dispatch<SetStateAction< string | undefined>> |
cloneId | Record id for clone action | string |