useModalForm
useModalForm
hook allows you to manage a form within a modal. It provides some useful methods to handle the form modal.
useModalForm
hook is extended from useForm
from the @refinedev/react-hook-form
package. This means that you can use all the features of useForm
hook.
Basic Usage
We'll show three examples, "create"
, "edit"
and "clone"
. Let's see how useModalForm
is used in all.
- create
- edit
- clone
refine doesn't automatically add a <EditButton/>
to the each record in <PostList>
which opens edit form in <Modal>
when clicked.
So, we have to put the <EditButton/>
on our list. In that way, <Edit>
form in <Modal>
can fetch data by the record id
.
<td>
<button onClick={() => show(post.id)}>Edit</button>
</td>
Don't forget to pass the record "id"
to show
to fetch the record data. This is necessary for both "edit"
and "clone"
forms.
refine doesn't automatically add a <CloneButton/>
to the each record in <PostList>
which opens edit form in <Modal>
when clicked.
So, we have to put the <CloneButton/>
on our list. In that way, <Clone>
form in <Modal>
can fetch data by the record id
.
<td>
<button onClick={() => show(post.id)}>clone</button>
</td>
Don't forget to pass the record "id"
to show
to fetch the record data. This is necessary for both "edit"
and "clone"
forms.
See Modal component
type ModalPropsType = {
isOpen: boolean
onClose: () => void
children: React.ReactNode
}
const Modal: React.FC<ModalPropsType> = ({ isOpen, onClose, children }) => {
if (!isOpen) return null
return (
<>
<div className="overlay" onClick={onClose}></div>
<div className="modal">
<div className="modal-title">
<button className="close-button" onClick={onClose}>
×
</button>
</div>
<div className="modal-content">{children}</div>
</div>
</>
)
}
See styles
* {
box-sizing: border-box;
}
.overlay {
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
background-color: rgba(0, 0, 0, 0.7);
z-index: 1000;
}
.modal {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: #fff;
z-index: 1000;
width: 500px;
overflow-y: auto;
}
.modal .modal-title {
display: flex;
justify-content: flex-end;
padding: 4px;
}
.modal .modal-content {
padding: 0px 16px 16px 16px;
}
.form {
display: flex;
flex-direction: column;
gap: 8px;
}
.form .form-group {
display: flex;
flex-direction: column;
gap: 4px;
}
.form input,
select,
textarea {
width: 100%;
padding: 8px;
border: 1px solid #ccc;
border-radius: 4px;
}
Properties
All useForm
props also available in useModalForm
. You can find descriptions on useForm
docs.
All React Hook Form useForm
props also available in useModalForm
. You can find descriptions on React Hook Form
docs.
defaultValues
Only available in
"create"
form.
Default values for the form. Use this to pre-populate the form with data that needs to be displayed.
const modalForm = useModalForm({
defaultValues: {
title: 'Hello World',
},
})
defaultVisible
Default:
false
When true
, modal will be visible by default.
const modalForm = useModalForm({
modalProps: {
defaultVisible: true,
},
})
autoSubmitClose
Default:
true
When true
, modal will be closed after successful submit.
const modalForm = useModalForm({
modalProps: {
autoSubmitClose: false,
},
})
autoResetForm
Default:
true
When true
, form will be reset after successful submit.
const modalForm = useModalForm({
modalProps: {
autoResetForm: false,
},
})
warnWhenUnsavedChanges
Default:
false
When you have unsaved changes and try to leave the current page, refine shows a confirmation modal box. To activate this feature.
You can also set this value in <Refine>
component.
const modalForm = useModalForm({
warnWhenUnsavedChanges: true,
})
syncWithLocation
Default:
false
When true
, the modals visibility state and the id
of the record will be synced with the URL.
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 modalForm = useModalForm({
syncWithLocation: { key: 'my-modal', syncId: true },
})
Return Values
All useForm
return values also available in useModalForm
. You can find descriptions on useForm
docs.
All React Hook Form useForm
return values also available in useModalForm
. You can find descriptions on useForm
docs.
visible
Current visibility state of the modal.
const modalForm = useModalForm({
defaultVisible: true,
})
console.log(modalForm.modal.visible) // true
title
Title of the modal. Based on resource and action values
const {
modal: { title },
} = useModalForm({
refineCoreProps: {
resource: 'posts',
action: 'create',
},
})
console.log(title) // "Create Post"
close
A function that can close the modal. It's useful when you want to close the modal manually.
const {
getInputProps,
handleSubmit,
register,
modal,
refineCore: { onFinish },
} = useModalForm()
return (
<>
<button onClick={show}>Show Modal</button>
<Modal {...modal}>
<form onSubmit={handleSubmit(onFinish)}>
<div>
<label>Title: </label>
<input {...register('title')} />
</div>
<div>
<button type="submit" onClick={modal.close}>
Cancel
</button>
<button type="submit" onClick={modal.submit}>
Save
</button>
</div>
</form>
</Modal>
</>
)
submit
A function that can submit the form. It's useful when you want to submit the form manually.
const {
getInputProps,
handleSubmit,
register,
modal,
refineCore: { onFinish },
} = useModalForm()
// ---
return (
<>
<button onClick={show}>Show Modal</button>
<Modal {...modal}>
<form onSubmit={handleSubmit(onFinish)}>
<div>
<label>Title: </label>
<input {...register('title')} />
</div>
<div>
<button type="submit" onClick={modal.submit}>
Save
</button>
</div>
</form>
</Modal>
</>
)
show
A function that can show the modal.
const {
saveButtonProps,
handleSubmit,
register,
modal,
refineCore: { onFinish, formLoading },
} = useModalForm()
return (
<>
<button onClick={show}>Show Modal</button>
<Modal {...modal}>
<form onSubmit={handleSubmit(onFinish)}>
<div>
<label>Title: </label>
<input {...register('title')} />
</div>
<div>
<button type="submit" {...saveButtonProps}>
Save
</button>
</div>
</form>
</Modal>
</>
)
saveButtonProps
It contains all the props needed by the "submit" button within the modal (disabled,loading etc.). You can manually pass these props to your custom button.
const {
saveButtonProps,
handleSubmit,
register,
modal,
refineCore: { onFinish, formLoading },
} = useModalForm()
return (
<>
<button onClick={show}>Show Modal</button>
<Modal {...modal}>
<form onSubmit={handleSubmit(onFinish)}>
<div>
<label>Title: </label>
<input {...register('title')} />
</div>
<div>
<button
type="submit"
disabled={saveButtonProps.disabled}
onClick={(e) => {
// -- your custom logic
saveButtonProps.onClick(e)
}}
>
Save
</button>
</div>
</form>
</Modal>
</>
)
API Reference
Properties
*
: These properties have default values inRefineContext
and can also be set on the <Refine> component.
It also accepts all props of useForm hook available in the React Hook Form.
Type Parameters
Property | Desription | Type | Default |
---|---|---|---|
TData | Result data returned by the query function. Extends BaseRecord | BaseRecord | BaseRecord |
TError | Custom error object that extends HttpError | HttpError | HttpError |
TVariables | Field Values for mutation function | {} | {} |
TContext | Second generic type of the useForm of the React Hook Form. | {} | {} |
TSelectData | Result data returned by the select function. Extends BaseRecord . If not specified, the value of TData will be used as the default value. | BaseRecord | TData |
Return values
Property | Description | Type |
---|---|---|
modal | Relevant states and methods to control the modal | ModalReturnValues |
refineCore | The return values of the useForm in the core | UseFormReturnValues |
React Hook Form Return Values | See React Hook Form documentation |
ModalReturnValues
Property Description Type visible State of modal visibility boolean
show Sets the visible state to true (id?: BaseKey) => void
close Sets the visible state to false () => void
submit Submits the form (values: TVariables) => void
title Modal title based on resource and action value string
saveButtonProps Props for a submit button { disabled: boolean, onClick: (e: React.BaseSyntheticEvent) => void; }
Example
npm create refine-app@latest -- --example form-react-hook-form-use-modal-form