diff --git a/docs/EditTutorial.md b/docs/EditTutorial.md index 52414758037..1ee948001aa 100644 --- a/docs/EditTutorial.md +++ b/docs/EditTutorial.md @@ -889,6 +889,7 @@ This affects both the submit button, and the form submission when the user press Users often need to edit data from several resources in the same form. React-admin doesn't support nested forms, but provides ways to edit related data in a user-friendly way: - [``](./EditInDialogButton.md) lets users open a modal to edit a related record +- [``](./ReferenceOneInput.md) lets users edit one related record - [``](./ReferenceManyInput.md) lets users edit a list of related records - [``](./ReferenceManyToManyInput.md) lets users edit a list of related records via an associative table diff --git a/docs/Features.md b/docs/Features.md index e4f959b9877..5093ce41120 100644 --- a/docs/Features.md +++ b/docs/Features.md @@ -233,6 +233,7 @@ React-admin supports **one-to-many**, **many-to-one**, **one-to-one**, and **man - [`ReferenceArrayInput`](./ReferenceArrayInput.md) - [`ReferenceManyInput`](./ReferenceManyInput.md) - [`ReferenceManyToManyInput`](./ReferenceManyToManyInput.md) +- [`ReferenceOneInput`](./ReferenceOneInput.md) The [Fields For Relationships](./FieldsForRelationships.md) page lists all reference fields together with their common usage. @@ -481,8 +482,8 @@ Inside forms, you can use [react-admin input components](./Inputs.md), designed | Array of objects | `[{ item: 'jeans', qty: 3 }, { item: 'shirt', qty: 1 }]` | [``](./ArrayInput.md) | | Array of Enums | `['foo', 'bar']` | [``](./SelectArrayInput.md), [``](./AutocompleteArrayInput.md), [``](./CheckboxGroupInput.md), [``](./DualListInput.md) | | Array of foreign keys | `[42, 43]` | [``](./ReferenceArrayInput.md) | -| Translations | `{ en: 'Hello', fr: 'Bonjour' }` | [``](./TranslatableInputs.md) | -| Related records | `[{ id: 42, title: 'Hello' }, { id: 43, title: 'World' }]` | [``](./ReferenceManyInput.md), [``](./ReferenceManyToManyInput.md) | +| Translations | `{ en: 'Hello', fr: 'Bonjour' }` | [``](./TranslatableInputs.md) | +| Related records | `[{ id: 42, title: 'Hello' }, { id: 43, title: 'World' }]` | [``](./ReferenceManyInput.md), [``](./ReferenceManyToManyInput.md), [``](./ReferenceOneInput.md) | You can build **dependent inputs**, using the [react-hook-form's `useWatch` hook](https://react-hook-form.com/api/usewatch). For instance, here is a `CityInput` that displays the cities of the selected country: diff --git a/docs/Inputs.md b/docs/Inputs.md index 9b6ab18f9e7..20898df62f3 100644 --- a/docs/Inputs.md +++ b/docs/Inputs.md @@ -79,8 +79,8 @@ React-admin provides a set of Input components, each one designed for a specific | Array of objects | `[{ item: 'jeans', qty: 3 }, { item: 'shirt', qty: 1 }]` | [``](./ArrayInput.md) | | Array of Enums | `['foo', 'bar']` | [``](./SelectArrayInput.md), [``](./AutocompleteArrayInput.md), [``](./CheckboxGroupInput.md), [``](./DualListInput.md) | | Array of foreign keys | `[42, 43]` | [``](./ReferenceArrayInput.md) | -| Translations | `{ en: 'Hello', fr: 'Bonjour' }` | [``](./TranslatableInputs.md) | -| Related records | `[{ id: 42, title: 'Hello' }, { id: 43, title: 'World' }]` | [``](./ReferenceManyInput.md), [``](./ReferenceManyToManyInput.md) | +| Translations | `{ en: 'Hello', fr: 'Bonjour' }` | [``](./TranslatableInputs.md) | +| Related records | `[{ id: 42, title: 'Hello' }, { id: 43, title: 'World' }]` | [``](./ReferenceManyInput.md), [``](./ReferenceManyToManyInput.md), [``](./ReferenceOneInput.md) | diff --git a/docs/Reference.md b/docs/Reference.md index d6874dd9454..beb377e0200 100644 --- a/docs/Reference.md +++ b/docs/Reference.md @@ -134,6 +134,7 @@ title: "Index" * [``](./ReferenceManyToManyField.md) * [``](./ReferenceManyToManyInput.md) * [``](./ReferenceOneField.md) +* [``](./ReferenceOneInput.md) * [``](./Resource.md) * [``](./RichTextField.md) * [``](./RichTextInput.md) diff --git a/docs/ReferenceOneField.md b/docs/ReferenceOneField.md index 28c4d5e362d..e5af4cc3f33 100644 --- a/docs/ReferenceOneField.md +++ b/docs/ReferenceOneField.md @@ -26,6 +26,8 @@ This field fetches a one-to-one relationship, e.g. the details of a book, when u For the inverse relationships (the book linked to a book_detail), you can use a [``](./ReferenceField.md). +**Tip**: To edit the records of a one-to-one relationship, use [the `` component](./ReferenceOneInput.md). + ## Usage Here is how to render a field of the `book_details` resource inside a Show view for the `books` resource: diff --git a/docs/ReferenceOneInput.md b/docs/ReferenceOneInput.md new file mode 100644 index 00000000000..1db46c9dda2 --- /dev/null +++ b/docs/ReferenceOneInput.md @@ -0,0 +1,237 @@ +--- +layout: default +title: "The ReferenceOneInput Component" +--- + +# `` + +Use `` in an `` or `` view to edit a record linked to the current record via a one-to-one relationship, e.g. to edit the details of a book in the book edition view. It's an [Enterprise Edition](https://marmelab.com/ra-enterprise) component, part of the `@react-admin/ra-relationships` package. + + + +`` renders the inputs provided as its children, and fetches the related record to populate them. When users change the related record fields, the `` component stores these changes locally. Then, when users actually submit the form, `` will update both the base record and the related record. + +## Usage + +Here is an example one-to-one relationship: a `book` has at most one `book_details` row associated to it. + +``` +┌─────────────┐ ┌──────────────┐ +│ book │ │ book_details │ +│-------------│ │--------------│ +│ id │───┐ │ id │ +│ title │ └──╼│ book_id │ +└─────────────┘ │ year │ + │ author │ + │ country │ + │ genre │ + │ pages │ + └──────────────┘ +``` + +You probably want to let users edit the book details directly from the book Edition view (instead of having to go to the book details Edition view). `` allows to do that. + +```jsx +import { + Edit, + SimpleForm, + TextInput, + NumberInput, +} from 'react-admin'; +import { ReferenceOneInput } from '@react-admin/ra-relationships'; + +const BookEdit = () => ( + + + + + + + + + + + + +); +``` + +`` requires a `reference` and a `target` prop to know which entity to fetch, and one or more inputs as its `children` to edit the related record. + +`` persists the changes in the referenced record (book details in the above example) after persisting the changes in the main resource (book in the above example). This means that you can also use `` in `` views. + +**Tip**: `` cannot be used with `undoable` mutations. You have to set `mutationMode="optimistic"` or `mutationMode="pessimistic"` in the parent `` or ``, as in the example above. + +## Props + +| Prop | Required | Type | Default | Description | +| -------------- | -------- | ------------------------- | -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `target` | Required | `string` | - | Target field carrying the relationship on the referenced resource, e.g. 'book_id' | +| `reference` | Required | `string` | - | The name of the resource for the referenced records, e.g. 'book_details' | +| `children` | Required | `Element` | - | One or several input elements that accept a `source` prop | +| `label` | Optional | `string` | `reference` | Input label. In i18n apps, the label is passed to the `translate` function. Defaults to the humanized `reference` when omitted. Set `label={false}` to hide the label. | +| `source` | Optional | `string` | `id` | Name of the field that carries the identity of the current record, used as origin for the relationship | +| `filter` | Optional | `Object` | - | Filters to use when fetching the related record, passed to `getManyReference()` | +| `sort` | Optional | `{ field, order }` | `{ field: 'id', order: 'ASC' }` | Sort order to use when fetching the related record, passed to `getManyReference()` | +| `defaultValue` | Optional | `Object` | - | Default value for the related record (in case it does not yet exist) | +| `sx` | Optional | `SxProps` | - | MUI shortcut for defining custom styles | + +Additional props are passed to the MUI `` component. + +## `children` + +`` expects input components as its children (like ``, ``, etc.), which will allow to edit the related record. The inputs will be rendered inside an [MUI ``](https://mui.com/material-ui/react-stack/). + +```jsx + + + + + + + +``` + +**Important note**: `` works by cloning its children and overriding their `source` prop, to add a temporary field name prefix. This means that, if you need to nest your inputs inside another component, you need to propagate the `source` prop to them. + +## `defaultValue` + +`` allows to specify a default value for the related record. This is useful when the current record does not yet have a related record, and you want to pre-fill the related record with some default values. + +{% raw %} + +```jsx + + + + + + + +``` + +{% endraw %} + +## `filter` + +`` allows to specify filters to use when fetching the related record. This can be useful when you need additional filters to select the related record. + +{% raw %} + +```jsx + + ... + +``` + +{% endraw %} + +## `label` + +By default, `` humanizes the `reference` name to build a label. You can customize the label by passing the `label` prop. + +```jsx + + ... + +``` + +React-admin uses [the i18n system](https://marmelab.com/react-admin/Translation.html) to translate the label, so you can use translation keys to have one label for each language supported by the interface: + +```jsx + + ... + +``` + +## `reference` + +The name of the resource to fetch for the related records. + +For instance, if you want to display the `book_details` of a given `book`, the `reference` name should be `book_details`: + +```jsx + + ... + +``` + +## `sort` + +`` allows to specify the sort options used when fetching the related record. This can be useful when the relation table does not have an `id` column. + +{% raw %} + +```jsx + + ... + +``` + +{% endraw %} + +## `source` + +By default, `` fetches the `reference` for which the `target` field equals the current record `id`. You can customize the field that carries the identity of the current record by setting the `source` prop. + +```jsx + + ... + +``` + +## `sx` + +You can override the style of the root component (a MUI [``](https://mui.com/material-ui/api/form-control/#main-content)) and its child components by setting the `sx` prop. + +{% raw %} + +```jsx + + ... + +``` + +{% endraw %} + +## `target` + +Name of the field carrying the relationship on the referenced resource. For instance, if each `book` is linked to a record in `book_details`, and each `book_details` exposes a `book_id` field linking to the `book`, the `target` would be `book_id`. + +```jsx + + ... + +``` + +## Limitations + +- `` cannot be used inside an `` or a ``. +- `` cannot have a `` as one of its children. \ No newline at end of file diff --git a/docs/img/reference-one-input.webm b/docs/img/reference-one-input.webm new file mode 100644 index 00000000000..5d83f543dcc Binary files /dev/null and b/docs/img/reference-one-input.webm differ diff --git a/docs/navigation.html b/docs/navigation.html index 07c22855075..549512d9ef1 100644 --- a/docs/navigation.html +++ b/docs/navigation.html @@ -187,6 +187,7 @@
  • <ReferenceArrayInput>
  • <ReferenceManyInput>
  • <ReferenceManyToManyInput>
  • +
  • <ReferenceOneInput>
  • <RichTextInput>
  • <SelectInput>
  • <SelectArrayInput>