Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ReferenceOneField accept sort & filter props #8306

Merged
merged 1 commit into from
Oct 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 29 additions & 5 deletions docs/ReferenceOneField.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,37 @@ const BookShow = () => (

**Tip**: As with `<ReferenceField>`, you can call `<ReferenceOneField>` as many times as you need in the same component, react-admin will only make one call to `dataProvider.getManyReference()` per reference.

**Tip**: `<ReferenceOneField>` can also be used to display one record of a one-to-many relationship. Use `sort` and/or `filter` props to select the appropriate record to display. The first record will be displayed.

```jsx
const BookShow = () => (
<Show>
<SimpleShowLayout>
<TextField source="title" />
<DateField source="published_at" />
<ReferenceOneField
label="Latest cool review"
reference="book_reviews"
target="book_id"
sort={{ field: "createdAt", order: "DESC" }}
filter={{ rating: 5 }}
>
<TextField source="title" />
</ReferenceOneField>
</SimpleShowLayout>
</Show>
);
```

## Properties

| Prop | Required | Type | Default | Description |
| ------------ | -------- | ------------------ | -------------------------------- | ----------------------------------------------------------------------------------- |
| `children` | Optional | `Element` | - | The Field element used to render the referenced record |
| `link` | Optional | `string | Function` | `edit` | Target of the link wrapping the rendered child. Set to `false` to disable the link. |
| `reference` | Required | `string` | - | The name of the resource for the referenced records, e.g. 'book_details' |
| `target` | Required | string | - | Target field carrying the relationship on the referenced resource, e.g. 'book_id' |
| ------------ | -------- | ------------------------------------------- | -------------------------------- | ----------------------------------------------------------------------------------- |
| `children` | Optional | `Element` | - | The Field element used to render the referenced record |
| `link` | Optional | `string | Function` | `edit` | Target of the link wrapping the rendered child. Set to `false` to disable the link. |
| `reference` | Required | `string` | - | The name of the resource for the referenced records, e.g. 'book_details' |
| `target` | Required | string | - | Target field carrying the relationship on the referenced resource, e.g. 'book_id' |
| `sort` | Optional | `{ field: String, order: 'ASC' or 'DESC' }` | `{ field: 'id', order: 'ASC' }` | Used to order referenced records |
| `filter` | Optional | `Object` | `{}` | Used to filter referenced records |

`<ReferenceOneField>` also accepts the [common field props](./Fields.md#common-field-props), except `emptyText` (use the child `empty` prop instead).
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ describe('useReferenceOneFieldController', () => {
record={{ id: 123, name: 'James Joyce' }}
reference="bios"
target="author_id"
sort={{ field: 'name', order: 'DESC' }}
filter={{ gender: 'female' }}
>
{() => 'null'}
</ReferenceOneFieldController>
Expand All @@ -101,8 +103,8 @@ describe('useReferenceOneFieldController', () => {
target: 'author_id',
id: 123,
pagination: { page: 1, perPage: 1 },
sort: { field: 'id', order: 'ASC' },
filter: {},
sort: { field: 'name', order: 'DESC' },
filter: { gender: 'female' },
});
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@ import get from 'lodash/get';

import { useGetManyReference } from '../../dataProvider';
import { useNotify } from '../../notification';
import { RaRecord } from '../../types';
import { RaRecord, SortPayload } from '../../types';
import { UseReferenceResult } from '../useReference';

export interface UseReferenceOneFieldControllerParams {
record?: RaRecord;
reference: string;
source?: string;
target: string;
sort?: SortPayload;
filter?: any;
}

/**
Expand All @@ -31,13 +33,21 @@ export interface UseReferenceOneFieldControllerParams {
* @prop {string} props.reference The linked resource name
* @prop {string} props.target The target resource key
* @prop {string} props.source The key current record identifier ('id' by default)
*
* @prop {Object} props.sort The sort to apply to the referenced records
* @prop {Object} props.filter The filter to apply to the referenced records
* @returns {UseReferenceResult} The request state. Destructure as { referenceRecord, isLoading, error }.
*/
export const useReferenceOneFieldController = (
props: UseReferenceOneFieldControllerParams
): UseReferenceResult => {
const { reference, record, target, source = 'id' } = props;
const {
reference,
record,
target,
source = 'id',
sort = { field: 'id', order: 'ASC' },
filter = {},
} = props;
const notify = useNotify();

const { data, error, isFetching, isLoading, refetch } = useGetManyReference(
Expand All @@ -46,8 +56,8 @@ export const useReferenceOneFieldController = (
target,
id: get(record, source),
pagination: { page: 1, perPage: 1 },
sort: { field: 'id', order: 'ASC' },
filter: {},
sort,
filter,
},
{
enabled: !!record,
Expand Down
7 changes: 7 additions & 0 deletions packages/ra-ui-materialui/src/field/ReferenceOneField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
LinkToType,
useCreatePath,
useTranslate,
SortPayload,
} from 'ra-core';

import { PublicFieldProps, fieldPropTypes, InjectedFieldProps } from './types';
Expand All @@ -30,6 +31,8 @@ export const ReferenceOneField = (props: ReferenceOneFieldProps) => {
source,
target,
emptyText,
sort,
filter,
link = false,
} = props;
const record = useRecordContext(props);
Expand All @@ -47,6 +50,8 @@ export const ReferenceOneField = (props: ReferenceOneFieldProps) => {
reference,
source,
target,
sort,
filter,
});

const resourceLinkPath =
Expand Down Expand Up @@ -90,6 +95,8 @@ export interface ReferenceOneFieldProps
children?: ReactNode;
reference: string;
target: string;
sort?: SortPayload;
filter?: any;
link?: LinkToType;
}

Expand Down