Skip to main content
🧙‍♂️ refine grants your wishes! Please give us a ⭐️ on GitHub to keep the magic going.
Version: 4.xx.xx

useDrawerForm

The useDrawerForm hook allows you to manage a form within a Drawer. It returns the Ant Design <Form> and <Drawer> components props.

INFORMATION

TheuseDrawerForm hook is extended from useForm from the @refinedev/antd package. This means that you can use all the features of useForm hook with it.

Basic Usage

We will show two examples, one for creating a post and one for editing it. Let's see how useDrwaerForm is used in them.

In this example, we will show you how to "create" a record with useDrawerForm:

localhost:3000/posts
import { HttpError } from "@refinedev/core";
import React from "react";

import { Create, List, useDrawerForm, useTable } from "@refinedev/antd";
import { Drawer, Form, Input, Select, Table } from "antd";

interface IPost {
id: number;
title: string;
status: "published" | "draft" | "rejected";
}

const PostList: React.FC = () => {
const { tableProps } = useTable<IPost, HttpError>();

const { formProps, drawerProps, show, saveButtonProps } = useDrawerForm<
IPost,
HttpError,
IPost
>({
action: "create",
});

return (
<>
<List
canCreate
createButtonProps={{
onClick: () => {
show();
},
}}
>
<Table {...tableProps} rowKey="id">
<Table.Column dataIndex="id" title="ID" />
<Table.Column dataIndex="title" title="Title" />
</Table>
</List>
<Drawer {...drawerProps}>
<Create saveButtonProps={saveButtonProps}>
<Form {...formProps} layout="vertical">
<Form.Item
label="Title"
name="title"
rules={[
{
required: true,
},
]}
>
<Input />
</Form.Item>
<Form.Item
label="Status"
name="status"
rules={[
{
required: true,
},
]}
>
<Select
options={[
{
label: "Published",
value: "published",
},
{
label: "Draft",
value: "draft",
},
{
label: "Rejected",
value: "rejected",
},
]}
/>
</Form.Item>
</Form>
</Create>
</Drawer>
</>
);
};

Properties

TIP

All useForm props are also available in useDrawerForm. You can find descriptions on the useForm documentation.

syncWithLocation

When syncWithLocation is true, the drawers visibility state and the id of the record will be synced with the URL. It is false by default.

This property can also be set as an object { key: string; syncId?: boolean } to customize the key of the URL query parameter. id will be synced with the URL only if syncId is true.

const drawerForm = useDrawerForm({
syncWithLocation: { key: "my-modal", syncId: true },
});

overtimeOptions

If you want loading overtime for the request, you can pass the overtimeOptions prop to the this hook. It is useful when you want to show a loading indicator when the request takes too long. interval is the time interval in milliseconds. onInterval is the function that will be called on each interval.

Return overtime object from this hook. elapsedTime is the elapsed time in milliseconds. It becomes undefined when the request is completed.

const { overtime } = useDrawerForm({
//...
overtimeOptions: {
interval: 1000,
onInterval(elapsedInterval) {
console.log(elapsedInterval);
},
},
});

console.log(overtime.elapsedTime); // undefined, 1000, 2000, 3000 4000, ...

// You can use it like this:
{
elapsedTime >= 4000 && <div>this takes a bit longer than expected</div>;
}

autoSave

If you want to save the form automatically after some delay when user edits the form, you can pass true to autoSave.enabled prop.

By default the autoSave feature does not invalidate queries. However, you can use the invalidateOnUnmount and invalidateOnClose props to invalidate queries upon unmount or close.

It also supports onMutationSuccess and onMutationError callback functions. You can use isAutoSave parameter to determine whether the mutation is triggered by autoSave or not.

CAUTION

autoSave feature operates exclusively in edit mode. Users can take advantage of this feature while editing data, as changes are automatically saved in editing mode. However, when creating new data, manual saving is still required.

onMutationSuccess and onMutationError callbacks will be called after the mutation is successful or failed.

enabled

Default: false

To enable the autoSave feature, set the enabled parameter to true.

useDrawerForm({
autoSave: {
enabled: true,
},
});

debounce

Default: 1000

Set the debounce time for the autoSave prop.

useDrawerForm({
autoSave: {
enabled: true,
debounce: 2000,
},
});

onFinish

If you want to modify the data before sending it to the server, you can use onFinish callback function.

useDrawerForm({
autoSave: {
enabled: true,
onFinish: (values) => {
return {
foo: "bar",
...values,
};
},
},
});

invalidateOnUnmount

Default: false

This prop is useful when you want to invalidate the list, many and detail queries from the current resource when the hook is unmounted. By default, it invalidates the list, many and detail queries associated with the current resource. Also, You can use the invalidates prop to select which queries to invalidate.

useDrawerForm({
autoSave: {
enabled: true,
invalidateOnUnmount: true,
},
});

invalidateOnClose

Default: false

This prop is useful when you want to invalidate the list, many and detail queries from the current resource when the drawer is closed. By default, it invalidates the list, many and detail queries associated with the current resource. Also, You can use the invalidates prop to select which queries to invalidate.

useDrawerForm({
autoSave: {
enabled: true,
invalidateOnClose: true,
},
});

Return values

show

A function that opens the <Drawer>. It takes an optional id parameter. If id is provided, it will fetch the record data and fill the <Form> with it.

close

A function that closes the <Drawer>. Same as [onClose][#onClose].

saveButtonProps

It contains the props needed by the "submit" button within the <Drawer> (disabled,loading etc.). When saveButtonProps.onClick is called, it triggers form.submit(). You can manually pass these props to your custom button.

deleteButtonProps

It contains the props needed by the "delete" button within the <Drawer> (disabled,loading etc.). When deleteButtonProps.onSuccess is called, it triggers it sets id to undefined and open to false. You can manually pass these props to your custom button.

formProps

It's required to manage <Form> state and actions. Under the hood the formProps came from useForm.

It contains the props to manage the Antd <Form> component such as onValuesChange, initialValues, onFieldsChange, onFinish etc.

drawerProps

It's required to manage <Drawer> state and actions.

width

Default: "500px"

It's the width of the <Drawer>.

onClose

A function that can close the <Drawer>. It's useful when you want to close the <Drawer> manually. When warnWhenUnsavedChanges is true, it will show a confirmation modal before closing the <Drawer>. If you override this function, you have to handle this confirmation modal manually.

open

Default: false

Current visible state of <Drawer>.

forceRender

Default: true

It renders <Drawer> instead of lazy rendering it.

overtime

overtime object is returned from this hook. elapsedTime is the elapsed time in milliseconds. It becomes undefined when the request is completed.

const { overtime } = useDrawerForm();

console.log(overtime.elapsedTime); // undefined, 1000, 2000, 3000 4000, ...

autoSaveProps

If autoSave is enabled, this hook returns autoSaveProps object with data, error, and status properties from mutation.

FAQ

How can I change the form data before submitting it to the API?

You may need to modify the form data before it is sent to the API.

For example, Let's send the values we received from the user in two separate inputs, name and surname, to the API as fullName.

pages/user/create.tsx
import { Create, Drawer, useDrawerForm } from "@refinedev/antd";
import { Form, Input } from "antd";
import React from "react";

export const UserCreate: React.FC = () => {
const { formProps, drawerProps, saveButtonProps } = useDrawerForm({
action: "create",
});

const handleOnFinish = (values) => {
formProps.onFinish?.({
fullName: `${values.name} ${values.surname}`,
});
};

return (
<Drawer {...drawerProps}>
<Create saveButtonProps={saveButtonProps}>
<Form
{...formProps}
onFinish={handleOnFinish}
layout="vertical"
>
<Form.Item label="Name" name="name">
<Input />
</Form.Item>
<Form.Item label="Surname" name="surname">
<Input />
</Form.Item>
</Form>
</Create>
</Drawer>
);
};

API Parameters

Properties

*: These props have default values in RefineContext and can also be set on <Refine> component. useDrawerForm will use what is passed to <Refine> as default but a local value will override it.

**: If not explicitly configured, default value of redirect depends which action used. If action is create, redirects default value is edit (created resources edit page). Otherwise if action is edit, redirects default value is list.

Type Parameters

PropertyDesriptionTypeDefault
TQueryFnDataResult data returned by the query function. Extends BaseRecordBaseRecordBaseRecord
TErrorCustom error object that extends HttpErrorHttpErrorHttpError
TVariablesValues for params.{}
TDataResult data returned by the select function. Extends BaseRecord. If not specified, the value of TQueryFnData will be used as the default value.BaseRecordTQueryFnData
TResponseResult data returned by the mutation function. Extends BaseRecord. If not specified, the value of TData will be used as the default value.BaseRecordTData
TResponseErrorCustom error object that extends HttpError. If not specified, the value of TError will be used as the default value.HttpErrorTError

Return Value

KeyDescriptionType
showA function that opens the drawer(id?: BaseKey) => void
formAnt Design form instanceFormInstance<TVariables>
formPropsAnt Design form propsFormProps
drawerPropsProps for managed drawerDrawerProps
saveButtonPropsProps for a submit button{ disabled: boolean; onClick: () => void; loading: boolean; }
deleteButtonPropsAdds props for delete buttonDeleteButtonProps
submitSubmit method, the parameter is the value of the form fields() => void
openWhether the drawer is open or notboolean
closeSpecify a function that can close the drawer() => void
overtimeOvertime loading props{ elapsedTime?: number }
autoSavePropsAuto save props{ data: UpdateResponse<TData> | undefined, error: HttpError | null, status: "loading" | "error" | "idle" | "success" }

Example

Run on your local
npm create refine-app@latest -- --example form-antd-use-drawer-form