|
| 1 | +--- |
| 2 | +layout: default |
| 3 | +title: "The RecordField Component" |
| 4 | +--- |
| 5 | + |
| 6 | +# `<RecordField>` |
| 7 | + |
| 8 | +`<RecordField>` displays a label and a record property. |
| 9 | + |
| 10 | + |
| 11 | + |
| 12 | +## Usage |
| 13 | + |
| 14 | +Use `<RecordField>` as descendent of a [`RecordContextProvider`](./useRecordContext.md#creating-a-record-context) like in record detail components (`<Show>`, `<Edit>`, `<ReferenceField>`, `<ReferenceOneField>`). |
| 15 | + |
| 16 | +For instance, to render the title of a book in a show view: |
| 17 | + |
| 18 | +```jsx |
| 19 | +import { Show, RecordField } from 'react-admin'; |
| 20 | +import { Stack } from '@mui/material'; |
| 21 | + |
| 22 | +export const BookShow = () => ( |
| 23 | + <Show> |
| 24 | + <Stack> |
| 25 | + <RecordField source="title" /> |
| 26 | + </Stack> |
| 27 | + </Show> |
| 28 | +); |
| 29 | +``` |
| 30 | + |
| 31 | +`<RecordField>` renders a label based on the humanized `source` prop, or on the `label` prop if present. It also grabs the `record` from the current [`RecordContext`](./useRecordContext.md), extracts the `record[source]` property, and displays it using a [`<TextField>`](./TextField.md) by default. |
| 32 | + |
| 33 | +You can override the label by passing a `label` prop: |
| 34 | + |
| 35 | +```jsx |
| 36 | +<RecordField source="title" label="Book title" /> |
| 37 | +``` |
| 38 | + |
| 39 | +The `source` prop can be a [deep source](./Fields.md#deep-field-source): |
| 40 | + |
| 41 | +```jsx |
| 42 | +<RecordField label="Author name" source="author.name" /> |
| 43 | +``` |
| 44 | + |
| 45 | +You can customize the way the value is displayed by passing a Field component in the `field` prop. For example, to display a numeric value using the browser locale, use the `NumberField`: |
| 46 | + |
| 47 | +```jsx |
| 48 | +import { RecordField, NumberField } from 'react-admin'; |
| 49 | + |
| 50 | +<RecordField source="price" field={NumberField} /> |
| 51 | +``` |
| 52 | + |
| 53 | +If you need to pass specific props to the field component, for example to format the value, prefer passing a field component as child. In this case, the `source` passed to the `RecordField` will only be used for the label: |
| 54 | + |
| 55 | +{% raw %} |
| 56 | +```jsx |
| 57 | +import { RecordField, NumberField } from 'react-admin'; |
| 58 | + |
| 59 | +<RecordField source="price"> |
| 60 | + <NumberField source="price" options={{ style: 'currency', currency: 'USD' }} /> |
| 61 | +</RecordField> |
| 62 | +``` |
| 63 | +{% endraw %} |
| 64 | + |
| 65 | +If you need to aggregate multiple fields, you can use the `render` prop instead, to pass a function that receives the current record and returns a React element: |
| 66 | + |
| 67 | +```jsx |
| 68 | +import { RecordField } from 'react-admin'; |
| 69 | + |
| 70 | +<RecordField |
| 71 | + label="Name" |
| 72 | + render={record => `${record.firstName} ${record.lastName}`} |
| 73 | +/> |
| 74 | +``` |
| 75 | + |
| 76 | +The `source`, `field`, `children`, and `render` props are mutually exclusive. |
| 77 | + |
| 78 | +## Props |
| 79 | + |
| 80 | +| Prop | Required | Type | Default | Description | |
| 81 | +| ----------- | -------- | ------------------ | ------- | -------------------------------------------------------------------------------- | |
| 82 | +| `children` | Optional | ReactNode | '' | Elements rendering the actual field. | |
| 83 | +| `field` | Optional | ReactElement | `TextField` | Field component used to render the field. Ignored if `children` or `render` are set. | |
| 84 | +| `label` | Optional | string | '' | Label to render. Can be a translation key. | |
| 85 | +| `render` | Optional | record => JSX | | Function to render the field value. Ignored if `children` is set. | |
| 86 | +| `source` | Optional | string | '' | Name of the record field to render. | |
| 87 | +| `sx` | Optional | object | {} | Styles to apply to the field. | |
| 88 | +| `TypographyProps` | Optional | object | {} | Props to pass to label wrapper | |
| 89 | +| `variant` | Optional | `'default' || 'inline'` | 'default' | When `inline`, the label is displayed inline with the field value. | |
| 90 | + |
| 91 | +## `children` |
| 92 | + |
| 93 | +The `children` prop is used to pass a field component that will be rendered instead of the default one. The `source` prop will only be used for the label. |
| 94 | + |
| 95 | +{% raw %} |
| 96 | +```jsx |
| 97 | +import { RecordField, NumberField } from 'react-admin'; |
| 98 | + |
| 99 | +<RecordField source="price"> |
| 100 | + <NumberField source="price" options={{ style: 'currency', currency: 'USD' }} /> |
| 101 | +</RecordField> |
| 102 | +``` |
| 103 | +{% endraw %} |
| 104 | + |
| 105 | +This ability is often used to render a field from a reference record, using [`<ReferenceField>`](./ReferenceField.md): |
| 106 | + |
| 107 | +```jsx |
| 108 | +import { RecordField, ReferenceField } from 'react-admin'; |
| 109 | + |
| 110 | +<RecordField label="Author"> |
| 111 | + <ReferenceField source="author_id" reference="users" /> |
| 112 | +</RecordField> |
| 113 | +``` |
| 114 | + |
| 115 | +If you just need to use a field component without any special prop, prefer the `field` prop: |
| 116 | + |
| 117 | +```jsx |
| 118 | +import { RecordField, NumberField } from 'react-admin'; |
| 119 | + |
| 120 | +<RecordField source="price" field={NumberField} /> |
| 121 | +// instead of |
| 122 | +<RecordField source="price"> |
| 123 | + <NumberField source="price" /> |
| 124 | +</RecordField> |
| 125 | +``` |
| 126 | + |
| 127 | +## `field` |
| 128 | + |
| 129 | +By default, `<RecordField>` uses the [`<TextField>`](./TextField.md) component to render the field value. |
| 130 | + |
| 131 | +```jsx |
| 132 | +<RecordField source="title" /> |
| 133 | +// equivalent to |
| 134 | +<RecordField source="title" field={TextField} /> |
| 135 | +``` |
| 136 | + |
| 137 | +Use the `field` prop to pass a custom field component instead: |
| 138 | + |
| 139 | +```jsx |
| 140 | +import { RecordField, NumberField } from 'react-admin'; |
| 141 | + |
| 142 | +<RecordField source="price" field={NumberField} /> |
| 143 | +``` |
| 144 | + |
| 145 | +If you need to pass specific props to the field component, for example to format the value, prefer passing a field component as child. In this case, the `source` passed to the `RecordField` will only be used for the label: |
| 146 | + |
| 147 | +{% raw %} |
| 148 | +```jsx |
| 149 | +import { RecordField, NumberField } from 'react-admin'; |
| 150 | + |
| 151 | +<RecordField source="price"> |
| 152 | + <NumberField source="price" options={{ style: 'currency', currency: 'USD' }} /> |
| 153 | +</RecordField> |
| 154 | +``` |
| 155 | +{% endraw %} |
| 156 | + |
| 157 | +## `label` |
| 158 | + |
| 159 | +When you use the `source` prop, the label is automatically generated from the source name using the "humanize" function. For example, the source `author.name` will be displayed as "Author name". |
| 160 | + |
| 161 | +You can customize the label by passing a custom [translation](./Translation.md) for the `resources.${resourceName}.fields.${source}` key. For example, if you have a resource called `posts`, and you want to customize the label for `<RecordField source="title" />` field, you can add the following translation: |
| 162 | + |
| 163 | +```json |
| 164 | +{ |
| 165 | + "resources": { |
| 166 | + "posts": { |
| 167 | + "fields": { |
| 168 | + "title": "Post title" |
| 169 | + } |
| 170 | + } |
| 171 | + } |
| 172 | +} |
| 173 | +``` |
| 174 | + |
| 175 | +If you don't use the `source` prop, or if you don't want to use the i18N features to customize the label, you can use the `label` prop to override the default label: |
| 176 | + |
| 177 | +```jsx |
| 178 | +<RecordField source="title" label="Post title" /> |
| 179 | +``` |
| 180 | + |
| 181 | +If you pass a translation key as `label`, react-admin will use the `i18nProvider` to translate it: |
| 182 | + |
| 183 | +```jsx |
| 184 | +<RecordField source="title" label="resources.posts.fields.title_custom" /> |
| 185 | +``` |
| 186 | + |
| 187 | +Finally, you can pass `false` to the `label` prop to hide the label: |
| 188 | + |
| 189 | +```jsx |
| 190 | +<RecordField source="title" label={false} /> |
| 191 | +``` |
| 192 | + |
| 193 | +Note that using `label={false}` is equivalent to rendering a `<TextField>` directly. |
| 194 | + |
| 195 | +## `render` |
| 196 | + |
| 197 | +The `render` prop is used to pass a function that receives the current record and returns a React element. This is useful when you need to aggregate multiple fields, or when you need to use a component that doesn't accept the `source` prop. |
| 198 | + |
| 199 | +```jsx |
| 200 | +import { RecordField } from 'react-admin'; |
| 201 | + |
| 202 | +<RecordField |
| 203 | + label="Name" |
| 204 | + render={record => `${record.firstName} ${record.lastName}`} |
| 205 | +/> |
| 206 | +``` |
| 207 | + |
| 208 | +If you pass both `source` and `render`, the `source` will be used for the label only. |
| 209 | + |
| 210 | +## `sx` |
| 211 | + |
| 212 | +Use the `sx` prop to pass custom styles to the field. |
| 213 | + |
| 214 | +{% raw %} |
| 215 | +```jsx |
| 216 | +<RecordField source="id" sx={{ opacity: 0.5 }} /> |
| 217 | +``` |
| 218 | +{% endraw %} |
| 219 | + |
| 220 | +If you want to style the label, use the `TypographyProps` prop instead: |
| 221 | + |
| 222 | +{% raw %} |
| 223 | +```jsx |
| 224 | +<RecordField |
| 225 | + source="id" |
| 226 | + TypographyProps={{ sx: { color: 'red' } }} |
| 227 | +/> |
| 228 | +``` |
| 229 | +{% endraw %} |
| 230 | + |
| 231 | +If you want to style the value only, prefer passing a custom component as child: |
| 232 | + |
| 233 | +{% raw %} |
| 234 | +```jsx |
| 235 | +<RecordField source="id"> |
| 236 | + <TextField source="id" sx={{ color: 'red' }} /> |
| 237 | +</RecordField> |
| 238 | +``` |
| 239 | +{% endraw %} |
| 240 | + |
| 241 | +## `source` |
| 242 | + |
| 243 | +Use the `source` prop to specify the name of the record field to render. |
| 244 | + |
| 245 | +For example, if the current record is: |
| 246 | + |
| 247 | +```json |
| 248 | +{ |
| 249 | + "id": 123, |
| 250 | + "title": "My post", |
| 251 | + "author": { |
| 252 | + "name": "John Doe" |
| 253 | + } |
| 254 | +} |
| 255 | +``` |
| 256 | + |
| 257 | +To display the `title` field, use: |
| 258 | + |
| 259 | +```jsx |
| 260 | +<RecordField source="title" /> |
| 261 | +``` |
| 262 | + |
| 263 | +The `source` prop can be a deep source, for example `author.name`. |
| 264 | + |
| 265 | +```jsx |
| 266 | +<RecordField source="author.name" /> |
| 267 | +``` |
| 268 | + |
| 269 | +If you use the `render` or `children` prop, the `source` will only be used for the label. |
| 270 | + |
| 271 | +## `TypographyProps` |
| 272 | + |
| 273 | +The `TypographyProps` prop is used to pass props to the label wrapper. This is useful when you want to style the label differently from the field value. |
| 274 | + |
| 275 | +{% raw %} |
| 276 | +```jsx |
| 277 | +<RecordField |
| 278 | + source="id" |
| 279 | + TypographyProps={{ sx: { color: 'red' } }} |
| 280 | +/> |
| 281 | +``` |
| 282 | +{% endraw %} |
| 283 | + |
| 284 | +## `variant` |
| 285 | + |
| 286 | +By default, `<RecordField>` renders the label above the field value. You can use the `variant` prop to render the label inline with the field value: |
| 287 | + |
| 288 | +```jsx |
| 289 | +<RecordField |
| 290 | + source="title" |
| 291 | + variant="inline" |
| 292 | +/> |
| 293 | +``` |
| 294 | + |
| 295 | +If you need to customize the width of the label, you can use the `TypographyProps` prop: |
| 296 | + |
| 297 | +{% raw %} |
| 298 | +```jsx |
| 299 | +<RecordField |
| 300 | + source="title" |
| 301 | + variant="inline" |
| 302 | + TypographyProps={{ sx: { width: 200 } }} |
| 303 | +/> |
| 304 | +``` |
| 305 | +{% endraw %} |
| 306 | + |
| 307 | +But since you generally need to do it for several fields, it's preferable to do it in the parent component: |
| 308 | + |
| 309 | +{% raw %} |
| 310 | +```jsx |
| 311 | +<Stack sx={{ '& .RaRecordField-label': { width: 200 } }}> |
| 312 | + <RecordField variant="inline" source="id" /> |
| 313 | + <RecordField variant="inline" source="title" /> |
| 314 | + <RecordField variant="inline" source="author" /> |
| 315 | + <RecordField variant="inline" source="summary" /> |
| 316 | + <RecordField variant="inline" source="year" field={NumberField} /> |
| 317 | +</Stack> |
| 318 | +``` |
| 319 | +{% endraw %} |
| 320 | + |
| 321 | +## TypeScript |
| 322 | + |
| 323 | +`<RecordField>` is a generic component. You can pass a type parameter to get hints for the `source` prop and type safety for the `record` argument of the `render` function. |
| 324 | + |
| 325 | +```tsx |
| 326 | +import { Show, RecordField } from 'react-admin'; |
| 327 | +import { Stack } from '@mui/material'; |
| 328 | + |
| 329 | +import { Book } from './types'; |
| 330 | + |
| 331 | +const BookShow = () => { |
| 332 | + const BookField = RecordField<Book>; |
| 333 | + return ( |
| 334 | + <Show> |
| 335 | + <Stack> |
| 336 | + <BookField source="title" /> |
| 337 | + <BookField source="author.name" /> |
| 338 | + <BookField source="price" render={record => `${record.price} USD`} /> |
| 339 | + </Stack> |
| 340 | + </Show> |
| 341 | + ); |
| 342 | +}; |
| 343 | +``` |
0 commit comments