Skip to content

Commit c7031fc

Browse files
authored
Merge pull request #11192 from marmelab/docs-arrayfieldbase-headless
[Doc] Add ArrayFieldBase headless documentation
2 parents 8e725c8 + c9f2412 commit c7031fc

6 files changed

Lines changed: 178 additions & 154 deletions

File tree

docs/ArrayField.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ storybook_path: ra-ui-materialui-fields-arrayfield--basic
1212

1313
`<ArrayField>` creates a [`ListContext`](./useListContext.md) with the field value, and renders its children components - usually iterator components like [`<DataTable>`](./DataTable.md) or [`<SingleFieldList>`](./SingleFieldList.md).
1414

15-
`<ArrayField>` is the Material UI export of the headless [`<ArrayFieldBase>`](./ArrayFieldBase.md) component from `ra-core`.
15+
`<ArrayField>` is the Material UI export of the headless [`<ArrayFieldBase>`](https://marmelab.com/ra-core/arrayfieldbase/) component from `ra-core`.
1616

1717
## Usage
1818

docs/ArrayFieldBase.md

Lines changed: 0 additions & 152 deletions
This file was deleted.

docs_headless/astro.config.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ export default defineConfig({
180180
items: [
181181
'fields',
182182
'fieldsforrelationships',
183+
'arrayfieldbase',
183184
'referencearrayfieldbase',
184185
'referencefieldbase',
185186
'referencemanycountbase',
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
---
2+
layout: default
3+
title: "<ArrayFieldBase>"
4+
---
5+
6+
Use `<ArrayFieldBase>` to display an embedded array of objects from the current record.
7+
8+
`<ArrayFieldBase>` reads the array field value from the current [`RecordContext`](./useRecordContext.md), creates a [`ListContext`](./useListContext.md) from it, and renders its children. This component is headless, so its children need to use that list context to render the desired UI.
9+
10+
**Tip**: Use [`<ReferenceArrayFieldBase>`](./ReferenceArrayFieldBase.md) when the array contains foreign keys to another resource. Use `<ArrayFieldBase>` when the array already contains the embedded objects to display.
11+
12+
## Usage
13+
14+
`<ArrayFieldBase>` is ideal for collections of embedded objects, like `tags` and `backlinks` in the following `post` record:
15+
16+
```js
17+
{
18+
id: 123,
19+
title: 'Lorem Ipsum Sit Amet',
20+
tags: [{ name: 'dolor' }, { name: 'sit' }, { name: 'amet' }],
21+
backlinks: [
22+
{
23+
uuid: '34fdf393-f449-4b04-a423-38ad02ae159e',
24+
date: '2012-08-10T00:00:00.000Z',
25+
url: 'https://example.com/foo/bar.html',
26+
},
27+
{
28+
uuid: 'd907743a-253d-4ec1-8329-404d4c5e6cf1',
29+
date: '2012-08-14T00:00:00.000Z',
30+
url: 'https://blog.johndoe.com/2012/08/12/foobar.html',
31+
},
32+
],
33+
}
34+
```
35+
36+
You can use `<ArrayFieldBase>` in a show view and render the embedded records with any component reading the list context:
37+
38+
```jsx
39+
import { ArrayFieldBase, RecordsIterator, ShowBase } from 'ra-core';
40+
41+
const PostShow = () => (
42+
<ShowBase>
43+
<div>
44+
<ArrayFieldBase source="tags">
45+
<ul>
46+
<RecordsIterator render={tag => <li>{tag.name}</li>} />
47+
</ul>
48+
</ArrayFieldBase>
49+
<ArrayFieldBase source="backlinks">
50+
<ul>
51+
<RecordsIterator
52+
render={backlink => (
53+
<li>
54+
<a href={backlink.url}>{backlink.url}</a>
55+
</li>
56+
)}
57+
/>
58+
</ul>
59+
</ArrayFieldBase>
60+
</div>
61+
</ShowBase>
62+
);
63+
```
64+
65+
## Props
66+
67+
| Prop | Required | Type | Default | Description |
68+
| ---------- | -------- | -------------------- | ------- | ------------------------------------------------------------------------------------ |
69+
| `children` | Required | `ReactNode` | - | The UI rendered inside the `ListContext`. |
70+
| `exporter` | Optional | `function \| false` | - | The exporter function exposed through the list context for export actions. |
71+
| `filter` | Optional | `object` | - | A permanent filter applied client-side to the embedded array. |
72+
| `perPage` | Optional | `number` | `1000` | The number of records to display per page. |
73+
| `sort` | Optional | `{ field, order }` | - | The sort applied client-side to the embedded array. |
74+
75+
`<ArrayFieldBase>` also accepts the base field props `source`, `record`, and `resource`.
76+
77+
Because it relies on [`useList`](./useList.md), `<ArrayFieldBase>` supports the same local filtering, sorting, pagination, and export behavior as other list-context-based components.
78+
79+
## `children`
80+
81+
`<ArrayFieldBase>` renders its `children` inside a [`ListContext`](./useListContext.md). Common choices are [`<RecordsIterator>`](./RecordsIterator.md), [`<WithListContext>`](./WithListContext.md), or any custom component using `useListContext()`.
82+
83+
```jsx
84+
import { ArrayFieldBase, WithListContext } from 'ra-core';
85+
86+
const BacklinksField = () => (
87+
<ArrayFieldBase source="backlinks">
88+
<WithListContext
89+
render={({ data }) => (
90+
<ul>
91+
{data?.map(backlink => (
92+
<li key={backlink.uuid}>{backlink.url}</li>
93+
))}
94+
</ul>
95+
)}
96+
/>
97+
</ArrayFieldBase>
98+
);
99+
```
100+
101+
## `exporter`
102+
103+
If one of the children exposes an export action through the list context, you can customize the export behavior with the `exporter` prop, or disable it entirely by passing `false`.
104+
105+
For instance, you can expose a custom export button for the embedded array:
106+
107+
```jsx
108+
import { ArrayFieldBase, downloadCSV, useListContext } from 'ra-core';
109+
import jsonExport from 'jsonexport/dist';
110+
111+
const exporter = backlinks => {
112+
const backlinksForExport = backlinks.map(({ uuid, url }) => ({
113+
uuid,
114+
url,
115+
}));
116+
jsonExport(backlinksForExport, (err, csv) => {
117+
downloadCSV(csv, 'backlinks');
118+
});
119+
};
120+
121+
const ExportBacklinksButton = () => {
122+
const { data, exporter } = useListContext();
123+
124+
if (!data || data.length === 0 || !exporter) {
125+
return null;
126+
}
127+
128+
return <button onClick={() => exporter(data)}>Export backlinks</button>;
129+
};
130+
131+
const PostBacklinks = () => (
132+
<ArrayFieldBase source="backlinks" exporter={exporter}>
133+
<ExportBacklinksButton />
134+
</ArrayFieldBase>
135+
);
136+
```
137+
138+
## `filter`
139+
140+
By default, `<ArrayFieldBase>` displays all records from the embedded array. Use the `filter` prop to keep only matching items. Filtering happens client-side, after reading the array value from the record.
141+
142+
```jsx
143+
<ArrayFieldBase
144+
source="backlinks"
145+
filter={{ date: '2012-08-10T00:00:00.000Z' }}
146+
>
147+
<WithListContext
148+
render={({ data }) => (
149+
<ul>
150+
{data?.map(backlink => (
151+
<li key={backlink.uuid}>{backlink.url}</li>
152+
))}
153+
</ul>
154+
)}
155+
/>
156+
</ArrayFieldBase>
157+
```
158+
159+
## `perPage`
160+
161+
Because `<ArrayFieldBase>` creates a [`ListContext`](./useListContext.md), you can paginate the embedded array with any pagination UI wired to that context.
162+
163+
## `sort`
164+
165+
By default, `<ArrayFieldBase>` displays items in the order they appear in the array. Use the `sort` prop to apply a client-side sort.
166+
167+
```jsx
168+
<ArrayFieldBase source="tags" sort={{ field: 'name', order: 'ASC' }}>
169+
<ul>
170+
<RecordsIterator render={tag => <li>{tag.name}</li>} />
171+
</ul>
172+
</ArrayFieldBase>
173+
```

docs_headless/src/content/docs/RecordsIterator.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@ const MostVisitedPosts = () => (
2929

3030
You can use `<RecordsIterator>` as a child of any component that provides a [`ListContext`](./useListContext.md), such as:
3131

32+
- [`<ArrayFieldBase>`](./ArrayFieldBase.md),
3233
- [`<ReferenceManyFieldBase>`](./ReferenceManyFieldBase.md),
33-
- [`<ReferenceArrayFieldBase>`](./ReferenceArrayField.md),
34+
- [`<ReferenceArrayFieldBase>`](./ReferenceArrayFieldBase.md),
3435
- [`<ListBase>`](./ListBase.md)
3536

3637
```jsx

docs_headless/src/content/docs/useListContext.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Whenever ra-core displays a List, it creates a `ListContext` to store the list d
66

77
The `ListContext` is available to descendants of:
88

9+
- `<ArrayFieldBase>`,
910
- `<ListBase>`,
1011
- `<ReferenceArrayFieldBase>`,
1112
- `<ReferenceManyFieldBase>`

0 commit comments

Comments
 (0)