Skip to content

Commit

Permalink
ReferenceOneField accept sort & filter props
Browse files Browse the repository at this point in the history
  • Loading branch information
nicgirault committed Oct 25, 2022
1 parent 520a59c commit f22f8d0
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 13 deletions.
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
1 change: 0 additions & 1 deletion packages/ra-ui-materialui/src/field/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { TableCellProps } from '@mui/material/TableCell';

type TextAlign = TableCellProps['align'];
type SortOrder = 'ASC' | 'DESC';

export interface FieldProps<RecordType extends RaRecord = any>
extends PublicFieldProps,
InjectedFieldProps<RecordType> {}
Expand Down

0 comments on commit f22f8d0

Please sign in to comment.