Skip to content

Commit dc04998

Browse files
committed
Isolate selection in multiple ArrayFields using storeKey
1 parent c0b71b4 commit dc04998

File tree

11 files changed

+1238
-0
lines changed

11 files changed

+1238
-0
lines changed

docs/ShowDialog.md

Lines changed: 320 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,320 @@
1+
---
2+
layout: default
3+
title: "ShowDialog"
4+
---
5+
6+
# `<ShowDialog>`
7+
8+
This [Enterprise Edition](https://react-admin-ee.marmelab.com)<img class="icon" src="./img/premium.svg" /> component offers a replacement to [the `<Show>` component](./Show.md) allowing users to visualize a record without leaving the context of the list page.
9+
10+
<video controls autoplay playsinline muted loop>
11+
<source src="https://react-admin-ee.marmelab.com/assets/ra-form-layout/latest/InDialogButtons.mp4" type="video/mp4" />
12+
Your browser does not support the video tag.
13+
</video>
14+
15+
## Usage
16+
17+
First, install the `@react-admin/ra-form-layout` package:
18+
19+
```sh
20+
npm install --save @react-admin/ra-form-layout
21+
# or
22+
yarn add @react-admin/ra-form-layout
23+
```
24+
25+
**Tip**: [`ra-form-layout`](https://react-admin-ee.marmelab.com/documentation/ra-form-layout#createdialog-editdialog--showdialog) is hosted in a private npm registry. You need to subscribe to one of the [Enterprise Edition](https://react-admin-ee.marmelab.com/) plans to access this package.
26+
27+
Then, add the `<ShowDialog>` component as a sibling to a `<List>` component.
28+
29+
```jsx
30+
import {
31+
List,
32+
Datagrid,
33+
ShowButton,
34+
SimpleShowLayout,
35+
TextField,
36+
DateField,
37+
} from 'react-admin';
38+
import { ShowDialog } from '@react-admin/ra-form-layout';
39+
40+
const CustomerList = () => (
41+
<>
42+
<List>
43+
<Datagrid>
44+
...
45+
<ShowButton />
46+
</Datagrid>
47+
</List>
48+
<ShowDialog>
49+
<SimpleShowLayout>
50+
<TextField source="first_name" />
51+
<TextField source="last_name" />
52+
<DateField source="date_of_birth" />
53+
</SimpleShowLayout>
54+
</ShowDialog>
55+
</>
56+
);
57+
```
58+
59+
In the related `<Resource>`, you don't need to declare a `show` component as the showing UI is part of the `list` component:
60+
61+
```jsx
62+
<Resource name="customers" list={CustomerList} />
63+
```
64+
65+
## Props
66+
67+
`<ShowDialog>` accepts the following props:
68+
69+
| Prop | Required | Type | Default | Description |
70+
| ------------------ | -------- | ----------------- | ------- | -------------------------------------------------------------------------- |
71+
| `children` | Required | `ReactNode` | | The content of the dialog |
72+
| `fullWidth` | Optional | `boolean` | `false` | If `true`, the dialog stretches to the full width of the screen |
73+
| `id` | Optional | `string | number` | | The record id. If not provided, it will be deduced from the record context |
74+
| `maxWidth` | Optional | `string` | `sm` | The max width of the dialog |
75+
| `queryOptions` | Optional | `object` | | The options to pass to the `useQuery` hook |
76+
| `resource` | Optional | `string` | | The resource name, e.g. `posts` |
77+
| `sx` | Optional | `object` | | Override the styles applied to the dialog component |
78+
| `title` | Optional | `ReactNode` | | The title of the dialog |
79+
80+
## `children`
81+
82+
`<ShowDialog>` doesn't render any field by default - it delegates this to its children, usually [a `SimpleShowLayout` component](./SimpleShowLayout.md).
83+
84+
React-admin also provides [`TabbedShowLayout`](./TabbedShowLayout.md), another layout component rendering tabs.
85+
86+
To use it, switch the `<ShowDialog>` child component:
87+
88+
```diff
89+
const MyShowDialog = () => (
90+
<ShowDialog>
91+
- <SimpleShowLayout>
92+
+ <TabbedShowLayout>
93+
+ <TabbedShowLayout.Tab label="Identity">
94+
<TextField source="first_name" />
95+
<TextField source="last_name" />
96+
+ </TabbedShowLayout.Tab>
97+
+ <TabbedShowLayout.Tab label="Informations">
98+
<DateField source="dob" label="born" />
99+
<SelectField source="sex" choices={sexChoices} />
100+
+ </TabbedShowLayout.Tab>
101+
- </SimpleShowLayout>
102+
+ </TabbedShowLayout>
103+
</ShowDialog>
104+
);
105+
```
106+
107+
## `fullWidth`
108+
109+
By default, `<ShowDialog>` renders a [Material UI `<Dialog>`](https://mui.com/material-ui/react-dialog/#full-screen-dialogs) component that takes the width of its content.
110+
111+
You can make the dialog full width by setting the `fullWidth` prop to `true`:
112+
113+
```jsx
114+
const MyShowDialog = () => (
115+
<ShowDialog fullWidth>
116+
...
117+
</ShowDialog>
118+
);
119+
```
120+
121+
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.
122+
123+
```jsx
124+
const MyShowDialog = () => (
125+
<ShowDialog fullWidth maxWidth="sm">
126+
...
127+
</ShowDialog>
128+
);
129+
```
130+
131+
## `id`
132+
133+
The `id` prop allows you to pass the record id to the `<ShowDialog>` component. If not provided, it will be deduced from the record context.
134+
135+
This is useful to link to a related record. For instance, the following dialog lets you show the author of a book:
136+
137+
```jsx
138+
const ShowAuthorDialog = () => {
139+
const book = useRecordContext();
140+
return (
141+
<ShowDialog resource="authors" id={book.author_id}>
142+
...
143+
</ShowDialog>
144+
);
145+
};
146+
```
147+
148+
## `maxWidth`
149+
150+
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`.
151+
152+
For example, you can use that prop to make the dialog full width:
153+
154+
```jsx
155+
const MyShowDialog = () => (
156+
<ShowDialog fullWidth maxWidth={false}>
157+
...
158+
</ShowDialog>
159+
);
160+
```
161+
162+
## `queryOptions`
163+
164+
The `queryOptions` prop allows you to pass options to the `useQuery` hook.
165+
166+
This can be useful e.g. to pass [a custom `meta`](./Actions.md#meta-parameter) to the `dataProvider.getOne()` call.
167+
168+
{% raw %}
169+
170+
```jsx
171+
const MyShowDialog = () => (
172+
<ShowDialog queryOptions={{ meta: { fetch: 'author' } }}>
173+
...
174+
</ShowDialog>
175+
);
176+
```
177+
178+
{% endraw %}
179+
180+
## `resource`
181+
182+
The `resource` prop allows you to pass the resource name to the `<ShowDialog>` component. If not provided, it will be deduced from the resource context.
183+
184+
This is useful to link to a related record. For instance, the following dialog lets you show the author of a book:
185+
186+
```jsx
187+
const ShowAuthorDialog = () => {
188+
const book = useRecordContext();
189+
return (
190+
<ShowDialog resource="authors" id={book.author_id}>
191+
...
192+
</ShowDialog>
193+
);
194+
};
195+
```
196+
197+
## `sx`
198+
199+
Customize the styles applied to the Material UI `<Dialog>` component:
200+
201+
{% raw %}
202+
203+
```jsx
204+
const MyShowDialog = () => (
205+
<ShowDialog sx={{ backgroundColor: 'paper' }}>
206+
...
207+
</ShowDialog>
208+
);
209+
```
210+
211+
{% endraw %}
212+
213+
## `title`
214+
215+
Unlike the `<Show>` components, with Dialog components the title will be displayed in the `<Dialog>`, not in the `<AppBar>`.
216+
If you pass a custom title component, it will render in the same `RecordContext` as the dialog's child component. That means you can display non-editable details of the current `record` in the title component.
217+
Here is an example:
218+
219+
```tsx
220+
import React from 'react';
221+
import {
222+
List,
223+
Datagrid,
224+
SimpleShowLayout,
225+
TextField,
226+
DateField,
227+
required,
228+
useRecordContext,
229+
ShowButton,
230+
} from 'react-admin';
231+
import { ShowDialog } from '@react-admin/ra-form-layout';
232+
233+
const CustomerShowTitle = () => {
234+
const record = useRecordContext();
235+
return record ? (
236+
<span>
237+
Show {record?.last_name} {record?.first_name}
238+
</span>
239+
) : null;
240+
};
241+
242+
const CustomerList = () => (
243+
<>
244+
<List>
245+
<Datagrid>
246+
...
247+
<ShowButton />
248+
</Datagrid>
249+
</List>
250+
<ShowDialog title={<CustomerShowTitle />}>
251+
<SimpleShowLayout>
252+
<TextField source="id" />
253+
<TextField source="first_name" />
254+
<TextField source="last_name" />
255+
<DateField source="date_of_birth" label="born" />
256+
</SimpleShowLayout>
257+
</EditDialog>
258+
</>
259+
);
260+
```
261+
262+
You can also hide the title by passing `null`:
263+
264+
```tsx
265+
<ShowDialog title={null}>
266+
<SimpleShowLayout>
267+
...
268+
</SimpleShowLayout>
269+
</ShowDialog>
270+
```
271+
272+
## Usage Without Routing
273+
274+
By default, `<ShowDialog>` creates a react-router `<Route>` for the displaying path (e.g. `/posts/2/show`), and renders when users go to that location (either by clicking on a datagrid row, or by typing the URL in the browser). If you embed it in the `list` page as explained above, the dialog will always render on top of the list.
275+
276+
This may not be what you want if you need to display the show dialog in another page (e.g. to show a related record).
277+
278+
In that case, use [the `<ShowInDialogButton>` component](./ShowInDialogButton.md), which doesn't create a route, but renders the dialog when the user clicks on it.
279+
280+
<video controls autoplay playsinline muted loop>
281+
<source src="https://react-admin-ee.marmelab.com/assets/ra-form-layout/latest/InDialogButtons.mp4" type="video/mp4" />
282+
Your browser does not support the video tag.
283+
</video>
284+
285+
Put `<ShowInDialogButton>` wherever you would put a `<ShowButton>`, and use the same children as you would for a `<Show>` component (e.g. a `<SimpleShowLayout>`):
286+
287+
```jsx
288+
import {
289+
Datagrid,
290+
ReferenceManyField,
291+
Show,
292+
SimpleShowLayout,
293+
TextField,
294+
} from "react-admin";
295+
import { ShowInDialogButton } from "@react-admin/ra-form-layout";
296+
297+
const CompanyShow = () => (
298+
<Show>
299+
<SimpleShowLayout>
300+
<TextField source="name" />
301+
<TextField source="address" />
302+
<TextField source="city" />
303+
<ReferenceManyField target="company_id" reference="employees">
304+
<Datagrid>
305+
<TextField source="first_name" />
306+
<TextField source="last_name" />
307+
<ShowInDialogButton>
308+
<SimpleShowLayout>
309+
<TextField source="first_name" />
310+
<TextField source="last_name" />
311+
</SimpleShowLayout>
312+
</ShowInDialogButton>
313+
</Datagrid>
314+
</ReferenceManyField>
315+
</SimpleShowLayout>
316+
</Show>
317+
);
318+
```
319+
320+
Check [the `<ShowInDialogButton>` component](./ShowInDialogButton.md) for more details.

0 commit comments

Comments
 (0)