Skip to content
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

[Doc] Add <TreeInput> and <ReferenceNodeInput> chapters #8974

Merged
merged 3 commits into from
Jun 5, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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>` instead of `<ReferenceInput>`.
fzaninotto marked this conversation as resolved.
Show resolved Hide resolved

<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