Skip to content

Commit 2514fd7

Browse files
Native form example
1 parent fe13200 commit 2514fd7

File tree

4 files changed

+105
-6
lines changed

4 files changed

+105
-6
lines changed

src/components/Modal/Modal.jsx

+4-4
Original file line numberDiff line numberDiff line change
@@ -68,16 +68,16 @@ export const Modal = ({
6868
useModalScrollPrevention(preventScrollUnderneath);
6969

7070
const onCancel = useCallback(
71-
(e) => dialogOnCancelHandler(e, closeButtonRef),
72-
[closeButtonRef],
71+
(e) => dialogOnCancelHandler(e, closeButtonRef, restProps.onCancel),
72+
[closeButtonRef, restProps.onCancel],
7373
);
7474
const onClick = useCallback(
7575
(e) => dialogOnClickHandler(e, closeButtonRef, internalDialogRef, allowCloseOnBackdropClick),
7676
[allowCloseOnBackdropClick, closeButtonRef, internalDialogRef],
7777
);
7878
const onClose = useCallback(
79-
(e) => dialogOnCloseHandler(e, closeButtonRef),
80-
[closeButtonRef],
79+
(e) => dialogOnCloseHandler(e, closeButtonRef, restProps.onClose),
80+
[closeButtonRef, restProps.onClose],
8181
);
8282
const onKeyDown = useCallback(
8383
(e) => dialogOnKeyDownHandler(

src/components/Modal/README.md

+89
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,10 @@ React.createElement(() => {
159159
label="Launch modal as form"
160160
onClick={() => setModalOpen(4)}
161161
/>
162+
<Button
163+
label="Launch modal as native form"
164+
onClick={() => setModalOpen(5)}
165+
/>
162166
<div>
163167
{modalOpen === 1 && (
164168
<Modal>
@@ -278,6 +282,91 @@ React.createElement(() => {
278282
</ModalFooter>
279283
</Modal>
280284
)}
285+
{modalOpen === 5 && (
286+
<Modal
287+
allowPrimaryActionOnEnterKey={false}
288+
closeButtonRef={modalCloseButtonRef}
289+
onCancel={(e) => {
290+
console.log('cancel', e);
291+
}}
292+
onClose={(e) => {
293+
console.log('close', e);
294+
}}
295+
primaryButtonRef={modalPrimaryButtonRef}
296+
>
297+
<ModalHeader>
298+
<ModalTitle>Add new user using native form</ModalTitle>
299+
<ModalCloseButton onClick={() => setModalOpen(false)} />
300+
</ModalHeader>
301+
<ModalBody>
302+
<ModalContent>
303+
<p>
304+
This is an example of a native form inside a modal.
305+
The difference is that the dialog is not controlled by React UI,
306+
but using native <code>&lt;form&gt;</code> element.
307+
This is useful when you need to use native form features
308+
like validation, submission, etc.
309+
</p>
310+
<p>
311+
First, you need to set <code>allowPrimaryActionOnEnterKey</code>
312+
to <code>false</code> and remove <code>onClick</code> from the
313+
primary button. Then, you need to set <code>form</code> attribute
314+
on the primary button to the <code>id</code> of the form to
315+
connect it with the form.
316+
</p>
317+
<p>
318+
Although we do not encourage using this approach, it is still
319+
possible to use it when needed.
320+
</p>
321+
<hr />
322+
<form method="dialog" id="native-form">
323+
<FormLayout fieldLayout="horizontal" labelWidth="limited">
324+
<Toggle
325+
label="Enabled"
326+
/>
327+
<TextField label="Username" required />
328+
<TextField label="Password" type="password" />
329+
<CheckboxField label="Force password on login" />
330+
<Radio
331+
label="Type of collaboration"
332+
options={[
333+
{ label: 'Internal', value: 'internal'},
334+
{ label: 'External', value: 'external'},
335+
]}
336+
/>
337+
<SelectField
338+
label="Role"
339+
options={[
340+
{ label: 'Programmer', value: 'programmer' },
341+
{ label: 'Team leader', value: 'team-leader' },
342+
{ label: 'Project manager', value: 'project-manager' },
343+
]}
344+
/>
345+
<FileInputField label="Photo" />
346+
<TextArea
347+
label="Additional info"
348+
helpText={<p>Enter key is used for new line,<br />so <strong>Enter won't submit the form</strong>.</p>}
349+
/>
350+
</FormLayout>
351+
</form>
352+
</ModalContent>
353+
</ModalBody>
354+
<ModalFooter>
355+
<Button
356+
form="native-form"
357+
label="Save"
358+
ref={modalPrimaryButtonRef}
359+
type="submit"
360+
/>
361+
<Button
362+
label="Close"
363+
onClick={() => setModalOpen(false)}
364+
priority="outline"
365+
ref={modalCloseButtonRef}
366+
/>
367+
</ModalFooter>
368+
</Modal>
369+
)}
281370
</div>
282371
</RUIProvider>
283372
);

src/components/Modal/_helpers/dialogOnCancelHandler.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export const dialogOnCancelHandler = (e, closeButtonRef) => {
1+
export const dialogOnCancelHandler = (e, closeButtonRef, onCancel = undefined) => {
22
// Prevent the default behaviour of the event as we want to close dialog manually.
33
e.preventDefault();
44

@@ -9,4 +9,9 @@ export const dialogOnCancelHandler = (e, closeButtonRef) => {
99
) {
1010
closeButtonRef.current.click();
1111
}
12+
13+
// This is a custom handler that is passed as a prop to the Modal component
14+
if (onCancel) {
15+
onCancel(e);
16+
}
1217
};
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
1-
export const dialogOnCloseHandler = (e, closeButtonRef) => {
1+
export const dialogOnCloseHandler = (e, closeButtonRef, onCloseHandler = undefined) => {
22
// Prevent the default behaviour of the event as we want to close dialog manually.
33
e.preventDefault();
44

55
// If the close button is not disabled, close the modal.
66
if (closeButtonRef?.current != null && closeButtonRef?.current?.disabled === false) {
77
closeButtonRef.current.click();
88
}
9+
10+
// This is a custom handler that is passed as a prop to the Modal component
11+
if (onCloseHandler) {
12+
onCloseHandler(e);
13+
}
914
};

0 commit comments

Comments
 (0)