Skip to content

Commit 6c83335

Browse files
authored
Merge pull request #9425 from marmelab/doc-editindialogbutton-redirection
[Doc] Document `<EditInDialogButton>` deletion side effect
2 parents 4206f5f + b3c19cd commit 6c83335

File tree

1 file changed

+297
-14
lines changed

1 file changed

+297
-14
lines changed

docs/EditInDialogButton.md

+297-14
Original file line numberDiff line numberDiff line change
@@ -5,37 +5,47 @@ title: "EditInDialogButton"
55

66
# `<EditInDialogButton>`
77

8-
This [Enterprise Edition](https://marmelab.com/ra-enterprise)<img class="icon" src="./img/premium.svg" /> component offers a way to open an `<Edit>` view inside a dialog, hence allowing to edit a record without leaving the current view.
9-
10-
It can be useful in case you want the ability to edit a record linked by a reference to the currently edited record, or if you have a nested `<Datagrid>` inside a `<Show>` or an `<Edit>` view.
8+
This [Enterprise Edition](https://marmelab.com/ra-enterprise)<img class="icon" src="./img/premium.svg" /> component renders a button opening an `<Edit>` view inside a dialog, hence allowing to edit a record without leaving the current view.
119

1210
<video controls autoplay playsinline muted loop>
1311
<source src="https://marmelab.com/ra-enterprise/modules/assets/ra-form-layout/latest/InDialogButtons.webm" type="video/webm" />
1412
<source src="https://marmelab.com/ra-enterprise/modules/assets/ra-form-layout/latest/InDialogButtons.mp4" type="video/mp4" />
1513
Your browser does not support the video tag.
1614
</video>
1715

16+
It can be useful in case you want the ability to edit a record linked by a reference to the currently edited record, or if you have a nested `<Datagrid>` inside a `<Show>` or an `<Edit>` view.
17+
1818
Note that this component doesn't use routing, so it doesn't change the URL. It's therefore not possible to bookmark the edit dialog, or to link to it from another page. If you need that functionality, use [`<EditDialog>`](./EditDialog.md) instead.
1919

2020
## Usage
2121

22-
Put `<EditInDialogButton>` wherever you would put an `<EditButton>`, and use the same children as you would for an [`<Edit>`](./Edit.md) component (e.g. a `<SimpleForm>`):
22+
First, install the `@react-admin/ra-form-layout` package:
23+
24+
```sh
25+
npm install --save @react-admin/ra-form-layout
26+
# or
27+
yarn add @react-admin/ra-form-layout
28+
```
29+
30+
**Tip**: [`ra-form-layout`](https://marmelab.com/ra-enterprise/modules/ra-form-layout#createindialogbutton-editindialogbutton-and-EditInDialogButton) is hosted in a private npm registry. You need to subscribe to one of the [Enterprise Edition](https://marmelab.com/ra-enterprise/) plans to access this package.
31+
32+
Then, put `<EditInDialogButton>` wherever you would put an `<EditButton>`, and use the same children as you would for an [`<Edit>`](./Edit.md) component (e.g. a `<SimpleForm>`):
2333

2434
```jsx
2535
import {
2636
Datagrid,
2737
ReferenceManyField,
2838
Show,
2939
SimpleForm,
30-
SimpleShowLayout,
40+
SimpleForm,
3141
TextField,
3242
TextInput,
3343
} from "react-admin";
3444
import { EditInDialogButton } from "@react-admin/ra-form-layout";
3545

3646
const CompanyShow = () => (
3747
<Show>
38-
<SimpleShowLayout>
48+
<SimpleForm>
3949
<TextField source="name" />
4050
<TextField source="address" />
4151
<TextField source="city" />
@@ -51,20 +61,293 @@ const CompanyShow = () => (
5161
</EditInDialogButton>
5262
</Datagrid>
5363
</ReferenceManyField>
54-
</SimpleShowLayout>
64+
</SimpleForm>
5565
</Show>
5666
);
5767
```
5868

59-
It accepts the following props:
69+
## Props
70+
71+
`<EditInDialogButton>` accepts the following props:
72+
73+
| Prop | Required | Type | Default | Description |
74+
| -------------- | -------- | ----------------- | ------- | ----------- |
75+
| `children` | Required | `ReactNode` | | The content of the dialog. |
76+
| `ButtonProps` | Optional | `object` | | Object containing props to pass to Material UI's `<Button>`. |
77+
| `empty WhileLoading` | Optional | `boolean` | | Set to `true` to return `null` while the list is loading. |
78+
| `fullWidth` | Optional | `boolean` | `false` | If `true`, the dialog stretches to the full width of the screen. |
79+
| `icon` | Optional | `ReactElement` | | Allows to override the default icon. |
80+
| `id` | Optional | `string | number` | | The record id. If not provided, it will be deduced from the record context. |
81+
| `inline` | Optional | `boolean` | | Set to true to display only a Material UI `<IconButton>` instead of the full `<Button>`. |
82+
| `label` | Optional | `string` | | Allows to override the default button label. I18N is supported. |
83+
| `maxWidth` | Optional | `string` | `sm` | The max width of the dialog. |
84+
| `mutation Options` | Optional | `object` | | The options to pass to the `useMutation` hook. |
85+
| `queryOptions` | Optional | `object` | | The options to pass to the `useQuery` hook.
86+
| `resource` | Optional | `string` | | The resource name, e.g. `posts`
87+
| `sx` | Optional | `object` | | Override the styles applied to the dialog component. |
88+
89+
## `children`
90+
91+
`<EditInDialogButton>` doesn't render any field by default - it delegates this to its children, usually a Form component.
92+
93+
React-admin provides several built-in form layout components:
94+
95+
- [`SimpleForm`](./SimpleForm.md) for a single-column layout
96+
- [`TabbedForm`](./TabbedForm.md) for a tabbed layout
97+
- [`AccordionForm`](./AccordionForm.md) for long forms with collapsible sections
98+
- [`LongForm`](./LongForm.md) for long forms with a navigation sidebar
99+
- [`WizardForm`](./WizardForm.md) for multi-step forms
100+
- [`EditDialog`](./EditDialog.md) for sub-forms in a modal dialog
101+
- and [`Form`](./Form.md), a headless component to use as a base for your custom layouts
102+
103+
To use an alternative form layout, switch the `<EditInDialogButton>` child component:
104+
105+
```diff
106+
const EditButton = () => (
107+
<EditInDialogButton fullWidth maxWidth="md">
108+
- <SimpleForm>
109+
+ <TabbedForm>
110+
+ <TabbedForm.Tab label="Identity">
111+
<TextInput source="first_name" fullWidth />
112+
<TextInput source="last_name" fullWidth />
113+
+ </TabbedForm.Tab>
114+
+ <TabbedForm.Tab label="Informations">
115+
<DateInput source="dob" label="born" fullWidth />
116+
<SelectInput source="sex" choices={sexChoices} fullWidth />
117+
+ </TabbedForm.Tab>
118+
- </SimpleForm>
119+
+ </TabbedForm>
120+
</EditInDialogButton>
121+
);
122+
```
123+
124+
## `ButtonProps`
125+
126+
The `ButtonProps` prop allows you to pass props to the MUI `<Button>` component. For instance, to change the color and size of the button:
127+
128+
{% raw %}
129+
```jsx
130+
const EditButton = () => (
131+
<EditInDialogButton ButtonProps={{ color: 'primary', fullWidth: true }}>
132+
<SimpleForm>
133+
...
134+
</SimpleForm>
135+
</EditInDialogButton>
136+
);
137+
```
138+
{% endraw %}
139+
140+
## `emptyWhileLoading`
141+
142+
By default, `<EditInDialogButton>` renders its child component even before the `dataProvider.getOne()` call returns. If you use `<SimpleForm>` or `<TabbedForm>`, this isn't a problem as these components only render when the record has been fetched. But if you use a custom child component that expects the record context to be defined, your component will throw an error.
143+
144+
To avoid this, set the `emptyWhileLoading` prop to `true`:
145+
146+
```jsx
147+
const EditButton = () => (
148+
<EditInDialogButton emptyWhileLoading>
149+
...
150+
</EditInDialogButton>
151+
);
152+
```
153+
154+
## `fullWidth`
155+
156+
By default, `<EditInDialogButton>` renders a [Material UI `<Dialog>`](https://mui.com/material-ui/react-dialog/#full-screen-dialogs) component that takes the width of its content.
157+
158+
You can make the dialog full width by setting the `fullWidth` prop to `true`:
159+
160+
```jsx
161+
const EditButton = () => (
162+
<EditInDialogButton fullWidth>
163+
...
164+
</EditInDialogButton>
165+
);
166+
```
167+
168+
In addition, you can set a dialog maximum width by using the `maxWidth` enumerable in combination with the `fullWidth` boolean. When the `fullWidth` prop is true, the dialog will adapt based on the `maxWidth` value.
169+
170+
```jsx
171+
const EditButton = () => (
172+
<EditInDialogButton fullWidth maxWidth="sm">
173+
...
174+
</EditInDialogButton>
175+
);
176+
```
177+
178+
## `icon`
179+
180+
The `icon` prop allows you to pass an icon to the button. It can be a MUI icon component, or a custom icon component.
181+
182+
```jsx
183+
import { Edit } from '@mui/icons-material';
184+
185+
const EditButton = () => (
186+
<EditInDialogButton icon={<Edit />}>
187+
...
188+
</EditInDialogButton>
189+
);
190+
```
191+
192+
## `id`
193+
194+
The `id` prop allows you to pass the record id to the `<EditInDialogButton>` component. If not provided, it will be deduced from the record context.
195+
196+
This is useful to link to a related record. For instance, the following button lets you show the author of a book:
197+
198+
```jsx
199+
const EditAuthorButton = () => {
200+
const book = useRecordContext();
201+
return (
202+
<EditInDialogButton resource="authors" id={book.author_id}>
203+
...
204+
</EditInDialogButton>
205+
);
206+
};
207+
```
208+
209+
## `inline`
210+
211+
By default, `<EditInDialogButton>` renders a `<Button>` component. If you want to display only an `<IconButton>`, set the `inline` prop to `true`:
212+
213+
```jsx
214+
const EditButton = () => (
215+
<EditInDialogButton inline>
216+
...
217+
</EditInDialogButton>
218+
);
219+
```
220+
221+
## `label`
222+
223+
The `label` prop allows you to pass a custom label to the button, instead of the default ("Edit"). It can be a string, or a React element.
224+
225+
```jsx
226+
const EditButton = () => (
227+
<EditInDialogButton label="Edit details">
228+
...
229+
</EditInDialogButton>
230+
);
231+
```
232+
233+
## `maxWidth`
234+
235+
The `maxWidth` prop allows you to set the max width of the dialog. It can be one of the following values: `xs`, `sm`, `md`, `lg`, `xl`, `false`. The default is `sm`.
236+
237+
For example, you can use that prop to make the dialog full width:
238+
239+
```jsx
240+
const EditButton = () => (
241+
<EditInDialogButton fullWidth maxWidth={false}>
242+
...
243+
</EditInDialogButton>
244+
);
245+
```
246+
247+
## `mutationOptions`
248+
249+
The `queryOptions` prop allows you to pass options to the `useMutation` hook.
250+
251+
This can be useful e.g. to pass [a custom `meta`](./Actions.md#meta-parameter) to the `dataProvider.update()` call.
252+
253+
{% raw %}
254+
```jsx
255+
const EditButton = () => (
256+
<EditInDialogButton mutationOptions={{ meta: { fetch: 'author' } }}>
257+
...
258+
</EditInDialogButton>
259+
);
260+
```
261+
{% endraw %}
262+
263+
## `queryOptions`
264+
265+
The `queryOptions` prop allows you to pass options to the `useQuery` hook.
266+
267+
This can be useful e.g. to pass [a custom `meta`](./Actions.md#meta-parameter) to the `dataProvider.getOne()` call.
268+
269+
{% raw %}
270+
```jsx
271+
const EditButton = () => (
272+
<EditInDialogButton queryOptions={{ meta: { fetch: 'author' } }}>
273+
...
274+
</EditInDialogButton>
275+
);
276+
```
277+
{% endraw %}
278+
279+
## `resource`
60280

61-
* `inline`: set to true to display only a Material UI `<IconButton>` instead of the full `<Button>`. The label will still be available as a `<Tooltip>` though.
62-
* `icon`: allows to override the default icon.
63-
* `label`: allows to override the default button label. I18N is supported.
64-
* `ButtonProps`: object containing props to pass to Material UI's `<Button>`.
65-
* remaining props will be passed to the [`<EditDialog>`](./EditDialog.md) dialog component.
281+
The `resource` prop allows you to pass the resource name to the `<EditInDialogButton>` component. If not provided, it will be deduced from the resource context.
66282

67-
Check out [the `ra-form-layout` documentation](https://marmelab.com/ra-enterprise/modules/ra-form-layout#createindialogbutton-editindialogbutton-and-showindialogbutton) for more details.
283+
This is useful to link to a related record. For instance, the following button lets you show the author of a book:
284+
285+
```jsx
286+
const EditAuthorButton = () => {
287+
const book = useRecordContext();
288+
return (
289+
<EditInDialogButton resource="authors" id={book.author_id}>
290+
...
291+
</EditInDialogButton>
292+
);
293+
};
294+
```
295+
296+
## `sx`
297+
298+
Customize the styles applied to the Material UI `<Dialog>` component:
299+
300+
{% raw %}
301+
```jsx
302+
const EditButton = () => (
303+
<EditInDialogButton sx={{ backgroundColor: 'paper' }}>
304+
...
305+
</EditInDialogButton>
306+
);
307+
```
308+
{% endraw %}
309+
310+
## Redirection After Deletion
311+
312+
If you use `<SimpleForm>` as child of `<EditInDialogButton>`, the default form toolbar includes a `<DeleteButton>`. And upon deletion, this button redirects to the current resource list. This is probably not what you want, so it's common to customize the form toolbar to disable the redirection after deletion:
313+
314+
{% raw %}
315+
```tsx
316+
// src/CustomToolbar.tsx
317+
import { Toolbar, SaveButton, DeleteButton } from 'react-admin';
318+
319+
export const CustomToolbar = () => (
320+
<Toolbar sx={{ justifyContent: 'space-between' }}>
321+
<SaveButton />
322+
<DeleteButton redirect={false} />
323+
</Toolbar>
324+
);
325+
326+
// src/EmployerEdit.tsx
327+
import { Edit, SimpleForm, TextInput, ReferenceManyField } from 'react-admin';
328+
import { EditInDialogButton } from '@react-admin/ra-form-layout';
329+
import { CustomToolbar } from './CustomToolbar';
330+
331+
const EmployerEdit = () => (
332+
<Edit>
333+
<SimpleForm>
334+
...
335+
<ReferenceManyField target="employer_id" reference="customers">
336+
<Datagrid>
337+
...
338+
<EditInDialogButton fullWidth maxWidth="sm">
339+
<SimpleForm toolbar={<CustomToolbar />}>
340+
<TextInput source="first_name" />
341+
<TextInput source="last_name" />
342+
</SimpleForm>
343+
</EditInDialogButton>
344+
</Datagrid>
345+
</ReferenceManyField>
346+
</SimpleForm>
347+
</Edit>
348+
);
349+
```
350+
{% endraw %}
68351

69352
## Combining With `<CreateInDialogButton>`
70353

0 commit comments

Comments
 (0)