Skip to content

Commit

Permalink
Merge pull request #8974 from marmelab/doc-treeinput
Browse files Browse the repository at this point in the history
[Doc] Add documentation for `<TreeInput>` and `<ReferenceNodeInput>`
  • Loading branch information
slax57 authored Jun 5, 2023
2 parents d4d4386 + b870796 commit 5b387fd
Show file tree
Hide file tree
Showing 13 changed files with 414 additions and 3 deletions.
1 change: 1 addition & 0 deletions docs/Features.md
Original file line number Diff line number Diff line change
Expand Up @@ -864,6 +864,7 @@ export const CategoriesList = () => (
Check out the following components for displaying hierarchical data:

- [`<TreeWithDetails>`](./TreeWithDetails.md): A list view for tree structures, with a details panel.
- [`<TreeInput>`](./TreeInput.md): An input component for tree structures.
- [`<Tree>`](https://marmelab.com/ra-enterprise/modules/ra-tree#tree-component): A list view for tree structures, with a Material UI skin.

## Application Building Blocks
Expand Down
5 changes: 2 additions & 3 deletions docs/Inputs.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,13 @@ React-admin provides a set of Input components, each one designed for a specific
| Date & time | `'2022-10-24T19:40:28.003Z'` | [`<DateTimeInput>`](./DateTimeInput.md) |
| Object | `{ foo: 'bar' }` | All inputs (see [ `source`](#source)) |
| Enum | `'foo'` | [`<SelectInput>`](./SelectInput.md), [`<AutocompleteInput>`](./AutocompleteInput.md), [`<RadioButtonGroupInput>`](./RadioButtonGroupInput.md) |
| Tree node | `42` | [`<TreeInput>`](./TreeInput.md) |
| Foreign key | `42` | [`<ReferenceInput>`](./ReferenceInput.md) |
| Array of objects | `[{ item: 'jeans', qty: 3 }, { item: 'shirt', qty: 1 }]` | [`<ArrayInput>`](./ArrayInput.md) |
| Array of Enums | `['foo', 'bar']` | [`<SelectArrayInput>`](./SelectArrayInput.md), [`<AutocompleteArrayInput>`](./AutocompleteArrayInput.md), [`<CheckboxGroupInput>`](./CheckboxGroupInput.md), [`<DualListInput>`](./DualListInput.md) |
| Array of foreign keys | `[42, 43]` | [`<ReferenceArrayInput>`](./ReferenceArrayInput.md) |
| Translations | `{ en: 'Hello', fr: 'Bonjour' }` | [`<TranslatableInputs>`](./TranslatableInputs.md) |
| Related records | `[{ id: 42, title: 'Hello' }, { id: 43, title: 'World' }]` | [`<ReferenceManyInput>`](./ReferenceManyInput.md), [`<ReferenceManyToManyInput>`](./ReferenceManyToManyInput.md), [`<ReferenceOneInput>`](./ReferenceOneInput.md) |


| Related records | `[{ id: 42, title: 'Hello' }, { id: 43, title: 'World' }]` | [`<ReferenceManyInput>`](./ReferenceManyInput.md), [`<ReferenceManyToManyInput>`](./ReferenceManyToManyInput.md), [`<ReferenceNodeInput>`](./ReferenceNodeInput.md), [`<ReferenceOneInput>`](./ReferenceOneInput.md) |

## `className`

Expand Down
2 changes: 2 additions & 0 deletions docs/Reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ title: "Index"
* [`<ReferenceManyInput>`](./ReferenceManyInput.md)<img class="icon" src="./img/premium.svg" />
* [`<ReferenceManyToManyField>`](./ReferenceManyToManyField.md)<img class="icon" src="./img/premium.svg" />
* [`<ReferenceManyToManyInput>`](./ReferenceManyToManyInput.md)<img class="icon" src="./img/premium.svg" />
* [`<ReferenceNodeInput>`](./ReferenceNodeInput.md)<img class="icon" src="./img/premium.svg" />
* [`<ReferenceOneField>`](./ReferenceOneField.md)
* [`<ReferenceOneInput>`](./ReferenceOneInput.md)
* [`<Resource>`](./Resource.md)
Expand Down Expand Up @@ -181,6 +182,7 @@ title: "Index"
* [`<TranslatableFields>`](./TranslatableFields.md)
* [`<TranslatableInputs>`](./TranslatableInputs.md)
* [`<Tree>`](https://marmelab.com/ra-enterprise/modules/ra-tree#tree-component)<img class="icon" src="./img/premium.svg" />
* [`<TreeInput>`](./TreeInput.md)<img class="icon" src="./img/premium.svg" />
* [`<TreeWithDetails>`](./TreeWithDetails.md)<img class="icon" src="./img/premium.svg" />
* [`<Toolbar>`](./Toolbar.md)

Expand Down
31 changes: 31 additions & 0 deletions docs/ReferenceInput.md
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,37 @@ const filterToQuery = searchText => ({ name_ilike: `%${searchText}%` });
</ReferenceInput>
```

## Tree Structure

If the reference resource is a tree, use [`<ReferenceNodeInput>`](./ReferenceNodeInput.md) instead of `<ReferenceInput>`.

<video controls autoplay playsinline muted loop>
<source src="./img/ReferenceNodeInput-TreeInput-basic.webm" type="video/webm"/>
<source src="./img/ReferenceNodeInput-TreeInput-basic.mp4" type="video/mp4"/>
Your browser does not support the video tag.
</video>

For instance, to edit the category of a product and let the user choose the category in a tree:

```tsx
import { Edit, SimpleForm, TextInput } from 'react-admin';
import { ReferenceNodeInput } from '@react-admin/ra-tree';

const ProductEdit = () => (
<Edit>
<SimpleForm>
<TextInput source="id" disabled />
<TextInput source="name" />
<ReferenceNodeInput
source="category_id"
reference="categories"
/>
</SimpleForm>
</Edit>
);
```


## Performance

Why does `<ReferenceInput>` use the `dataProvider.getMany()` method with a single value `[id]` instead of `dataProvider.getOne()` to fetch the record for the current value?
Expand Down
113 changes: 113 additions & 0 deletions docs/ReferenceNodeInput.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
---
layout: default
title: "The ReferenceNodeInput Component"
---

# `<ReferenceNodeInput>` Component

This [Enterprise Edition](https://marmelab.com/ra-enterprise)<img class="icon" src="./img/premium.svg" /> component allows users to select one or several nodes from a tree of a reference resource. For instance, this is useful to select a category for a product.

<video controls autoplay playsinline muted loop>
<source src="./img/ReferenceNodeInput-TreeInput-basic.webm" type="video/webm"/>
<source src="./img/ReferenceNodeInput-TreeInput-basic.mp4" type="video/mp4"/>
Your browser does not support the video tag.
</video>

## Usage

Use `<ReferenceNodeInput>` in a react-admin form, and set the `reference` and `source` props just like for a `<ReferenceInput>`.

```tsx
import { Edit, SimpleForm, TextInput } from 'react-admin';
import { ReferenceNodeInput } from '@react-admin/ra-tree';

const ProductEdit = () => (
<Edit>
<SimpleForm>
<TextInput source="name" />
<ReferenceNodeInput
source="category_id"
reference="categories"
/>
</SimpleForm>
</Edit>
);
```

`<ReferenceNodeInput>` is a controller component, i.e. it fetches the tree from the reference resource, creates a tree choices context, and renders its child component.

By default `<ReferenceNodeInput>` will render a simple [`<TreeInput>`](./TreeInput.md) as its child. If you need to customize the `<TreeInput>` props, e.g. set the `multiple` prop, you will need to pass the child explicitly:

```tsx
import { Edit, SimpleForm, TextInput } from 'react-admin';
import { ReferenceNodeInput, TreeInput } from '@react-admin/ra-tree';

const ProductEdit = () => (
<Edit>
<SimpleForm>
<TextInput source="name" />
<ReferenceNodeInput
source="category_id"
reference="categories"
>
<TreeInput multiple />
</ReferenceNodeInput>
</SimpleForm>
</Edit>
);
```

<video controls autoplay playsinline muted loop>
<source src="./img/ReferenceNodeInput-TreeInput-multiple.webm" type="video/webm"/>
<source src="./img/ReferenceNodeInput-TreeInput-multiple.mp4" type="video/mp4"/>
Your browser does not support the video tag.
</video>

## Props

| Prop | Required | Type | Default | Description |
| ----------------- | ------------ | ---------------- | --------------- | ----------------------------------------------------------------------------------------- |
| `reference` | Required | string | - | The reference resource |
| `source` | Required | string | - | The name of the source field |
| `children` | Optional | React Element | `<TreeInput>` | The child component responsible for rendering the input |
| `meta` | Optional | object | - | An object containing metadata to be passed when calling the dataProvider |

## `children`

`<ReferenceNodeInput>` accepts only one child, which is responsible for rendering the input. By default, it renders a simple `<TreeInput>` with no props. If you need to pass additional props to `<TreeInput>`, you will need to pass them explicitely:

```tsx
<ReferenceNodeInput source="category_id" reference="categories">
<TreeInput multiple checkStrictly={false} />
</ReferenceNodeInput>
```

## `meta`

Use the `meta` prop to pass metadata to the dataProvider when calling `getTree()`:

{% raw %}
```tsx
<ReferenceNodeInput
source="category_id"
reference="categories"
meta={{ foo: 'bar' }}
/>
```
{% endraw %}

## `reference`

Use the `reference` prop to specify the reference resource:

```tsx
<ReferenceNodeInput source="category_id" reference="categories" />
```

## `source`

Use the `source` prop to specify the name of the source field:

```tsx
<ReferenceNodeInput source="category_id" reference="categories" />
```
37 changes: 37 additions & 0 deletions docs/SelectInput.md
Original file line number Diff line number Diff line change
Expand Up @@ -712,3 +712,40 @@ const CreateCategory = () => {
};
```
{% endraw %}

## Tree Structure

If the choices form a hierarchy or a tree, use the [`<TreeInput>`](./TreeInput.md) component instead of `<SelectInput>`. It renders a collapsible tree structure, and lets users select a value by clicking on a node.

<video controls autoplay playsinline muted loop>
<source src="./img/ReferenceNodeInput-TreeInput-basic.webm" type="video/webm"/>
<source src="./img/ReferenceNodeInput-TreeInput-basic.mp4" type="video/mp4"/>
Your browser does not support the video tag.
</video>

```tsx
import { Edit, SimpleForm, TextInput } from 'react-admin';
import { TreeInput } from '@react-admin/ra-tree';

export const ProductEdit = () => (
<Edit>
<SimpleForm>
<TextInput source="id" disabled />
<TextInput source="name" />
<TreeInput source="category" treeData={[
{ id: 1, title: 'Clothing', isRoot: true, children: [2, 6] },
{ id: 2, title: 'Men', children: [3] },
{ id: 3, title: 'Suits', children: [4, 5] },
{ id: 4, title: 'Slacks', children: [] },
{ id: 5, title: 'Jackets', children: [] },
{ id: 6, title: 'Women', children: [7, 10, 11] },
{ id: 7, title: 'Dresses', children: [8, 9] },
{ id: 8, title: 'Evening Gowns', children: [] },
{ id: 9, title: 'Sun Dresses', children: [] },
{ id: 10, title: 'Skirts', children: [] },
{ id: 11, title: 'Blouses', children: [] },
]} />
</SimpleForm>
</Edit>
);
```
Loading

0 comments on commit 5b387fd

Please sign in to comment.