diff --git a/packages/ra-core/src/controller/field/useReferenceManyFieldController.spec.tsx b/packages/ra-core/src/controller/field/useReferenceManyFieldController.spec.tsx index f2ae6c31cb4..2104545f1d7 100644 --- a/packages/ra-core/src/controller/field/useReferenceManyFieldController.spec.tsx +++ b/packages/ra-core/src/controller/field/useReferenceManyFieldController.spec.tsx @@ -5,6 +5,7 @@ import expect from 'expect'; import { testDataProvider } from '../../dataProvider/testDataProvider'; import { CoreAdminContext } from '../../core'; import { useReferenceManyFieldController } from './useReferenceManyFieldController'; +import { memoryStore } from '../../store'; const ReferenceManyFieldController = props => { const { children, page = 1, perPage = 25, ...rest } = props; @@ -326,4 +327,41 @@ describe('useReferenceManyFieldController', () => { signal: undefined, }); }); + + it('should support custom storeKey', async () => { + const store = memoryStore(); + const setStore = jest.spyOn(store, 'setItem'); + + render( + + + {({ onToggleItem }) => { + return ( + + ); + }} + + + ); + + fireEvent.click(await screen.findByText('Toggle')); + await waitFor(() => { + expect(setStore).toHaveBeenCalledWith('customKey.selectedIds', [ + 123, + ]); + }); + }); }); diff --git a/packages/ra-core/src/controller/field/useReferenceManyFieldController.ts b/packages/ra-core/src/controller/field/useReferenceManyFieldController.ts index ec8ca0aff26..d64f0b587f4 100644 --- a/packages/ra-core/src/controller/field/useReferenceManyFieldController.ts +++ b/packages/ra-core/src/controller/field/useReferenceManyFieldController.ts @@ -7,35 +7,13 @@ import lodashDebounce from 'lodash/debounce'; import { useSafeSetState, removeEmpty } from '../../util'; import { useGetManyReference } from '../../dataProvider'; import { useNotify } from '../../notification'; -import { Identifier, RaRecord, SortPayload } from '../../types'; +import { FilterPayload, Identifier, RaRecord, SortPayload } from '../../types'; import { ListControllerResult } from '../list'; import usePaginationState from '../usePaginationState'; import { useRecordSelection } from '../list/useRecordSelection'; import useSortState from '../useSortState'; import { useResourceContext } from '../../core'; -export interface UseReferenceManyFieldControllerParams< - RecordType extends RaRecord = RaRecord, - ReferenceRecordType extends RaRecord = RaRecord, -> { - debounce?: number; - filter?: any; - page?: number; - perPage?: number; - record?: RecordType; - reference: string; - resource?: string; - sort?: SortPayload; - source?: string; - target: string; - queryOptions?: UseQueryOptions< - { data: ReferenceRecordType[]; total: number }, - Error - >; -} - -const defaultFilter = {}; - /** * Fetch reference records, and return them when available * @@ -89,6 +67,7 @@ export const useReferenceManyFieldController = < } = props; const notify = useNotify(); const resource = useResourceContext(props); + const storeKey = props.storeKey ?? `${resource}.${record?.id}.${reference}`; const { meta, ...otherQueryOptions } = queryOptions; // pagination logic @@ -109,7 +88,7 @@ export const useReferenceManyFieldController = < // selection logic const [selectedIds, selectionModifiers] = useRecordSelection({ - resource: `${resource}.${record?.id}.${reference}`, + resource: storeKey, }); // filter logic @@ -253,3 +232,26 @@ export const useReferenceManyFieldController = < total, } as ListControllerResult; }; + +export interface UseReferenceManyFieldControllerParams< + RecordType extends Record = Record, + ReferenceRecordType extends Record = Record, +> { + debounce?: number; + filter?: FilterPayload; + page?: number; + perPage?: number; + record?: RecordType; + reference: string; + resource?: string; + sort?: SortPayload; + source?: string; + storeKey?: string; + target: string; + queryOptions?: Omit< + UseQueryOptions<{ data: ReferenceRecordType[]; total: number }, Error>, + 'queryKey' | 'queryFn' + >; +} + +const defaultFilter = {}; diff --git a/packages/ra-ui-materialui/src/field/ReferenceManyField.stories.tsx b/packages/ra-ui-materialui/src/field/ReferenceManyField.stories.tsx index 6e50f08e2b4..7437ff1a865 100644 --- a/packages/ra-ui-materialui/src/field/ReferenceManyField.stories.tsx +++ b/packages/ra-ui-materialui/src/field/ReferenceManyField.stories.tsx @@ -5,7 +5,7 @@ import { RecordContextProvider, ResourceContextProvider, } from 'ra-core'; -import { ThemeProvider, Box } from '@mui/material'; +import { ThemeProvider, Box, Stack } from '@mui/material'; import { createTheme } from '@mui/material/styles'; import { TextField } from '../field'; @@ -117,3 +117,33 @@ export const WithMeta = () => ( ); + +export const StoreKey = () => ( + + + + + + + + + + + + + + +); diff --git a/packages/ra-ui-materialui/src/field/ReferenceManyField.tsx b/packages/ra-ui-materialui/src/field/ReferenceManyField.tsx index a0400209f9b..1413ca20515 100644 --- a/packages/ra-ui-materialui/src/field/ReferenceManyField.tsx +++ b/packages/ra-ui-materialui/src/field/ReferenceManyField.tsx @@ -1,14 +1,12 @@ import React, { ReactElement, ReactNode } from 'react'; import { - FilterPayload, - SortPayload, useReferenceManyFieldController, ListContextProvider, ResourceContextProvider, useRecordContext, RaRecord, + UseReferenceManyFieldControllerParams, } from 'ra-core'; -import { UseQueryOptions } from '@tanstack/react-query'; import { FieldProps } from './types'; @@ -75,6 +73,7 @@ export const ReferenceManyField = < resource, sort = defaultSort, source = 'id', + storeKey, target, queryOptions, } = props; @@ -93,6 +92,7 @@ export const ReferenceManyField = < resource, sort, source, + storeKey, target, queryOptions, }); @@ -110,21 +110,10 @@ export const ReferenceManyField = < export interface ReferenceManyFieldProps< RecordType extends Record = Record, ReferenceRecordType extends Record = Record, -> extends Omit, 'source'> { +> extends Omit, 'source'>, + UseReferenceManyFieldControllerParams { children: ReactNode; - debounce?: number; - filter?: FilterPayload; - page?: number; pagination?: ReactElement; - perPage?: number; - reference: string; - sort?: SortPayload; - source?: string; - target: string; - queryOptions?: UseQueryOptions< - { data: ReferenceRecordType[]; total: number }, - Error - >; } const defaultFilter = {};