Skip to content

Commit 0c8b36b

Browse files
authored
Merge pull request #8899 from marmelab/fix-reference-field-link-function
Fix ReferenceField link function is called with referencing record
2 parents dadd6b6 + 8733b28 commit 0c8b36b

File tree

3 files changed

+66
-25
lines changed

3 files changed

+66
-25
lines changed

packages/ra-ui-materialui/src/field/ReferenceField.spec.tsx

+41
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,47 @@ describe('<ReferenceField />', () => {
572572
expect(screen.queryAllByRole('link')).toHaveLength(0);
573573
});
574574

575+
it('should call the link function with the referenced record', async () => {
576+
const dataProvider = testDataProvider({
577+
getMany: jest.fn().mockResolvedValue({
578+
data: [{ id: 123, title: 'foo' }],
579+
}),
580+
});
581+
const link = jest.fn().mockReturnValue('/posts/123');
582+
583+
render(
584+
<ThemeProvider theme={theme}>
585+
<CoreAdminContext dataProvider={dataProvider}>
586+
<ResourceDefinitionContextProvider
587+
definitions={{
588+
posts: {
589+
hasEdit: true,
590+
},
591+
}}
592+
>
593+
<ReferenceField
594+
record={record}
595+
resource="comments"
596+
source="postId"
597+
reference="posts"
598+
link={link}
599+
>
600+
<TextField source="title" />
601+
</ReferenceField>
602+
</ResourceDefinitionContextProvider>
603+
</CoreAdminContext>
604+
</ThemeProvider>
605+
);
606+
await waitFor(() =>
607+
expect(dataProvider.getMany).toHaveBeenCalledTimes(1)
608+
);
609+
expect(screen.queryByRole('link')?.getAttribute('href')).toBe(
610+
'#/posts/123'
611+
);
612+
613+
expect(link).toHaveBeenCalledWith({ id: 123, title: 'foo' }, 'posts');
614+
});
615+
575616
it('should accept multiple children', async () => {
576617
render(<Children />);
577618
expect(screen.findByText('9780393966473')).not.toBeNull();

packages/ra-ui-materialui/src/field/ReferenceField.tsx

+24-24
Original file line numberDiff line numberDiff line change
@@ -120,24 +120,7 @@ export interface ReferenceFieldProps<RecordType extends RaRecord = any>
120120
*/
121121
export const NonEmptyReferenceField: FC<
122122
Omit<ReferenceFieldProps, 'source'> & { id: Identifier }
123-
> = ({ children, id, record, reference, link, ...props }) => {
124-
const createPath = useCreatePath();
125-
const resourceDefinition = useResourceDefinition({ resource: reference });
126-
127-
const resourceLinkPath =
128-
link === false ||
129-
(link === 'edit' && !resourceDefinition.hasEdit) ||
130-
(link === 'show' && !resourceDefinition.hasShow)
131-
? false
132-
: createPath({
133-
resource: reference,
134-
id,
135-
type:
136-
typeof link === 'function'
137-
? link(record, reference)
138-
: link,
139-
});
140-
123+
> = ({ children, id, record, reference, ...props }) => {
141124
return (
142125
<ResourceContextProvider value={reference}>
143126
<PureReferenceFieldView
@@ -147,7 +130,6 @@ export const NonEmptyReferenceField: FC<
147130
reference,
148131
id,
149132
})}
150-
resourceLinkPath={resourceLinkPath}
151133
>
152134
{children}
153135
</PureReferenceFieldView>
@@ -167,11 +149,13 @@ export const ReferenceFieldView: FC<ReferenceFieldViewProps> = props => {
167149
isLoading,
168150
reference,
169151
referenceRecord,
170-
resourceLinkPath,
152+
link,
171153
sx,
172154
} = props;
173155
const getRecordRepresentation = useGetRecordRepresentation(reference);
174156
const translate = useTranslate();
157+
const createPath = useCreatePath();
158+
const resourceDefinition = useResourceDefinition({ resource: reference });
175159

176160
if (error) {
177161
return (
@@ -194,6 +178,20 @@ export const ReferenceFieldView: FC<ReferenceFieldViewProps> = props => {
194178
) : null;
195179
}
196180

181+
const resourceLinkPath =
182+
link === false ||
183+
(link === 'edit' && !resourceDefinition.hasEdit) ||
184+
(link === 'show' && !resourceDefinition.hasShow)
185+
? false
186+
: createPath({
187+
resource: reference,
188+
id: referenceRecord.id,
189+
type:
190+
typeof link === 'function'
191+
? link(referenceRecord, reference)
192+
: link,
193+
});
194+
197195
let child = children || (
198196
<Typography component="span" variant="body2">
199197
{getRecordRepresentation(referenceRecord)}
@@ -227,10 +225,12 @@ ReferenceFieldView.propTypes = {
227225
reference: PropTypes.string,
228226
referenceRecord: PropTypes.any,
229227
resource: PropTypes.string,
230-
resourceLinkPath: PropTypes.oneOfType([
228+
// @ts-ignore
229+
link: PropTypes.oneOfType([
231230
PropTypes.string,
232-
PropTypes.oneOf([false]),
233-
]) as React.Validator<string | false>,
231+
PropTypes.bool,
232+
PropTypes.func,
233+
]),
234234
source: PropTypes.string,
235235
translateChoice: PropTypes.oneOfType([PropTypes.func, PropTypes.bool]),
236236
};
@@ -242,7 +242,7 @@ export interface ReferenceFieldViewProps
242242
reference: string;
243243
resource?: string;
244244
translateChoice?: Function | boolean;
245-
resourceLinkPath?: string | false;
245+
link?: LinkToType;
246246
children?: ReactNode;
247247
sx?: SxProps;
248248
}

packages/ra-ui-materialui/src/field/ReferenceOneField.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ export const ReferenceOneField = <RecordType extends RaRecord = any>(
8484
isLoading={isLoading}
8585
isFetching={isFetching}
8686
referenceRecord={referenceRecord}
87-
resourceLinkPath={resourceLinkPath}
87+
link={resourceLinkPath}
8888
reference={reference}
8989
refetch={refetch}
9090
error={error}

0 commit comments

Comments
 (0)