-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
Add render prop to page and reference base components #10832
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
Merged
Merged
Changes from all commits
Commits
Show all changes
41 commits
Select commit
Hold shift + click to select a range
e3aecf1
add render props to ListBase component
ThieryMichel 14652d4
add render props to InfiniteListBase component
ThieryMichel 4619f16
add tests
ThieryMichel 8ce9450
add render props to EditBase component
ThieryMichel 6511b2e
add render props to CreateBase component
ThieryMichel bf3897d
add render props to ShowBase component
ThieryMichel e03818e
add render props to ReferenceFIeldBase component
ThieryMichel bcfa72a
add render prop on ReferenceManyFieldBase
ThieryMichel 04b3085
add render prop on ReferenceOneFieldBase
ThieryMichel 4e0ebea
create ReferenceArrayFieldBase and use it in MUI ReferenceArrayField
ThieryMichel 730f556
add render prop on ReferenceArrayFieldBase
ThieryMichel 3ae7f98
code review applied
ThieryMichel 4d1c035
add check on render and children on all referenceBase field
ThieryMichel d385168
add doc for ReferenceFieldBase
ThieryMichel a78f838
add doc for ReferenceManyFieldBase
ThieryMichel 665c58d
remove unneeded renderPagination prop from ReferenceManyFieldBase
ThieryMichel b39185d
remove unneeded renderPagination from ReferenceArrayFieldBase
ThieryMichel 70b260c
add doc on ReferenceArrayFieldBase
ThieryMichel 58b7a55
add doc on ReferenceManyFieldBase
ThieryMichel 59bc05e
stop referring mui component in ReferenceFieldBase doc, move section …
ThieryMichel d7d1d0b
fix type
ThieryMichel 8b256f5
rename ra-core FieldProps to FieldPropsBase
ThieryMichel 68637c0
fix render type in doc
ThieryMichel 60eaf37
fix ra-core/controller/field/ReferenceOneFieldBase story name
ThieryMichel 8c08dec
code review
ThieryMichel 8c95570
remove pagination prop from ReferenceArrayFieldBase and ReferenceMany…
ThieryMichel 2f655d4
use context instead of controllerContext
ThieryMichel 4a2d425
add missing pagination on mui reference many and array
ThieryMichel f3794b3
remove mui components from ReferenceManyFieldBase doc. Add example of…
ThieryMichel 555d093
remove mui components from ReferenceFieldBase doc.
ThieryMichel 9dbb604
remove mui components from ReferenceArrayFieldBase doc.
ThieryMichel f8f8465
remove mui components from ReferenceOneFieldBase doc.
ThieryMichel 8046b0e
move pagination on ReferenceManyField side
ThieryMichel ab82156
Add optional loading, error and empty props to ReferenceBase commponents
fzaninotto ef70578
Improve ListBase doc
fzaninotto 10a52cf
Misc doc fixes
fzaninotto a701965
Fix types
fzaninotto 979444c
Fix base stories and doc
fzaninotto c6911a0
Add context to render empty, error and loading components
fzaninotto 64d2806
Fix cannot override ReferenceArrayField props via theme anymore
fzaninotto 0aba5d4
Improve readability
fzaninotto File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,226 @@ | ||
| --- | ||
| layout: default | ||
| title: "The ReferenceArrayFieldBase Component" | ||
| storybook_path: ra-core-fields-referencearrayfieldbase--basic | ||
| --- | ||
|
|
||
| # `<ReferenceArrayFieldBase>` | ||
|
|
||
| Use `<ReferenceArrayFieldBase>` to display a list of related records, via a one-to-many relationship materialized by an array of foreign keys. | ||
|
|
||
| `<ReferenceArrayFieldBase>` fetches a list of referenced records (using the `dataProvider.getMany()` method), and puts them in a [`ListContext`](./useListContext.md). This component is headless, and its children need to use the data from this context to render the desired ui. | ||
|
|
||
| **Tip**: For a rendering a list of chips by default, use [the `<ReferenceArrayField>` component](./ReferenceArrayField.md) instead. | ||
|
|
||
| **Tip**: If the relationship is materialized by a foreign key on the referenced resource, use [the `<ReferenceManyFieldBase>` component](./ReferenceManyFieldBase.md) instead. | ||
|
|
||
| ## Usage | ||
|
|
||
| For instance, let's consider a model where a `post` has many `tags`, materialized to a `tags_ids` field containing an array of ids: | ||
|
|
||
| ``` | ||
| ┌──────────────┐ ┌────────┐ | ||
| │ posts │ │ tags │ | ||
| │--------------│ │--------│ | ||
| │ id │ ┌───│ id │ | ||
| │ title │ │ │ name │ | ||
| │ body │ │ └────────┘ | ||
| │ is_published │ │ | ||
| │ tag_ids │╾──┘ | ||
| └──────────────┘ | ||
| ``` | ||
|
|
||
| A typical `post` record therefore looks like this: | ||
|
|
||
| ```json | ||
| { | ||
| "id": 1, | ||
| "title": "Hello world", | ||
| "body": "...", | ||
| "is_published": true, | ||
| "tags_ids": [1, 2, 3] | ||
| } | ||
| ``` | ||
|
|
||
| In that case, use `<ReferenceArrayFieldBase>` to display the post tag names as a list of chips, as follows: | ||
|
|
||
| ```jsx | ||
| import { ListBase, ListIterator, ReferenceArrayFieldBase } from 'react-admin'; | ||
|
|
||
| export const PostList = () => ( | ||
| <ListBase> | ||
| <ListIterator> | ||
| <ReferenceArrayFieldBase reference="tags" source="tag_ids"> | ||
| <TagList /> | ||
| </ReferenceArrayFieldBase> | ||
| </ListIterator> | ||
| </ListBase> | ||
| ); | ||
|
|
||
| const TagList = (props: { children: React.ReactNode }) => { | ||
| const context = useListContext(); | ||
|
|
||
| if (context.isPending) { | ||
| return <p>Loading...</p>; | ||
| } | ||
|
|
||
| if (context.error) { | ||
| return <p className="error">{context.error.toString()}</p>; | ||
| } | ||
| return ( | ||
| <p> | ||
| {listContext.data?.map((tag, index) => ( | ||
| <li key={index}>{tag.name}</li> | ||
| ))} | ||
| </p> | ||
| ); | ||
| }; | ||
| ``` | ||
|
|
||
| `<ReferenceArrayFieldBase>` expects a `reference` attribute, which specifies the resource to fetch for the related records. It also expects a `source` attribute, which defines the field containing the list of ids to look for in the referenced resource. | ||
|
|
||
| `<ReferenceArrayFieldBase>` fetches the `tag` resources related to each `post` resource by matching `post.tag_ids` to `tag.id`. | ||
|
|
||
| You can change how the list of related records is rendered by passing a custom child reading the `ListContext` (e.g. a [`<DataTable>`](./DataTable.md)) or a render function prop. See the [`children`](#children) and the [`render`](#render) sections for details. | ||
|
|
||
| ## Props | ||
|
|
||
| | Prop | Required | Type | Default | Description | | ||
| | -------------- | -------- | --------------------------------------------------------------------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------ | | ||
| | `source` | Required | `string` | - | Name of the property to display | | ||
| | `reference` | Required | `string` | - | The name of the resource for the referenced records, e.g. 'tags' | | ||
| | `children` | Optional\* | `Element` | | One or several elements that render a list of records based on a `ListContext` | | ||
| | `render` | Optional\* | `(ListContext) => Element` | | A function that takes a list context and renders a list of records | | ||
| | `filter` | Optional | `Object` | - | Filters to use when fetching the related records (the filtering is done client-side) | | ||
| | `perPage` | Optional | `number` | 1000 | Maximum number of results to display | | ||
| | `queryOptions` | Optional | [`UseQuery Options`](https://tanstack.com/query/v5/docs/react/reference/useQuery) | `{}` | `react-query` options for the `getMany` query | | ||
| | `sort` | Optional | `{ field, order }` | `{ field: 'id', order: 'DESC' }` | Sort order to use when displaying the related records (the sort is done client-side) | | ||
| | `sortBy` | Optional | `string | Function` | `source` | When used in a `List`, name of the field to use for sorting when the user clicks on the column header. | | ||
|
|
||
| \* Either one of children or render is required. | ||
|
|
||
| ## `children` | ||
|
|
||
| You can pass any React component as child, to render the list of related records based on the `ListContext`. | ||
|
|
||
| ```jsx | ||
| <ReferenceArrayFieldBase label="Tags" reference="tags" source="tag_ids"> | ||
| <TagList /> | ||
| </ReferenceArrayFieldBase> | ||
|
|
||
| const TagList = (props: { children: React.ReactNode }) => { | ||
| const { isPending, error, data } = useListContext(); | ||
|
|
||
| if (isPending) { | ||
| return <p>Loading...</p>; | ||
| } | ||
|
|
||
| if (error) { | ||
| return <p className="error">{error.toString()}</p>; | ||
| } | ||
| return ( | ||
| <p> | ||
| {data?.map((tag, index) => ( | ||
| <li key={index}>{tag.name}</li> | ||
| ))} | ||
| </p> | ||
| ); | ||
| }; | ||
| ``` | ||
|
|
||
| ## `render` | ||
|
|
||
| Alternatively to `children`, you can pass a `render` function prop to `<ReferenceArrayFieldBase>`. The `render` prop will receive the `ListContext` as its argument, allowing to inline the rendering logic. | ||
|
|
||
| ```jsx | ||
| <ReferenceArrayFieldBase | ||
| label="Tags" | ||
| reference="tags" | ||
| source="tag_ids" | ||
| render={({ isPending, error, data }) => { | ||
| if (isPending) { | ||
| return <p>Loading...</p>; | ||
| } | ||
| if (error) { | ||
| return <p className="error">{error.toString()}</p>; | ||
| } | ||
| return ( | ||
| <p> | ||
| {data.map((tag, index) => ( | ||
| <li key={index}>{tag.name}</li> | ||
| ))} | ||
| </p> | ||
| ); | ||
| }} | ||
| /> | ||
| ``` | ||
|
|
||
| **Tip**: When receiving a `render` prop, the `<ReferenceArrayFieldBase>` component will ignore the `children` property. | ||
|
|
||
| ## `filter` | ||
|
|
||
| `<ReferenceArrayFieldBase>` fetches all the related records, and displays them all, too. You can use the `filter` prop to filter the list of related records to display (this works by filtering the records client-side, after the fetch). | ||
|
|
||
| For instance, to render only tags that are 'published', you can use the following code: | ||
|
|
||
| {% raw %} | ||
| ```jsx | ||
| <ReferenceArrayFieldBase | ||
| label="Tags" | ||
| source="tag_ids" | ||
| reference="tags" | ||
| filter={{ is_published: true }} | ||
| /> | ||
| ``` | ||
| {% endraw %} | ||
|
|
||
| ## `perPage` | ||
|
|
||
| `<ReferenceArrayFieldBase>` fetches *all* the related fields, and puts them all in a `ListContext`. If a record has a large number of related records, it may be a good idea to limit the number of displayed records. The `perPage` prop allows to create a client-side pagination for the related records. | ||
|
|
||
| For instance, to limit the display of related records to 10, you can use the following code: | ||
|
|
||
| ```jsx | ||
| <ReferenceArrayFieldBase label="Tags" source="tag_ids" reference="tags" perPage={10} /> | ||
| ``` | ||
|
|
||
| ## `queryOptions` | ||
|
|
||
| Use the `queryOptions` prop to pass options to [the `dataProvider.getMany()` query](./useGetOne.md#aggregating-getone-calls) that fetches the referenced record. | ||
|
|
||
| For instance, to pass [a custom `meta`](./Actions.md#meta-parameter): | ||
|
|
||
| {% raw %} | ||
| ```jsx | ||
| <ReferenceArrayFieldBase queryOptions={{ meta: { foo: 'bar' } }} /> | ||
| ``` | ||
| {% endraw %} | ||
|
|
||
| ## `reference` | ||
|
|
||
| The resource to fetch for the relateds record. | ||
|
|
||
| For instance, if the `posts` resource has a `tag_ids` field, set the `reference` to `tags` to fetch the tags related to each post. | ||
|
|
||
| ```jsx | ||
| <ReferenceArrayFieldBase label="Tags" source="tag_ids" reference="tags" /> | ||
| ``` | ||
|
|
||
| ## `sort` | ||
|
|
||
| By default, the related records are displayed in the order in which they appear in the `source`. For instance, if the current record is `{ id: 1234, title: 'Lorem Ipsum', tag_ids: [1, 23, 4] }`, a `<ReferenceArrayFieldBase>` on the `tag_ids` field will display tags in the order 1, 23, 4. | ||
|
|
||
| `<ReferenceArrayFieldBase>` can force a different order (via a client-side sort after fetch) if you specify a `sort` prop. | ||
|
|
||
| For instance, to sort tags by title in ascending order, you can use the following code: | ||
|
|
||
| {% raw %} | ||
| ```jsx | ||
| <ReferenceArrayFieldBase | ||
| label="Tags" | ||
| source="tag_ids" | ||
| reference="tags" | ||
| sort={{ field: 'title', order: 'ASC' }} | ||
| /> | ||
| ``` | ||
| {% endraw %} | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.