Skip to content

Commit 33aef90

Browse files
authored
Merge pull request #10749 from marmelab/recordfield
Add RecordField component
2 parents 4f9f836 + 9c87f76 commit 33aef90

File tree

9 files changed

+994
-16
lines changed

9 files changed

+994
-16
lines changed

docs/RecordField.md

Lines changed: 411 additions & 0 deletions
Large diffs are not rendered by default.

docs/Reference.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ title: "Index"
149149
**- R -**
150150

151151
* [`<RadioButtonGroupInput>`](./RadioButtonGroupInput.md)
152+
* [`<RecordField>`](./RecordField.md)
152153
* [`<RecordRepresentation>`](./RecordRepresentation.md)
153154
* [`<ReferenceArrayField>`](./ReferenceArrayField.md)
154155
* [`<ReferenceArrayInput>`](./ReferenceArrayInput.md)

docs/_includes/navigation.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@
183183
<li {% if page.path == 'ImageField.md' %} class="active beginner" {% else %} class="beginner" {% endif %}><a class="nav-link" href="./ImageField.html"><code>&lt;ImageField&gt;</code></a></li>
184184
<li {% if page.path == 'MarkdownField.md' %} class="active" {% endif %}><a class="nav-link" href="./MarkdownField.html"><code>&lt;MarkdownField&gt;</code><img class="premium" src="./img/premium.svg" /></a></li>
185185
<li {% if page.path == 'NumberField.md' %} class="active beginner" {% else %} class="beginner" {% endif %}><a class="nav-link" href="./NumberField.html"><code>&lt;NumberField&gt;</code></a></li>
186+
<li {% if page.path == 'RecordField.md' %} class="active beginner" {% else %} class="beginner" {% endif %}><a class="nav-link" href="./RecordField.html"><code>&lt;RecordField&gt;</code></a></li>
186187
<li {% if page.path == 'ReferenceField.md' %} class="active beginner" {% else %} class="beginner" {% endif %}><a class="nav-link" href="./ReferenceField.html"><code>&lt;ReferenceField&gt;</code></a></li>
187188
<li {% if page.path == 'ReferenceArrayField.md' %} class="active beginner" {% else %} class="beginner" {% endif %}><a class="nav-link" href="./ReferenceArrayField.html"><code>&lt;ReferenceArrayField&gt;</code></a></li>
188189
<li {% if page.path == 'ReferenceManyField.md' %} class="active beginner" {% else %} class="beginner" {% endif %}><a class="nav-link" href="./ReferenceManyField.html"><code>&lt;ReferenceManyField&gt;</code></a></li>

docs/img/RecordField.png

40.5 KB
Loading

examples/simple/src/comments/CommentShow.tsx

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,18 @@
11
import * as React from 'react';
2-
import {
3-
DateField,
4-
ReferenceField,
5-
Show,
6-
SimpleShowLayout,
7-
TextField,
8-
} from 'react-admin';
2+
import { DateField, ReferenceField, RecordField, Show } from 'react-admin';
3+
import { Stack } from '@mui/material';
94

105
const CommentShow = () => (
116
<Show queryOptions={{ meta: { prefetch: ['post'] } }}>
12-
<SimpleShowLayout>
13-
<TextField source="id" />
14-
<ReferenceField source="post_id" reference="posts">
15-
<TextField source="title" />
16-
</ReferenceField>
17-
<TextField source="author.name" />
18-
<DateField source="created_at" />
19-
<TextField source="body" />
20-
</SimpleShowLayout>
7+
<Stack gap={1} sx={{ py: 1, px: 2 }}>
8+
<RecordField source="id" />
9+
<RecordField source="post_id">
10+
<ReferenceField source="post_id" reference="posts" />
11+
</RecordField>
12+
<RecordField source="author.name" />
13+
<RecordField field={DateField} source="created_at" />
14+
<RecordField source="body" />
15+
</Stack>
2116
</Show>
2217
);
2318

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import * as React from 'react';
2+
import expect from 'expect';
3+
import { render, screen } from '@testing-library/react';
4+
5+
import {
6+
Basic,
7+
Source,
8+
Label,
9+
Empty,
10+
Render,
11+
Field,
12+
Children,
13+
} from './RecordField.stories';
14+
export default {
15+
title: 'ra-ui-materialui/fields/RecordField',
16+
};
17+
18+
describe('<RecordField />', () => {
19+
describe('source', () => {
20+
it('should render the source field from the record in context', () => {
21+
render(<Basic />);
22+
expect(screen.queryByText('War and Peace')).not.toBeNull();
23+
});
24+
it('should render nothing when the source is not found', () => {
25+
render(<Source />);
26+
expect(screen.queryByText('Missing field')).not.toBeNull();
27+
});
28+
it('should support paths with dots', () => {
29+
render(<Source />);
30+
expect(screen.queryByText('Leo Tolstoy')).not.toBeNull();
31+
});
32+
});
33+
describe('label', () => {
34+
it('should render the humanized source as label by default', () => {
35+
render(<Basic />);
36+
expect(screen.queryByText('Title')).not.toBeNull();
37+
});
38+
it('should render the label prop as label', () => {
39+
render(<Label />);
40+
expect(screen.queryByText('Identifier')).not.toBeNull();
41+
});
42+
it('should render no label when label is false', () => {
43+
render(<Label />);
44+
expect(screen.queryByText('Summary')).toBeNull();
45+
});
46+
});
47+
describe('empty', () => {
48+
it('should render the translated empty when the record is undefined', () => {
49+
render(<Empty />);
50+
expect(screen.queryByText('No title')).not.toBeNull();
51+
});
52+
it('should render the translated empty when using a render prop', () => {
53+
render(<Empty />);
54+
expect(screen.queryByText('Unknown author')).not.toBeNull();
55+
});
56+
it('should render the translated empty when using a field prop', () => {
57+
render(<Empty />);
58+
expect(screen.queryByText('0')).not.toBeNull();
59+
});
60+
});
61+
describe('render', () => {
62+
it('should render the value using the render prop', () => {
63+
render(<Render />);
64+
expect(screen.queryByText('WAR AND PEACE')).not.toBeNull();
65+
});
66+
it('should allow to render a React element', () => {
67+
render(<Render />);
68+
expect(screen.queryByText('LEO TOLSTOY')).not.toBeNull();
69+
});
70+
it('should not fail when the record is undefined', () => {
71+
render(<Render />);
72+
expect(screen.queryByText('Summary')).not.toBeNull();
73+
});
74+
});
75+
describe('field', () => {
76+
it('should use the field component to render the field', () => {
77+
render(<Field />);
78+
expect(screen.queryByText('1,869')).not.toBeNull();
79+
});
80+
});
81+
describe('children', () => {
82+
it('should render the field using the children rather than a TextField', () => {
83+
render(<Children />);
84+
expect(screen.queryByText('Leo Tolstoy')).not.toBeNull();
85+
expect(screen.queryByText('(DECD)')).not.toBeNull();
86+
});
87+
});
88+
});

0 commit comments

Comments
 (0)