Skip to content

Commit

Permalink
Merge pull request #10132 from marmelab/fix-reference-many-field-data…
Browse files Browse the repository at this point in the history
…grid-share-selections

Fix ReferenceManyField does not allow to override store key for its children selection
  • Loading branch information
fzaninotto authored Aug 7, 2024
2 parents 0929902 + 2373c2c commit 785a419
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -326,4 +327,41 @@ describe('useReferenceManyFieldController', () => {
signal: undefined,
});
});

it('should support custom storeKey', async () => {
const store = memoryStore();
const setStore = jest.spyOn(store, 'setItem');

render(
<CoreAdminContext store={store}>
<ReferenceManyFieldController
resource="authors"
source="uniqueName"
record={{
id: 123,
uniqueName: 'jamesjoyce256',
name: 'James Joyce',
}}
reference="books"
target="author_id"
storeKey="customKey"
>
{({ onToggleItem }) => {
return (
<button onClick={() => onToggleItem(123)}>
Toggle
</button>
);
}}
</ReferenceManyFieldController>
</CoreAdminContext>
);

fireEvent.click(await screen.findByText('Toggle'));
await waitFor(() => {
expect(setStore).toHaveBeenCalledWith('customKey.selectedIds', [
123,
]);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -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
*
Expand Down Expand Up @@ -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
Expand All @@ -109,7 +88,7 @@ export const useReferenceManyFieldController = <

// selection logic
const [selectedIds, selectionModifiers] = useRecordSelection({
resource: `${resource}.${record?.id}.${reference}`,
resource: storeKey,
});

// filter logic
Expand Down Expand Up @@ -253,3 +232,26 @@ export const useReferenceManyFieldController = <
total,
} as ListControllerResult<ReferenceRecordType>;
};

export interface UseReferenceManyFieldControllerParams<
RecordType extends Record<string, any> = Record<string, any>,
ReferenceRecordType extends Record<string, any> = Record<string, any>,
> {
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 = {};
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -117,3 +117,33 @@ export const WithMeta = () => (
</ReferenceManyField>
</Wrapper>
);

export const StoreKey = () => (
<Wrapper>
<Stack direction="row" spacing={2}>
<ReferenceManyField
reference="books"
target="author_id"
queryOptions={{
meta: { foo: 'bar' },
}}
>
<Datagrid>
<TextField source="title" />
</Datagrid>
</ReferenceManyField>
<ReferenceManyField
reference="books"
target="author_id"
queryOptions={{
meta: { foo: 'bar' },
}}
storeKey="custom"
>
<Datagrid>
<TextField source="title" />
</Datagrid>
</ReferenceManyField>
</Stack>
</Wrapper>
);
21 changes: 5 additions & 16 deletions packages/ra-ui-materialui/src/field/ReferenceManyField.tsx
Original file line number Diff line number Diff line change
@@ -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';

Expand Down Expand Up @@ -75,6 +73,7 @@ export const ReferenceManyField = <
resource,
sort = defaultSort,
source = 'id',
storeKey,
target,
queryOptions,
} = props;
Expand All @@ -93,6 +92,7 @@ export const ReferenceManyField = <
resource,
sort,
source,
storeKey,
target,
queryOptions,
});
Expand All @@ -110,21 +110,10 @@ export const ReferenceManyField = <
export interface ReferenceManyFieldProps<
RecordType extends Record<string, any> = Record<string, any>,
ReferenceRecordType extends Record<string, any> = Record<string, any>,
> extends Omit<FieldProps<RecordType>, 'source'> {
> extends Omit<FieldProps<RecordType>, 'source'>,
UseReferenceManyFieldControllerParams<RecordType, ReferenceRecordType> {
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 = {};
Expand Down

0 comments on commit 785a419

Please sign in to comment.