Skip to content

Add RecordField component #10749

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

Open
wants to merge 6 commits into
base: next
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
411 changes: 411 additions & 0 deletions docs/RecordField.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions docs/Reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ title: "Index"
**- R -**

* [`<RadioButtonGroupInput>`](./RadioButtonGroupInput.md)
* [`<RecordField>`](./RecordField.md)
* [`<RecordRepresentation>`](./RecordRepresentation.md)
* [`<ReferenceArrayField>`](./ReferenceArrayField.md)
* [`<ReferenceArrayInput>`](./ReferenceArrayInput.md)
Expand Down
1 change: 1 addition & 0 deletions docs/_includes/navigation.html
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@
<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>
<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>
<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>
<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>
<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>
<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>
<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>
Expand Down
Binary file added docs/img/RecordField.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
27 changes: 11 additions & 16 deletions examples/simple/src/comments/CommentShow.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,18 @@
import * as React from 'react';
import {
DateField,
ReferenceField,
Show,
SimpleShowLayout,
TextField,
} from 'react-admin';
import { DateField, ReferenceField, RecordField, Show } from 'react-admin';
import { Stack } from '@mui/material';

const CommentShow = () => (
<Show queryOptions={{ meta: { prefetch: ['post'] } }}>
<SimpleShowLayout>
<TextField source="id" />
<ReferenceField source="post_id" reference="posts">
<TextField source="title" />
</ReferenceField>
<TextField source="author.name" />
<DateField source="created_at" />
<TextField source="body" />
</SimpleShowLayout>
<Stack gap={1} sx={{ py: 1, px: 2 }}>
<RecordField source="id" />
<RecordField source="post_id">
<ReferenceField source="post_id" reference="posts" />
</RecordField>
<RecordField source="author.name" />
<RecordField field={DateField} source="created_at" />
<RecordField source="body" />
</Stack>
</Show>
);

Expand Down
88 changes: 88 additions & 0 deletions packages/ra-ui-materialui/src/field/RecordField.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import * as React from 'react';
import expect from 'expect';
import { render, screen } from '@testing-library/react';

import {
Basic,
Source,
Label,
Empty,
Render,
Field,
Children,
} from './RecordField.stories';
export default {
title: 'ra-ui-materialui/fields/RecordField',
};

describe('<RecordField />', () => {
describe('source', () => {
it('should render the source field from the record in context', () => {
render(<Basic />);
expect(screen.queryByText('War and Peace')).not.toBeNull();
});
it('should render nothing when the source is not found', () => {
render(<Source />);
expect(screen.queryByText('Missing field')).not.toBeNull();
});
it('should support paths with dots', () => {
render(<Source />);
expect(screen.queryByText('Leo Tolstoy')).not.toBeNull();
});
});
describe('label', () => {
it('should render the humanized source as label by default', () => {
render(<Basic />);
expect(screen.queryByText('Title')).not.toBeNull();
});
it('should render the label prop as label', () => {
render(<Label />);
expect(screen.queryByText('Identifier')).not.toBeNull();
});
it('should render no label when label is false', () => {
render(<Label />);
expect(screen.queryByText('Summary')).toBeNull();
});
});
describe('empty', () => {
it('should render the translated empty when the record is undefined', () => {
render(<Empty />);
expect(screen.queryByText('No title')).not.toBeNull();
});
it('should render the translated empty when using a render prop', () => {
render(<Empty />);
expect(screen.queryByText('Unknown author')).not.toBeNull();
});
it('should render the translated empty when using a field prop', () => {
render(<Empty />);
expect(screen.queryByText('0')).not.toBeNull();
});
});
describe('render', () => {
it('should render the value using the render prop', () => {
render(<Render />);
expect(screen.queryByText('WAR AND PEACE')).not.toBeNull();
});
it('should allow to render a React element', () => {
render(<Render />);
expect(screen.queryByText('LEO TOLSTOY')).not.toBeNull();
});
it('should not fail when the record is undefined', () => {
render(<Render />);
expect(screen.queryByText('Summary')).not.toBeNull();
});
});
describe('field', () => {
it('should use the field component to render the field', () => {
render(<Field />);
expect(screen.queryByText('1,869')).not.toBeNull();
});
});
describe('children', () => {
it('should render the field using the children rather than a TextField', () => {
render(<Children />);
expect(screen.queryByText('Leo Tolstoy')).not.toBeNull();
expect(screen.queryByText('(DECD)')).not.toBeNull();
});
});
});
Loading
Loading