Skip to content

Commit e083b46

Browse files
authored
Merge pull request #8192 from marmelab/add-queryoptions-ri
Add `queryOptions` prop to `ReferenceInput`
2 parents bd83464 + 86fae55 commit e083b46

File tree

4 files changed

+71
-23
lines changed

4 files changed

+71
-23
lines changed

docs/ReferenceInput.md

+30-12
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,18 @@ You can tweak how this component fetches the possible values using the `page`, `
2727

2828
## Props
2929

30-
| Prop | Required | Type | Default | Description |
31-
|--------------------|----------|---------------------------------------------|----------------------------------|------------------------------------------------------------------------------------------|
32-
| `source` | Required | `string` | - | Name of the entity property to use for the input value |
33-
| `label` | Optional | `string` | - | Useful only when `ReferenceInput` is in a Filter array, the label is used as the Filter label.|
34-
| `reference` | Required | `string` | '' | Name of the reference resource, e.g. 'posts'. |
35-
| `children` | Optional | `ReactNode` | `<AutocompleteInput />` | The actual selection component |
36-
| `filter` | Optional | `Object` | `{}` | Permanent filters to use for getting the suggestion list |
37-
| `page` | Optional | `number` | 1 | The current page number |
38-
| `perPage` | Optional | `number` | 25 | Number of suggestions to show |
39-
| `sort` | Optional | `{ field: String, order: 'ASC' or 'DESC' }` | `{ field: 'id', order: 'DESC' }` | How to order the list of suggestions |
40-
| `enableGetChoices` | Optional | `({q: string}) => boolean` | `() => true` | Function taking the `filterValues` and returning a boolean to enable the `getList` call. |
30+
| Prop | Required | Type | Default | Description |
31+
|--------------------|----------|---------------------------------------------|----------------------------------|------------------------------------------------------------------------------------------------|
32+
| `source` | Required | `string` | - | Name of the entity property to use for the input value |
33+
| `label` | Optional | `string` | - | Useful only when `ReferenceInput` is in a Filter array, the label is used as the Filter label. |
34+
| `reference` | Required | `string` | '' | Name of the reference resource, e.g. 'posts'. |
35+
| `children` | Optional | `ReactNode` | `<AutocompleteInput />` | The actual selection component |
36+
| `filter` | Optional | `Object` | `{}` | Permanent filters to use for getting the suggestion list |
37+
| `page` | Optional | `number` | 1 | The current page number |
38+
| `perPage` | Optional | `number` | 25 | Number of suggestions to show |
39+
| `sort` | Optional | `{ field: String, order: 'ASC' or 'DESC' }` | `{ field: 'id', order: 'DESC' }` | How to order the list of suggestions |
40+
| `enableGetChoices` | Optional | `({q: string}) => boolean` | `() => true` | Function taking the `filterValues` and returning a boolean to enable the `getList` call. |
41+
| `queryOptions` | Optional | [`UseQueryOptions`](https://tanstack.com/query/v4/docs/reference/useQuery?from=reactQueryV3&original=https://react-query-v3.tanstack.com/reference/useQuery) | `{}` | `react-query` client options |
4142

4243
**Note**: `<ReferenceInput>` doesn't accept the [common input props](./Inputs.md#common-input-props) (like `label`) ; it is the responsibility of the child component to apply them.
4344

@@ -79,7 +80,8 @@ You can make the `getList()` call lazy by using the `enableGetChoices` prop. Thi
7980
<ReferenceInput
8081
source="post_id"
8182
reference="posts"
82-
enableGetChoices={({ q }) => q.length >= 2} />
83+
enableGetChoices={({ q }) => q.length >= 2}
84+
/>
8385
```
8486

8587
## `filter`
@@ -166,6 +168,22 @@ Then to display a selector for the post author, you should call `<ReferenceInput
166168
<ReferenceInput source="author_id" reference="authors" />
167169
```
168170

171+
## queryOptions
172+
173+
Use [the `queryOptions` prop](#queryoptions) to pass [a custom `meta`](./Actions.md#meta-parameter) to the `dataProvider.getList()` call.
174+
175+
```jsx
176+
import { ReferenceInput, AutocompleteInput } from 'react-admin';
177+
178+
<ReferenceInput
179+
source="post_id"
180+
reference="posts"
181+
queryOptions={{ meta: { foo: 'bar' } }}
182+
>
183+
<AutocompleteInput label="Post" />
184+
</ReferenceInput>
185+
```
186+
169187
## Performance
170188

171189
Why does `<ReferenceInput>` use the `dataProvider.getMany()` method with a single value `[id]` instead of `dataProvider.getOne()` to fetch the record for the current value?

packages/ra-core/src/controller/input/useReferenceInputController.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ export const useReferenceInputController = <RecordType extends RaRecord = any>(
5959
reference,
6060
source,
6161
} = props;
62+
const { meta, ...otherQueryOptions } = queryOptions;
6263

6364
const [params, paramsModifiers] = useReferenceParams({
6465
resource: reference,
@@ -94,11 +95,12 @@ export const useReferenceInputController = <RecordType extends RaRecord = any>(
9495
},
9596
sort: { field: params.sort, order: params.order },
9697
filter: { ...params.filter, ...filter },
98+
meta,
9799
},
98100
{
99101
enabled: isGetMatchingEnabled,
100102
keepPreviousData: true,
101-
...queryOptions,
103+
...otherQueryOptions,
102104
}
103105
);
104106

@@ -186,7 +188,7 @@ export interface UseReferenceInputControllerParams<
186188
hasNextPage?: boolean;
187189
hasPreviousPage?: boolean;
188190
};
189-
}>;
191+
}> & { meta?: any };
190192
page?: number;
191193
perPage?: number;
192194
record?: RaRecord;

packages/ra-ui-materialui/src/input/ReferenceInput.spec.tsx

+33-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@ import * as React from 'react';
22
import expect from 'expect';
33
import { render, screen, waitFor } from '@testing-library/react';
44
import { QueryClient } from 'react-query';
5-
import { testDataProvider, useChoicesContext } from 'ra-core';
5+
import {
6+
testDataProvider,
7+
useChoicesContext,
8+
CoreAdminContext,
9+
Form,
10+
} from 'ra-core';
611

712
import { ReferenceInput } from './ReferenceInput';
813
import { AdminContext } from '../AdminContext';
@@ -96,4 +101,31 @@ describe('<ReferenceInput />', () => {
96101
expect(screen.getByLabelText('total').innerHTML).toEqual('2');
97102
});
98103
});
104+
105+
it('should accept meta in queryOptions', async () => {
106+
const getList = jest
107+
.fn()
108+
.mockImplementationOnce(() =>
109+
Promise.resolve({ data: [], total: 25 })
110+
);
111+
const dataProvider = testDataProvider({ getList });
112+
render(
113+
<CoreAdminContext dataProvider={dataProvider}>
114+
<Form>
115+
<ReferenceInput
116+
{...defaultProps}
117+
queryOptions={{ meta: { foo: 'bar' } }}
118+
/>
119+
</Form>
120+
</CoreAdminContext>
121+
);
122+
await waitFor(() => {
123+
expect(getList).toHaveBeenCalledWith('posts', {
124+
filter: {},
125+
pagination: { page: 1, perPage: 25 },
126+
sort: { field: 'id', order: 'DESC' },
127+
meta: { foo: 'bar' },
128+
});
129+
});
130+
});
99131
});

packages/ra-ui-materialui/src/input/ReferenceInput.tsx

+4-8
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
useReferenceInputController,
66
InputProps,
77
ResourceContextProvider,
8+
UseReferenceInputControllerParams,
89
} from 'ra-core';
910

1011
import { ReferenceError } from './ReferenceError';
@@ -118,15 +119,10 @@ ReferenceInput.defaultProps = {
118119
children: <AutocompleteInput />,
119120
};
120121

121-
export interface ReferenceInputProps extends InputProps {
122+
export interface ReferenceInputProps
123+
extends InputProps,
124+
UseReferenceInputControllerParams {
122125
children?: ReactElement;
123126
label?: string;
124-
page?: number;
125-
perPage?: number;
126-
reference: string;
127-
// @deprecated
128-
referenceSource?: (resource: string, source: string) => string;
129-
resource?: string;
130-
enableGetChoices?: (filters: any) => boolean;
131127
[key: string]: any;
132128
}

0 commit comments

Comments
 (0)