diff --git a/docs/ArrayField.md b/docs/ArrayField.md index c95e218a74e..1139beb0853 100644 --- a/docs/ArrayField.md +++ b/docs/ArrayField.md @@ -12,7 +12,7 @@ storybook_path: ra-ui-materialui-fields-arrayfield--basic `` creates a [`ListContext`](./useListContext.md) with the field value, and renders its children components - usually iterator components like [``](./DataTable.md) or [``](./SingleFieldList.md). -`` is the Material UI export of the headless [``](./ArrayFieldBase.md) component from `ra-core`. +`` is the Material UI export of the headless [``](https://marmelab.com/ra-core/arrayfieldbase/) component from `ra-core`. ## Usage diff --git a/docs/ArrayFieldBase.md b/docs/ArrayFieldBase.md deleted file mode 100644 index d12b95c3791..00000000000 --- a/docs/ArrayFieldBase.md +++ /dev/null @@ -1,152 +0,0 @@ ---- -layout: default -title: "The ArrayFieldBase Component" ---- - -# `` - -`` renders an embedded array of objects. -`` is a headless component, handling only the list logic. This allows you to use any UI library for the render. For a Material UI version, see [``](./ArrayField.md). - -`` creates a [`ListContext`](./useListContext.md) with the field value, and renders its children components. - -## Usage - -`` is ideal for collections of objects, e.g. `tags` and `backlinks` in the following `post` object: - -```js -{ - id: 123, - title: 'Lorem Ipsum Sit Amet', - tags: [{ name: 'dolor' }, { name: 'sit' }, { name: 'amet' }], - backlinks: [ - { - uuid: '34fdf393-f449-4b04-a423-38ad02ae159e', - date: '2012-08-10T00:00:00.000Z', - url: 'https://example.com/foo/bar.html', - }, - { - uuid: 'd907743a-253d-4ec1-8329-404d4c5e6cf1', - date: '2012-08-14T00:00:00.000Z', - url: 'https://blog.johndoe.com/2012/08/12/foobar.html', - } - ] -} -``` - -You can leverage `` in a Show view and render the list using any component reading the list context: - -{% raw %} -```jsx -import { - ArrayFieldBase, - RecordsIterator, - Show, - SimpleShowLayout, - TextField, -} from 'react-admin'; - -const PostShow = () => ( - - - - -
    -
  • {tag.name}
  • } /> -
-
- - - -
-
-); -``` -{% endraw %} - -## Props - -| Prop | Required | Type | Default | Description | -|------------|----------|-------------------|---------|------------------------------------------| -| `children` | Required | `ReactNode` | | The component to render the list. | -| `filter` | Optional | `object` | | The filter to apply to the list. | -| `exporter` | Optional | `function` | `default Exporter` | The function called by export buttons in the list context. | -| `perPage` | Optional | `number` | 1000 | The number of items to display per page. | -| `sort` | Optional | `{ field, order}` | | The sort to apply to the list. | - -`` accepts the base field props `source`, `record`, and `resource`. - -`` relies on [`useList`](./useList.md) to filter, paginate, and sort the data, so it accepts the same props. - -## `children` - -`` renders its `children` wrapped in a [``](./useListContext.md). Commonly used children are [``](./RecordsIterator.md), [``](./WithListContext.md), or any custom component using `useListContext()`. - -{% raw %} -```jsx -import { ArrayFieldBase, WithListContext } from 'react-admin'; - -const BacklinksField = () => ( - - ( -
    - {data?.map(backlink => ( -
  • {backlink.url}
  • - ))} -
- )} - /> -
-); -``` -{% endraw %} - -## `filter` - -By default, `` displays all the records in the embedded array. Use the `filter` prop to restrict them. - -{% raw %} -```jsx - - ( -
    - {data?.map(backlink => ( -
  • {backlink.url}
  • - ))} -
- )} - /> -
-``` -{% endraw %} - -## `perPage` - -Because `` creates a [`ListContext`](./useListContext.md), you can paginate the embedded array with any pagination UI wired to that context. - -## `sort` - -By default, `` displays the items in the order they are stored in the field. You can use the `sort` prop to change the sort order. - -{% raw %} -```jsx - -
    -
  • {tag.name}
  • } /> -
-
-``` -{% endraw %} diff --git a/docs_headless/astro.config.mjs b/docs_headless/astro.config.mjs index a5759097eed..e78e338b9d2 100644 --- a/docs_headless/astro.config.mjs +++ b/docs_headless/astro.config.mjs @@ -180,6 +180,7 @@ export default defineConfig({ items: [ 'fields', 'fieldsforrelationships', + 'arrayfieldbase', 'referencearrayfieldbase', 'referencefieldbase', 'referencemanycountbase', diff --git a/docs_headless/src/content/docs/ArrayFieldBase.md b/docs_headless/src/content/docs/ArrayFieldBase.md new file mode 100644 index 00000000000..e09d0d94de9 --- /dev/null +++ b/docs_headless/src/content/docs/ArrayFieldBase.md @@ -0,0 +1,173 @@ +--- +layout: default +title: "" +--- + +Use `` to display an embedded array of objects from the current record. + +`` 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. + +**Tip**: Use [``](./ReferenceArrayFieldBase.md) when the array contains foreign keys to another resource. Use `` when the array already contains the embedded objects to display. + +## Usage + +`` is ideal for collections of embedded objects, like `tags` and `backlinks` in the following `post` record: + +```js +{ + id: 123, + title: 'Lorem Ipsum Sit Amet', + tags: [{ name: 'dolor' }, { name: 'sit' }, { name: 'amet' }], + backlinks: [ + { + uuid: '34fdf393-f449-4b04-a423-38ad02ae159e', + date: '2012-08-10T00:00:00.000Z', + url: 'https://example.com/foo/bar.html', + }, + { + uuid: 'd907743a-253d-4ec1-8329-404d4c5e6cf1', + date: '2012-08-14T00:00:00.000Z', + url: 'https://blog.johndoe.com/2012/08/12/foobar.html', + }, + ], +} +``` + +You can use `` in a show view and render the embedded records with any component reading the list context: + +```jsx +import { ArrayFieldBase, RecordsIterator, ShowBase } from 'ra-core'; + +const PostShow = () => ( + +
+ +
    +
  • {tag.name}
  • } /> +
+
+ + + +
+
+); +``` + +## Props + +| Prop | Required | Type | Default | Description | +| ---------- | -------- | -------------------- | ------- | ------------------------------------------------------------------------------------ | +| `children` | Required | `ReactNode` | - | The UI rendered inside the `ListContext`. | +| `exporter` | Optional | `function \| false` | - | The exporter function exposed through the list context for export actions. | +| `filter` | Optional | `object` | - | A permanent filter applied client-side to the embedded array. | +| `perPage` | Optional | `number` | `1000` | The number of records to display per page. | +| `sort` | Optional | `{ field, order }` | - | The sort applied client-side to the embedded array. | + +`` also accepts the base field props `source`, `record`, and `resource`. + +Because it relies on [`useList`](./useList.md), `` supports the same local filtering, sorting, pagination, and export behavior as other list-context-based components. + +## `children` + +`` renders its `children` inside a [`ListContext`](./useListContext.md). Common choices are [``](./RecordsIterator.md), [``](./WithListContext.md), or any custom component using `useListContext()`. + +```jsx +import { ArrayFieldBase, WithListContext } from 'ra-core'; + +const BacklinksField = () => ( + + ( +
    + {data?.map(backlink => ( +
  • {backlink.url}
  • + ))} +
+ )} + /> +
+); +``` + +## `exporter` + +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`. + +For instance, you can expose a custom export button for the embedded array: + +```jsx +import { ArrayFieldBase, downloadCSV, useListContext } from 'ra-core'; +import jsonExport from 'jsonexport/dist'; + +const exporter = backlinks => { + const backlinksForExport = backlinks.map(({ uuid, url }) => ({ + uuid, + url, + })); + jsonExport(backlinksForExport, (err, csv) => { + downloadCSV(csv, 'backlinks'); + }); +}; + +const ExportBacklinksButton = () => { + const { data, exporter } = useListContext(); + + if (!data || data.length === 0 || !exporter) { + return null; + } + + return ; +}; + +const PostBacklinks = () => ( + + + +); +``` + +## `filter` + +By default, `` 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. + +```jsx + + ( +
    + {data?.map(backlink => ( +
  • {backlink.url}
  • + ))} +
+ )} + /> +
+``` + +## `perPage` + +Because `` creates a [`ListContext`](./useListContext.md), you can paginate the embedded array with any pagination UI wired to that context. + +## `sort` + +By default, `` displays items in the order they appear in the array. Use the `sort` prop to apply a client-side sort. + +```jsx + +
    +
  • {tag.name}
  • } /> +
+
+``` diff --git a/docs_headless/src/content/docs/RecordsIterator.md b/docs_headless/src/content/docs/RecordsIterator.md index 87916c23892..d03a0a546b1 100644 --- a/docs_headless/src/content/docs/RecordsIterator.md +++ b/docs_headless/src/content/docs/RecordsIterator.md @@ -29,8 +29,9 @@ const MostVisitedPosts = () => ( You can use `` as a child of any component that provides a [`ListContext`](./useListContext.md), such as: +- [``](./ArrayFieldBase.md), - [``](./ReferenceManyFieldBase.md), -- [``](./ReferenceArrayField.md), +- [``](./ReferenceArrayFieldBase.md), - [``](./ListBase.md) ```jsx diff --git a/docs_headless/src/content/docs/useListContext.md b/docs_headless/src/content/docs/useListContext.md index 3da2d4b52ea..c11d8e6eec5 100644 --- a/docs_headless/src/content/docs/useListContext.md +++ b/docs_headless/src/content/docs/useListContext.md @@ -6,6 +6,7 @@ Whenever ra-core displays a List, it creates a `ListContext` to store the list d The `ListContext` is available to descendants of: +- ``, - ``, - ``, - ``