From 01fed1cd09841ced3681226f5d89251c83612c4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?An=C3=ADbal=20Svarcas?= Date: Fri, 23 Sep 2022 08:15:29 -0300 Subject: [PATCH 1/3] Fix ReferenceInput props type adding meta and record --- .../controller/input/useReferenceInputController.ts | 2 +- .../ra-ui-materialui/src/input/ReferenceInput.tsx | 12 ++++-------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/packages/ra-core/src/controller/input/useReferenceInputController.ts b/packages/ra-core/src/controller/input/useReferenceInputController.ts index 6144016a740..e1361799903 100644 --- a/packages/ra-core/src/controller/input/useReferenceInputController.ts +++ b/packages/ra-core/src/controller/input/useReferenceInputController.ts @@ -186,7 +186,7 @@ export interface UseReferenceInputControllerParams< hasNextPage?: boolean; hasPreviousPage?: boolean; }; - }>; + }> & { meta?: any }; page?: number; perPage?: number; record?: RaRecord; diff --git a/packages/ra-ui-materialui/src/input/ReferenceInput.tsx b/packages/ra-ui-materialui/src/input/ReferenceInput.tsx index 6fdb0c89b7d..6171f74aff0 100644 --- a/packages/ra-ui-materialui/src/input/ReferenceInput.tsx +++ b/packages/ra-ui-materialui/src/input/ReferenceInput.tsx @@ -5,6 +5,7 @@ import { useReferenceInputController, InputProps, ResourceContextProvider, + UseReferenceInputControllerParams, } from 'ra-core'; import { ReferenceError } from './ReferenceError'; @@ -118,15 +119,10 @@ ReferenceInput.defaultProps = { children: , }; -export interface ReferenceInputProps extends InputProps { +export interface ReferenceInputProps + extends InputProps, + UseReferenceInputControllerParams { children?: ReactElement; label?: string; - page?: number; - perPage?: number; - reference: string; - // @deprecated - referenceSource?: (resource: string, source: string) => string; - resource?: string; - enableGetChoices?: (filters: any) => boolean; [key: string]: any; } From f395d3821c87f63f873a8fa5915562ab7345c51d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?An=C3=ADbal=20Svarcas?= Date: Fri, 23 Sep 2022 08:30:58 -0300 Subject: [PATCH 2/3] Add documentation --- docs/ReferenceInput.md | 42 ++++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/docs/ReferenceInput.md b/docs/ReferenceInput.md index a272d8b9108..6dee154cf25 100644 --- a/docs/ReferenceInput.md +++ b/docs/ReferenceInput.md @@ -27,17 +27,18 @@ You can tweak how this component fetches the possible values using the `page`, ` ## Props -| Prop | Required | Type | Default | Description | -|--------------------|----------|---------------------------------------------|----------------------------------|------------------------------------------------------------------------------------------| -| `source` | Required | `string` | - | Name of the entity property to use for the input value | -| `label` | Optional | `string` | - | Useful only when `ReferenceInput` is in a Filter array, the label is used as the Filter label.| -| `reference` | Required | `string` | '' | Name of the reference resource, e.g. 'posts'. | -| `children` | Optional | `ReactNode` | `` | The actual selection component | -| `filter` | Optional | `Object` | `{}` | Permanent filters to use for getting the suggestion list | -| `page` | Optional | `number` | 1 | The current page number | -| `perPage` | Optional | `number` | 25 | Number of suggestions to show | -| `sort` | Optional | `{ field: String, order: 'ASC' or 'DESC' }` | `{ field: 'id', order: 'DESC' }` | How to order the list of suggestions | -| `enableGetChoices` | Optional | `({q: string}) => boolean` | `() => true` | Function taking the `filterValues` and returning a boolean to enable the `getList` call. | +| Prop | Required | Type | Default | Description | +|--------------------|----------|---------------------------------------------|----------------------------------|------------------------------------------------------------------------------------------------| +| `source` | Required | `string` | - | Name of the entity property to use for the input value | +| `label` | Optional | `string` | - | Useful only when `ReferenceInput` is in a Filter array, the label is used as the Filter label. | +| `reference` | Required | `string` | '' | Name of the reference resource, e.g. 'posts'. | +| `children` | Optional | `ReactNode` | `` | The actual selection component | +| `filter` | Optional | `Object` | `{}` | Permanent filters to use for getting the suggestion list | +| `page` | Optional | `number` | 1 | The current page number | +| `perPage` | Optional | `number` | 25 | Number of suggestions to show | +| `sort` | Optional | `{ field: String, order: 'ASC' or 'DESC' }` | `{ field: 'id', order: 'DESC' }` | How to order the list of suggestions | +| `enableGetChoices` | Optional | `({q: string}) => boolean` | `() => true` | Function taking the `filterValues` and returning a boolean to enable the `getList` call. | +| `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 | **Note**: `` 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. @@ -79,7 +80,8 @@ You can make the `getList()` call lazy by using the `enableGetChoices` prop. Thi q.length >= 2} /> + enableGetChoices={({ q }) => q.length >= 2} +/> ``` ## `filter` @@ -166,6 +168,22 @@ Then to display a selector for the post author, you should call ` ``` +## queryOptions + +Use [the `queryOptions` prop](#queryoptions) to pass [a custom `meta`](./Actions.md#meta-parameter) to the `dataProvider.getList()` call. + +```jsx +import { ReferenceInput, AutocompleteInput } from 'react-admin'; + + + + +``` + ## Performance Why does `` use the `dataProvider.getMany()` method with a single value `[id]` instead of `dataProvider.getOne()` to fetch the record for the current value? From 86fae5554b1fa933feb2b9b58d061e9b9abecf53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?An=C3=ADbal=20Svarcas?= Date: Fri, 23 Sep 2022 08:48:05 -0300 Subject: [PATCH 3/3] Add test --- .../input/useReferenceInputController.ts | 4 ++- .../src/input/ReferenceInput.spec.tsx | 34 ++++++++++++++++++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/packages/ra-core/src/controller/input/useReferenceInputController.ts b/packages/ra-core/src/controller/input/useReferenceInputController.ts index e1361799903..e43792e6160 100644 --- a/packages/ra-core/src/controller/input/useReferenceInputController.ts +++ b/packages/ra-core/src/controller/input/useReferenceInputController.ts @@ -59,6 +59,7 @@ export const useReferenceInputController = ( reference, source, } = props; + const { meta, ...otherQueryOptions } = queryOptions; const [params, paramsModifiers] = useReferenceParams({ resource: reference, @@ -94,11 +95,12 @@ export const useReferenceInputController = ( }, sort: { field: params.sort, order: params.order }, filter: { ...params.filter, ...filter }, + meta, }, { enabled: isGetMatchingEnabled, keepPreviousData: true, - ...queryOptions, + ...otherQueryOptions, } ); diff --git a/packages/ra-ui-materialui/src/input/ReferenceInput.spec.tsx b/packages/ra-ui-materialui/src/input/ReferenceInput.spec.tsx index fca6bf7374b..b78b8639f8e 100644 --- a/packages/ra-ui-materialui/src/input/ReferenceInput.spec.tsx +++ b/packages/ra-ui-materialui/src/input/ReferenceInput.spec.tsx @@ -2,7 +2,12 @@ import * as React from 'react'; import expect from 'expect'; import { render, screen, waitFor } from '@testing-library/react'; import { QueryClient } from 'react-query'; -import { testDataProvider, useChoicesContext } from 'ra-core'; +import { + testDataProvider, + useChoicesContext, + CoreAdminContext, + Form, +} from 'ra-core'; import { ReferenceInput } from './ReferenceInput'; import { AdminContext } from '../AdminContext'; @@ -96,4 +101,31 @@ describe('', () => { expect(screen.getByLabelText('total').innerHTML).toEqual('2'); }); }); + + it('should accept meta in queryOptions', async () => { + const getList = jest + .fn() + .mockImplementationOnce(() => + Promise.resolve({ data: [], total: 25 }) + ); + const dataProvider = testDataProvider({ getList }); + render( + +
+ + +
+ ); + await waitFor(() => { + expect(getList).toHaveBeenCalledWith('posts', { + filter: {}, + pagination: { page: 1, perPage: 25 }, + sort: { field: 'id', order: 'DESC' }, + meta: { foo: 'bar' }, + }); + }); + }); });