Skip to content

Commit 9804dcc

Browse files
committed
Add <ReferenceField empty> prop
1 parent 85a130c commit 9804dcc

File tree

4 files changed

+68
-27
lines changed

4 files changed

+68
-27
lines changed

docs/ReferenceField.md

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -74,26 +74,38 @@ It uses `dataProvider.getMany()` instead of `dataProvider.getOne()` [for perform
7474
| `source` | Required | `string` | - | Name of the property to display |
7575
| `reference` | Required | `string` | - | The name of the resource for the referenced records, e.g. 'posts' |
7676
| `children` | Optional | `ReactNode` | - | One or more Field elements used to render the referenced record |
77-
| `emptyText` | Optional | `string` | '' | Defines a text to be shown when the field has no value or when the reference is missing |
77+
| `empty` | Optional | `ReactNode` | - | What to render when the field has no value or when the reference is missing |
7878
| `label` | Optional | `string | Function` | `resources. [resource]. fields.[source]` | Label to use for the field when rendered in layout components |
7979
| `link` | Optional | `string | Function` | `edit` | Target of the link wrapping the rendered child. Set to `false` to disable the link. |
8080
| `queryOptions` | Optional | [`UseQuery Options`](https://tanstack.com/query/v5/docs/react/reference/useQuery) | `{}` | `react-query` client options |
8181
| `sortBy` | Optional | `string | Function` | `source` | Name of the field to use for sorting when used in a Datagrid |
8282

8383
`<ReferenceField>` also accepts the [common field props](./Fields.md#common-field-props).
8484

85-
## `emptyText`
85+
## `empty`
8686

87-
`<ReferenceField>` can display a custom message when the referenced record is missing, thanks to the `emptyText` prop.
87+
`<ReferenceField>` can display a custom message when the referenced record is missing, thanks to the `empty` prop.
8888

8989
```jsx
90-
<ReferenceField source="user_id" reference="users" emptyText="Missing user" />
90+
<ReferenceField source="user_id" reference="users" empty="Missing user" />
9191
```
9292

93-
`<ReferenceField>` renders the `emptyText`:
93+
`<ReferenceField>` renders the `empty` element when:
9494

95-
- when the referenced record is missing (no record in the `users` table with the right `user_id`), or
96-
- when the field is empty (no `user_id` in the record).
95+
- the referenced record is missing (no record in the `users` table with the right `user_id`), or
96+
- the field is empty (no `user_id` in the record).
97+
98+
When `empty` is a string, `<ReferenceField>` renders it as a `<Typography>` and passes the text through the i18n system, so you can use translation keys to have one message for each language supported by the interface:
99+
100+
```jsx
101+
<ReferenceField source="user_id" reference="users" empty="resources.users.missing" />
102+
```
103+
104+
You can also pass a React element to the `empty` prop:
105+
106+
```jsx
107+
<ReferenceField source="user_id" reference="users" empty={<span>Missing user</span>} />
108+
```
97109

98110
## `label`
99111

docs/WithRecord.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ const BookShow = () => (
2323
);
2424
```
2525

26-
Note that if `record` is undefined, `<WithRecord>` doesn't call the `render` callback and renders nothing, so you don't have to worry about this case in your render callback.
26+
Note that if `record` is undefined, `<WithRecord>` doesn't call the `render` callback and renders nothing (or the `empty` prop), so you don't have to worry about this case in your render callback.
2727

2828
## Availability
2929

packages/ra-ui-materialui/src/field/ReferenceField.stories.tsx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,32 @@ export const MissingReferenceIdEmptyTextTranslation = () => (
158158
</Wrapper>
159159
);
160160

161+
export const MissingReferenceIdEmpty = () => (
162+
<Wrapper record={{ id: 1, title: 'War and Peace' }}>
163+
<ReferenceField
164+
source="detail_id"
165+
reference="book_details"
166+
empty={<b>no detail</b>}
167+
>
168+
<TextField source="ISBN" />
169+
</ReferenceField>
170+
</Wrapper>
171+
);
172+
173+
export const MissingReferenceIdEmptyTranslation = () => (
174+
<Wrapper record={{ id: 1, title: 'War and Peace' }}>
175+
<I18nContextProvider value={i18nProvider}>
176+
<ReferenceField
177+
source="detail_id"
178+
reference="book_details"
179+
empty="resources.books.not_found"
180+
>
181+
<TextField source="ISBN" />
182+
</ReferenceField>
183+
</I18nContextProvider>
184+
</Wrapper>
185+
);
186+
161187
const missingReferenceDataProvider = {
162188
getMany: () =>
163189
Promise.resolve({

packages/ra-ui-materialui/src/field/ReferenceField.tsx

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -68,20 +68,26 @@ export const ReferenceField = <
6868
props: inProps,
6969
name: PREFIX,
7070
});
71-
const { emptyText } = props;
71+
const { emptyText, empty } = props;
7272
const translate = useTranslate();
73-
const id = useFieldValue(props);
74-
75-
if (id == null) {
76-
return emptyText ? (
77-
<Typography component="span" variant="body2">
78-
{emptyText && translate(emptyText, { _: emptyText })}
79-
</Typography>
80-
) : null;
81-
}
8273

8374
return (
84-
<ReferenceFieldBase<ReferenceRecordType> {...props}>
75+
<ReferenceFieldBase<ReferenceRecordType>
76+
{...props}
77+
empty={
78+
emptyText ? (
79+
<Typography component="span" variant="body2">
80+
{emptyText && translate(emptyText, { _: emptyText })}
81+
</Typography>
82+
) : typeof empty === 'string' ? (
83+
<Typography component="span" variant="body2">
84+
{empty && translate(empty, { _: empty })}
85+
</Typography>
86+
) : (
87+
empty ?? null
88+
)
89+
}
90+
>
8591
<PureReferenceFieldView<RecordType, ReferenceRecordType>
8692
{...props}
8793
/>
@@ -94,6 +100,11 @@ export interface ReferenceFieldProps<
94100
ReferenceRecordType extends RaRecord = RaRecord,
95101
> extends FieldProps<RecordType> {
96102
children?: ReactNode;
103+
/**
104+
* @deprecated Use the empty prop instead
105+
*/
106+
emptyText?: string;
107+
empty?: ReactNode;
97108
queryOptions?: Omit<
98109
UseQueryOptions<ReferenceRecordType[], Error>,
99110
'queryFn' | 'queryKey'
@@ -122,7 +133,6 @@ export const ReferenceFieldView = <
122133
useReferenceFieldContext();
123134

124135
const getRecordRepresentation = useGetRecordRepresentation(reference);
125-
const translate = useTranslate();
126136

127137
if (error) {
128138
return (
@@ -140,13 +150,6 @@ export const ReferenceFieldView = <
140150
if (isLoading) {
141151
return <LinearProgress />;
142152
}
143-
if (!referenceRecord) {
144-
return emptyText ? (
145-
<Typography component="span" variant="body2">
146-
{emptyText && translate(emptyText, { _: emptyText })}
147-
</Typography>
148-
) : null;
149-
}
150153

151154
const child = children || (
152155
<Typography component="span" variant="body2">

0 commit comments

Comments
 (0)