From 2373c2c1b9aeb3fa3291cc7039bed58b553963f9 Mon Sep 17 00:00:00 2001
From: Gildas Garcia <1122076+djhi@users.noreply.github.com>
Date: Tue, 6 Aug 2024 16:10:34 +0200
Subject: [PATCH] Fix ReferenceManyField does not allow to override store key
for its children selection
---
.../useReferenceManyFieldController.spec.tsx | 38 ++++++++++++++
.../field/useReferenceManyFieldController.ts | 50 ++++++++++---------
.../src/field/ReferenceManyField.stories.tsx | 32 +++++++++++-
.../src/field/ReferenceManyField.tsx | 21 ++------
4 files changed, 100 insertions(+), 41 deletions(-)
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 = {};