<ReferenceOneInput>
Use <ReferenceOneInput>
in an <Edit>
or <Create>
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 component, part of the @react-admin/ra-relationships
package.
<ReferenceOneInput>
renders the inputs provided as its children, and fetches the related record to populate them. When users change the related record fields, the <ReferenceOneInput>
component stores these changes locally. Then, when users actually submit the form, <ReferenceOneInput>
will update both the base record and the related record.
Tip: If you need to edit an array of related records, i.e. if there are several book details for a given book, you should use <ReferenceManyInput>
instead.
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). <ReferenceOneInput>
allows to do that.
import {
Edit,
SimpleForm,
TextInput,
NumberInput,
} from 'react-admin';
import { ReferenceOneInput } from '@react-admin/ra-relationships';
const BookEdit = () => (
<Edit mutationMode="optimistic">
<SimpleForm>
<TextInput source="title" />
<ReferenceOneInput reference="book_details" target="book_id">
<NumberInput source="year" />
<TextInput source="author" />
<TextInput source="country" />
<TextInput source="genre" />
<NumberInput source="pages" />
</ReferenceOneInput>
</SimpleForm>
</Edit>
);
<ReferenceOneInput>
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.
<ReferenceOneInput>
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 <ReferenceOneInput>
in <Create>
views.
Tip: <ReferenceOneInput>
cannot be used with undoable
mutations. You have to set mutationMode="optimistic"
or mutationMode="pessimistic"
in the parent <Edit>
, 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 |
- | Material UI shortcut for defining custom styles |
Additional props are passed to the Material UI <Stack>
component.
children
<ReferenceOneInput>
expects input components as its children (like <TextInput>
, <NumberInput>
, etc.), which will allow to edit the related record. The inputs will be rendered inside a Material UI <Stack>
.
<ReferenceOneInput reference="book_details" target="book_id">
<NumberInput source="year" />
<TextInput source="author" />
<TextInput source="country" />
<TextInput source="genre" />
<NumberInput source="pages" />
</ReferenceOneInput>
Important note: <ReferenceOneInput>
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
<ReferenceOneInput>
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.
<ReferenceOneInput
reference="book_details"
target="book_id"
defaultValue={{ author: 'Gustave Flaubert', year: 1857 }}
>
<NumberInput source="year" />
<TextInput source="author" />
<TextInput source="country" />
<TextInput source="genre" />
<NumberInput source="pages" />
</ReferenceOneInput>
filter
<ReferenceOneInput>
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.
<ReferenceOneInput
reference="book_details"
target="book_id"
filter={{ reviewed: true }}
>
...
</ReferenceOneInput>
label
By default, <ReferenceOneInput>
humanizes the reference
name to build a label. You can customize the label by passing the label
prop.
<ReferenceOneInput
reference="book_details"
target="book_id"
label="Detailed information about the book"
>
...
</ReferenceOneInput>
React-admin uses the i18n system to translate the label, so you can use translation keys to have one label for each language supported by the interface:
<ReferenceOneInput
reference="book_details"
target="book_id"
label="resource.books.fields.details"
>
...
</ReferenceOneInput>
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
:
<ReferenceOneInput reference="book_details" target="book_id">
...
</ReferenceOneInput>
sort
<ReferenceOneInput>
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.
<ReferenceOneInput
reference="book_details"
target="book_id"
sort={{ field: '_id', order: 'DESC' }}
>
...
</ReferenceOneInput>
source
By default, <ReferenceManyInput>
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.
<ReferenceOneInput reference="book_details" target="book_id" source="_id">
...
</ReferenceOneInput>
sx
You can override the style of the root component (a Material UI <FormControl>
) and its child components by setting the sx
prop.
<ReferenceOneInput
reference="book_details"
target="book_id"
sx={{ border: '1px solid red' }}
>
...
</ReferenceOneInput>
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
.
<ReferenceOneInput reference="book_details" target="book_id">
...
</ReferenceOneInput>
Customizing The Child Inputs
<ReferenceOneInput>
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 will need to propagate the source
prop to them.
In this example, the <TextInput>
component is wrapped inside a <MyCustomInput>
component. That adds an icon and additional styling.
import AccountCircle from '@mui/icons-material/AccountCircle';
import AutoStoriesIcon from '@mui/icons-material/AutoStories';
import CalendarMonthIcon from '@mui/icons-material/CalendarMonth';
import ClassIcon from '@mui/icons-material/Class';
import LanguageIcon from '@mui/icons-material/Language';
import { Box, SxProps } from '@mui/material';
import * as React from 'react';
import { TextInput } from 'react-admin';
import { ReferenceOneInput } from '@react-admin/ra-relationships';
const MyCustomInput = ({
source,
icon: Icon,
}: {
source: string;
icon: React.FunctionComponent<{ sx?: SxProps }>;
}) => (
<Box sx={{ display: 'flex', alignItems: 'flex-end' }}>
<Icon sx={{ color: 'action.active', mr: 1.5, my: 1 }} />
<TextInput
source={source} // Propagate the source prop to the real input
variant="standard"
size="small"
helperText={false}
/>
</Box>
);
export const CustomInputs = () => (
<ReferenceOneInput reference="book_details" target="book_id">
<MyCustomInput source="year" icon={CalendarMonthIcon} />
<MyCustomInput source="author" icon={AccountCircle} />
<MyCustomInput source="country" icon={LanguageIcon} />
<MyCustomInput source="genre" icon={ClassIcon} />
<MyCustomInput source="pages" icon={AutoStoriesIcon} />
</ReferenceOneInput>
);
Limitations
<ReferenceOneInput>
cannot be used inside an<ArrayInput>
or a<ReferenceManyInput>
.<ReferenceOneInput>
cannot have a<ReferenceManyInput>
or a<ReferenceManyToManyInput>
as one of its children.<ReferenceOneInput>
does not support server side validation.