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] Improve FunctionField documentation #9614

Merged
merged 2 commits into from
Jan 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
112 changes: 106 additions & 6 deletions docs/FunctionField.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,122 @@ title: "The FunctionField Component"

# `<FunctionField>`

If you need a special function to render a field, `<FunctionField>` is the perfect match. It passes the `record` to a `render` function supplied by the developer. For instance, to display the full name of a `user` record based on `first_name` and `last_name` properties:
If you need a special function to render a field, `<FunctionField>` is the perfect match. It executes a `render` function using the current record as parameter.

<iframe src="https://www.youtube-nocookie.com/embed/gcgefw79QdM" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen style="aspect-ratio: 16 / 9;width:100%;margin-bottom:1em;"></iframe>

## Usage

`<FunctionField>` requires a `render` prop, which is a function that takes the current record as argument and returns a string or an element.

For instance, to display the full name of a `user` record based on `first_name` and `last_name` properties:

```jsx
import { FunctionField } from 'react-admin';
import { List, Datagrid, FunctionField } from 'react-admin';

<FunctionField label="Name" render={record => `${record.first_name} ${record.last_name}`} />
const UserList = () => (
<List>
<Datagrid>
<FunctionField
source="last_name"
render={record => `${record.first_name} ${record.last_name}`}
/>
...
</Datagrid>
</List>
);
```

## Properties
Theoretically, you can omit the `source` for the `<FunctionField>` since you provide the render function. However, when used inside a `<Datagrid>`, providing the `source` prop (or the `sortBy` prop) is required to make the column sortable. When a user clicks on a column, `<Datagrid>` uses these properties to sort the data.

`<FunctionField>` is based on [the `useRecordContext` hook](./useRecordContext.md).

## Props

| Prop | Required | Type | Default | Description |
| -------- | -------- | -------- | ------- | -------------------------------------------------------------------------- |
| `render` | Required | function | - | A function returning a string (or an element) to display based on a record |

`<FunctionField>` also accepts the [common field props](./Fields.md#common-field-props).

**Tip**: Technically, you can omit the `source` and `sortBy` properties for the `<FunctionField>` since you provide the render function. However, providing a `source` or a `sortBy` will allow the `Datagrid` to make the column sortable, since when a user clicks on a column, the `Datagrid` uses these properties to sort. Should you provide both, `sortBy` will override `source` for sorting the column.
## `render`

The `render` prop accepts a function that takes the current record as argument and returns a string or an element.

```tsx
// return a string
const render = (record: any) => `${record.first_name} ${record.last_name}`;

// return an element
const render = (record: any) => (
<>{record.first_name} <strong>{record.last_name}</strong></>
);
```

React-admin wraps the result of the `render` function in a `<Typography>` component.

Since this function executes in a [RecordContext](./useRecordContext.md), you can even use other Field components to compute the value:

```tsx
import { List, Datagrid, FunctionField, TextField } from 'react-admin';

const render = () => (
<span>
<TextField source="first_name" />{' '}
<TextField source="last_name" />
</span>
);
const UserList = () => (
<List>
<Datagrid>
<FunctionField source="last_name" label="Name" render={render} />
...
</Datagrid>
</List>
);
```

However, if you only need to combine Field components, prefer [the `<WrapperField>` component](./WrapperField.md) for a simpler syntax:

```tsx
import { List, Datagrid, WrapperField, TextField } from 'react-admin';

const UserList = () => (
<List>
<Datagrid>
<WrapperField label="Name" source="last_name">
<TextField source="first_name" />
<TextField source="last_name" />
</WrapperField>
...
</Datagrid>
</List>
);
```

## TypeScript

To type the `record` argument of the `render` function, provide the record's type as a generic parameter to the component:

```tsx
import { List, Datagrid, FunctionField } from 'react-admin';

interface User {
id: number;
first_name: string;
last_name: string;
}

**Tip**: If you want to combine two existing Field components, check [the `<WrapperField>` component](./WrapperField.md) instead.
const UserList = () => (
<List>
<Datagrid>
<FunctionField<User>
source="last_name"
label="Name"
render={record => `${record.first_name} ${record.last_name}`}
/>
...
</Datagrid>
</List>
);
```
7 changes: 6 additions & 1 deletion docs/WrapperField.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ title: "The WrapperField Component"

This component simply renders its children. Why would you want to use such a dumb component? To combine several fields in a single cell (in a `<Datagrid>`), in a single row (in a `<SimpleShowLayout>`) or in a group of inputs (in a `<SimpleFormConfigurable>`) .

## Usage

`<WrapperField>` allows to define the `label` and sort field for a combination of fields:

```jsx
Expand Down Expand Up @@ -44,5 +46,8 @@ const PostEdit = () => (
);
```

**Tip**: If you just want to combine two fields in a string, check [the `<FunctionField>` component](./FunctionField.md) instead.

## Props

**Tip**: If you just want to combine two fields in a string, check [the `<FunctionField>` component](./FunctionField.md) instead.
`<WrapperField>` accepts the [common field props](./Fields.md#common-field-props).