Skip to content

Commit d26a330

Browse files
djhiMadeorsk
authored andcommitted
Add offline support to <ReferenceInputBase>, <ReferenceInput> and <AutocompleteInput>
1 parent 29c4c07 commit d26a330

File tree

10 files changed

+395
-80
lines changed

10 files changed

+395
-80
lines changed

docs/AutocompleteInput.md

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -54,27 +54,28 @@ The form value for the source must be the selected value, e.g.
5454

5555
## Props
5656

57-
| Prop | Required | Type | Default | Description |
58-
|--------------------------- |----------|-------------------------------------------------|-------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
59-
| `choices` | Optional | `Object[]` | `-` | List of items to autosuggest. Required if not inside a ReferenceInput. |
60-
| `create` | Optional | `Element` | `-` | A React Element to render when users want to create a new choice |
61-
| `createLabel` | Optional | `string` &#124; `ReactNode` | - | The label used as hint to let users know they can create a new choice. Displayed when the filter is empty. |
62-
| `createItemLabel` | Optional | `string` &#124; `(filter: string) => ReactNode` | `ra.action .create_item` | The label for the menu item allowing users to create a new choice. Used when the filter is not empty. |
63-
| `debounce` | Optional | `number` | `250` | The delay to wait before calling the setFilter function injected when used in a ReferenceInput. |
64-
| `emptyText` | Optional | `string` | `''` | The text to use for the empty element |
65-
| `emptyValue` | Optional | `any` | `''` | The value to use for the empty element |
66-
| `filterToQuery` | Optional | `string` => `Object` | `q => ({ q })` | How to transform the searchText into a parameter for the data provider |
67-
| `isPending` | Optional | `boolean` | `false` | If `true`, the component will display a loading indicator. |
68-
| `inputText` | Optional | `Function` | `-` | Required if `optionText` is a custom Component, this function must return the text displayed for the current selection. |
69-
| `matchSuggestion` | Optional | `Function` | `-` | Required if `optionText` is a React element. Function returning a boolean indicating whether a choice matches the filter. `(filter, choice) => boolean` |
70-
| `onChange` | Optional | `Function` | `-` | A function called with the new value, along with the selected record, when the input value changes |
71-
| `onCreate` | Optional | `Function` | `-` | A function called with the current filter value when users choose to create a new choice. |
57+
| Prop | Required | Type | Default | Description |
58+
|--------------------------- |----------|-------------------------------------------------|--------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
59+
| `choices` | Optional | `Object[]` | `-` | List of items to autosuggest. Required if not inside a ReferenceInput. |
60+
| `create` | Optional | `Element` | `-` | A React Element to render when users want to create a new choice |
61+
| `createLabel` | Optional | `string` &#124; `ReactNode` | - | The label used as hint to let users know they can create a new choice. Displayed when the filter is empty. |
62+
| `createItemLabel` | Optional | `string` &#124; `(filter: string) => ReactNode` | `ra.action .create_item` | The label for the menu item allowing users to create a new choice. Used when the filter is not empty. |
63+
| `debounce` | Optional | `number` | `250` | The delay to wait before calling the setFilter function injected when used in a ReferenceInput. |
64+
| `emptyText` | Optional | `string` | `''` | The text to use for the empty element |
65+
| `emptyValue` | Optional | `any` | `''` | The value to use for the empty element |
66+
| `filterToQuery` | Optional | `string` => `Object` | `q => ({ q })` | How to transform the searchText into a parameter for the data provider |
67+
| `isPending` | Optional | `boolean` | `false` | If `true`, the component will display a loading indicator. |
68+
| `inputText` | Optional | `Function` | `-` | Required if `optionText` is a custom Component, this function must return the text displayed for the current selection. |
69+
| `matchSuggestion` | Optional | `Function` | `-` | Required if `optionText` is a React element. Function returning a boolean indicating whether a choice matches the filter. `(filter, choice) => boolean` |
70+
| `offline` | Optional | `ReactNode` | - | What to render when there is no network connectivity when fetching the choices |
71+
| `onChange` | Optional | `Function` | `-` | A function called with the new value, along with the selected record, when the input value changes |
72+
| `onCreate` | Optional | `Function` | `-` | A function called with the current filter value when users choose to create a new choice. |
7273
| `optionText` | Optional | `string` &#124; `Function` &#124; `Component` | `undefined` &#124; `record Representation` | Field name of record to display in the suggestion item or function using the choice object as argument |
73-
| `optionValue` | Optional | `string` | `id` | Field name of record containing the value to use as input value |
74-
| `setFilter` | Optional | `Function` | `null` | A callback to inform the `searchText` has changed and new `choices` can be retrieved based on this `searchText`. Signature `searchText => void`. This function is automatically set up when using `ReferenceInput`. |
75-
| `shouldRender Suggestions` | Optional | `Function` | `() => true` | A function that returns a `boolean` to determine whether or not suggestions are rendered. |
76-
| `suggestionLimit` | Optional | `number` | `null` | Limits the numbers of suggestions that are shown in the dropdown list |
77-
| `translateChoice` | Optional | `boolean` | `true` | Whether the choices should be translated |
74+
| `optionValue` | Optional | `string` | `id` | Field name of record containing the value to use as input value |
75+
| `setFilter` | Optional | `Function` | `null` | A callback to inform the `searchText` has changed and new `choices` can be retrieved based on this `searchText`. Signature `searchText => void`. This function is automatically set up when using `ReferenceInput`. |
76+
| `shouldRender Suggestions` | Optional | `Function` | `() => true` | A function that returns a `boolean` to determine whether or not suggestions are rendered. |
77+
| `suggestionLimit` | Optional | `number` | `null` | Limits the numbers of suggestions that are shown in the dropdown list |
78+
| `translateChoice` | Optional | `boolean` | `true` | Whether the choices should be translated |
7879

7980
`<AutocompleteInput>` also accepts the [common input props](./Inputs.md#common-input-props).
8081

@@ -370,6 +371,27 @@ const UserCountry = () => {
370371
}
371372
```
372373

374+
## `offline`
375+
376+
`<AutocompleteInput>` can display a custom message when it can't fetch the choices because there is no network connectivity, thanks to the `offline` prop.
377+
378+
```jsx
379+
<ReferenceInput source="user_id" reference="users">
380+
<AutocompleteInput offline={<span>No network, could not fetch data</span>} />
381+
</ReferenceInput>
382+
```
383+
384+
You can pass either a React element or a string to the `offline` prop:
385+
386+
```jsx
387+
<ReferenceInput source="user_id" reference="users">
388+
<AutocompleteInput offline={<span>No network, could not fetch data</span>} />
389+
</ReferenceInput>
390+
<ReferenceInput source="user_id" reference="users">
391+
<AutocompleteInput offline="No network, could not fetch data" />
392+
</ReferenceInput>
393+
```
394+
373395
## `onChange`
374396

375397
Use the `onChange` prop to get notified when the input value changes.

docs/ReferenceInput.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ See the [`children`](#children) section for more details.
110110
| `label` | Optional | `string` | - | Useful only when `ReferenceInput` is in a Filter array, the label is used as the Filter label. |
111111
| `page` | Optional | `number` | 1 | The current page number |
112112
| `perPage` | Optional | `number` | 25 | Number of suggestions to show |
113+
| `offline` | Optional | `ReactNode` | - | What to render when there is no network connectivity when loading the record |
113114
| `queryOptions` | Optional | [`UseQueryOptions`](https://tanstack.com/query/v5/docs/react/reference/useQuery) | `{}` | `react-query` client options |
114115
| `sort` | Optional | `{ field: String, order: 'ASC' or 'DESC' }` | `{ field:'id', order:'DESC' }` | How to order the list of suggestions |
115116

@@ -191,6 +192,26 @@ const filters = [
191192
];
192193
```
193194

195+
## `offline`
196+
197+
`<ReferenceInput>` can display a custom message when the referenced record is missing because there is no network connectivity, thanks to the `offline` prop.
198+
199+
```jsx
200+
<ReferenceInput source="user_id" reference="users" offline="No network, could not fetch data" />
201+
```
202+
203+
`<ReferenceInput>` renders the `offline` element when:
204+
205+
- the referenced record is missing (no record in the `users` table with the right `user_id`), and
206+
- there is no network connectivity
207+
208+
You can pass either a React element or a string to the `offline` prop:
209+
210+
```jsx
211+
<ReferenceInput source="user_id" reference="users" offline={<span>No network, could not fetch data</span>} />
212+
<ReferenceInput source="user_id" reference="users" offline="No network, could not fetch data" />
213+
```
214+
194215
## `parse`
195216

196217
By default, children of `<ReferenceInput>` transform the empty form value (an empty string) into `null` before passing it to the `dataProvider`.

packages/ra-core/src/controller/input/ReferenceInputBase.spec.tsx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
SelfReference,
1818
QueryOptions,
1919
Meta,
20+
Offline,
2021
} from './ReferenceInputBase.stories';
2122

2223
describe('<ReferenceInputBase />', () => {
@@ -68,8 +69,8 @@ describe('<ReferenceInputBase />', () => {
6869
return <div>{resource}</div>;
6970
};
7071
const dataProvider = testDataProvider({
71-
// @ts-ignore
7272
getList: () =>
73+
// @ts-ignore
7374
Promise.resolve({ data: [{ id: 1 }, { id: 2 }], total: 2 }),
7475
});
7576
render(
@@ -92,8 +93,8 @@ describe('<ReferenceInputBase />', () => {
9293
return <div aria-label="total">{total}</div>;
9394
};
9495
const dataProvider = testDataProvider({
95-
// @ts-ignore
9696
getList: () =>
97+
// @ts-ignore
9798
Promise.resolve({ data: [{ id: 1 }, { id: 2 }], total: 2 }),
9899
});
99100
render(
@@ -187,6 +188,15 @@ describe('<ReferenceInputBase />', () => {
187188
screen.getByText('Save').click();
188189
await screen.findByText('Proust', undefined, { timeout: 5000 });
189190
});
191+
192+
it('should render the offline prop node when offline', async () => {
193+
render(<Offline />);
194+
fireEvent.click(await screen.findByText('Simulate offline'));
195+
fireEvent.click(await screen.findByText('Toggle Child'));
196+
await screen.findByText('You are offline, cannot load data');
197+
fireEvent.click(await screen.findByText('Simulate online'));
198+
await screen.findByText('lorem');
199+
});
190200
});
191201

192202
const AutocompleteInput = (

0 commit comments

Comments
 (0)