Skip to content

Commit ed472ec

Browse files
committed
add renderProp on edit component
1 parent a5b5efe commit ed472ec

File tree

5 files changed

+80
-6
lines changed

5 files changed

+80
-6
lines changed

docs/Edit.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ You can customize the `<Edit>` component using the following props:
6666
* [`actions`](#actions): override the actions toolbar with a custom component
6767
* [`aside`](#aside): component to render aside to the main content
6868
* `children`: the components that renders the form
69+
* `render`: a function to renders the form, receive the editContext as argument.
6970
* `className`: passed to the root component
7071
* [`component`](#component): override the root component
7172
* [`disableAuthentication`](#disableauthentication): disable the authentication check
@@ -80,6 +81,33 @@ You can customize the `<Edit>` component using the following props:
8081
* [`title`](#title): override the page title
8182
* [`transform`](#transform): transform the form data before calling `dataProvider.update()`
8283

84+
## `render`
85+
86+
Alternatively to children you can pass a render prop to `<List>`. The render prop will receive the list context as its argument, allowing to inline the render logic for both the list content.
87+
When receiving a render prop the `<List>` component will ignore the children property.
88+
89+
{% raw %}
90+
```tsx
91+
<List
92+
render={({ error, isPending }) => {
93+
if (isPending) {
94+
return <div>Loading...</div>;
95+
}
96+
if (error) {
97+
return <div>Error: {error.message}</div>;
98+
}
99+
return (
100+
<SimpleList
101+
primaryText="%{title} (%{year})"
102+
secondaryText="%{summary}"
103+
tertiaryText={record => record.year}
104+
/>
105+
);
106+
}}
107+
/>
108+
```
109+
{% endraw %}
110+
83111
## `actions`
84112

85113
You can replace the list of default actions by your own elements using the `actions` prop:

packages/ra-ui-materialui/src/detail/Edit.spec.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import {
2929
NotificationTranslated,
3030
EmptyWhileLoading,
3131
Themed,
32+
WithRenderProp,
3233
} from './Edit.stories';
3334

3435
describe('<Edit />', () => {
@@ -340,6 +341,13 @@ describe('<Edit />', () => {
340341
});
341342
});
342343

344+
it('should allow tu use render prop instead of children', async () => {
345+
render(<WithRenderProp />);
346+
await waitFor(() => {
347+
expect(screen.queryAllByText('War and Peace')).toHaveLength(1);
348+
});
349+
});
350+
343351
describe('onSuccess prop', () => {
344352
it('should allow to override the default success side effects', async () => {
345353
const dataProvider = {

packages/ra-ui-materialui/src/detail/Edit.stories.tsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,3 +397,24 @@ export const Themed = () => (
397397
</Admin>
398398
</TestMemoryRouter>
399399
);
400+
401+
export const WithRenderProp = () => (
402+
<TestMemoryRouter initialEntries={['/books/1/Edit']}>
403+
<Admin dataProvider={dataProvider}>
404+
<Resource
405+
name="books"
406+
edit={() => (
407+
<Edit
408+
render={editContext => {
409+
return editContext.record ? (
410+
<span>{editContext.record.title}</span>
411+
) : null;
412+
}}
413+
>
414+
<BookTitle />
415+
</Edit>
416+
)}
417+
/>
418+
</Admin>
419+
</TestMemoryRouter>
420+
);

packages/ra-ui-materialui/src/detail/Edit.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ export const Edit = <RecordType extends RaRecord = any>(
7676
loading = defaultLoading,
7777
...rest
7878
} = props;
79+
7980
return (
8081
<EditBase<RecordType>
8182
resource={resource}
@@ -95,7 +96,7 @@ export const Edit = <RecordType extends RaRecord = any>(
9596

9697
export interface EditProps<RecordType extends RaRecord = any, ErrorType = Error>
9798
extends EditBaseProps<RecordType, ErrorType>,
98-
Omit<EditViewProps, 'children'> {}
99+
Omit<EditViewProps, 'children' | 'render'> {}
99100

100101
const defaultLoading = <Loading />;
101102

packages/ra-ui-materialui/src/detail/EditView.tsx

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as React from 'react';
2-
import type { ReactElement, ElementType } from 'react';
2+
import type { ReactElement, ElementType, ReactNode } from 'react';
33
import {
44
Card,
55
CardContent,
@@ -9,7 +9,11 @@ import {
99
type Theme,
1010
} from '@mui/material';
1111
import clsx from 'clsx';
12-
import { useEditContext, useResourceDefinition } from 'ra-core';
12+
import {
13+
EditControllerResult,
14+
useEditContext,
15+
useResourceDefinition,
16+
} from 'ra-core';
1317

1418
import { EditActions } from './EditActions';
1519
import { Title } from '../layout';
@@ -22,6 +26,7 @@ export const EditView = (props: EditViewProps) => {
2226
actions,
2327
aside,
2428
children,
29+
render,
2530
className,
2631
component: Content = Card,
2732
emptyWhileLoading = false,
@@ -30,11 +35,13 @@ export const EditView = (props: EditViewProps) => {
3035
} = props;
3136

3237
const { hasShow } = useResourceDefinition();
33-
const { resource, defaultTitle, record, isPending } = useEditContext();
38+
const editContext = useEditContext();
39+
40+
const { resource, defaultTitle, record, isPending } = editContext;
3441

3542
const finalActions =
3643
typeof actions === 'undefined' && hasShow ? defaultActions : actions;
37-
if (!children || (!record && isPending && emptyWhileLoading)) {
44+
if ((!children && !render) || (!record && isPending && emptyWhileLoading)) {
3845
return null;
3946
}
4047

@@ -54,7 +61,15 @@ export const EditView = (props: EditViewProps) => {
5461
})}
5562
>
5663
<Content className={EditClasses.card}>
57-
{record ? children : <CardContent>&nbsp;</CardContent>}
64+
{record ? (
65+
render ? (
66+
render(editContext)
67+
) : (
68+
children
69+
)
70+
) : (
71+
<CardContent>&nbsp;</CardContent>
72+
)}
5873
</Content>
5974
{aside}
6075
</div>
@@ -70,6 +85,7 @@ export interface EditViewProps
7085
emptyWhileLoading?: boolean;
7186
title?: string | ReactElement | false;
7287
sx?: SxProps<Theme>;
88+
render?: (editContext: EditControllerResult) => ReactNode;
7389
}
7490

7591
const PREFIX = 'RaEdit';

0 commit comments

Comments
 (0)