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

Fix <DatagridConfigurable> fails to render when using a Field with a label element #8928

Merged
merged 3 commits into from
May 19, 2023
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions docs/Datagrid.md
Original file line number Diff line number Diff line change
Expand Up @@ -920,6 +920,25 @@ const PostList = () => (
);
```

The inspector uses the field `source` (or `label` when it's a string) to display the column name. If you use non-field children (e.g. action buttons), then it's your responsibility to wrap them in a component with a `label` prop, that will be used by the inspector:

```jsx
const FieldWrapper = ({ children, label }) => children;
const PostList = () => (
<List>
<DatagridConfigurable>
<TextField source="id" />
<TextField source="title" />
<TextField source="author" />
<TextField source="year" />
<FieldWrapper label="Actions">
<EditButton />
</FieldWrapper>
</DatagridConfigurable>
</List>
);
```

`<DatagridConfigurable>` accepts the same props as `<Datagrid>`.

## Editable Spreadsheet
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ import * as React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import expect from 'expect';

import { Basic, Omit, PreferenceKey } from './DatagridConfigurable.stories';
import {
Basic,
Omit,
PreferenceKey,
LabelElement,
} from './DatagridConfigurable.stories';

describe('<DatagridConfigurable>', () => {
it('should render a datagrid with configurable columns', async () => {
Expand All @@ -18,7 +23,7 @@ describe('<DatagridConfigurable>', () => {
screen.getByLabelText('Year').click();
expect(screen.queryByText('1869')).not.toBeNull();
});
it('should accept fields with a custom title', async () => {
it('should accept fields with a custom label', async () => {
render(<Basic />);
screen.getByLabelText('Configure mode').click();
await screen.findByText('Inspector');
Expand All @@ -31,6 +36,19 @@ describe('<DatagridConfigurable>', () => {
screen.getByLabelText('Original title').click();
expect(screen.queryByText('War and Peace')).not.toBeNull();
});
it('should accept fields with a label element', async () => {
render(<LabelElement />);
screen.getByLabelText('Configure mode').click();
await screen.findByText('Inspector');
fireEvent.mouseOver(screen.getByText('Leo Tolstoy'));
await screen.getByTitle('ra.configurable.customize').click();
await screen.findByText('Datagrid');
expect(screen.queryByText('War and Peace')).not.toBeNull();
screen.getByLabelText('Title').click();
expect(screen.queryByText('War and Peace')).toBeNull();
screen.getByLabelText('Title').click();
expect(screen.queryByText('War and Peace')).not.toBeNull();
});
it('should accept fields with no source', async () => {
render(<Basic />);
screen.getByLabelText('Configure mode').click();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as React from 'react';
import { MemoryRouter } from 'react-router-dom';
import { PreferencesEditorContextProvider } from 'ra-core';
import { Box } from '@mui/material';
import { memoryStore, StoreContextProvider } from 'ra-core';

import { DatagridConfigurable } from './DatagridConfigurable';
import { Inspector, InspectorButton } from '../../preferences';
Expand Down Expand Up @@ -43,91 +44,100 @@ AuthorField.defaultProps = { label: 'Author' };

const theme = createTheme();

const Wrapper = ({ children }) => (
<StoreContextProvider value={memoryStore()}>
<ThemeProvider theme={theme}>
<PreferencesEditorContextProvider>
<MemoryRouter>
<Inspector />
<Box display="flex" justifyContent="flex-end">
<InspectorButton />
</Box>
<Box p={2}>{children}</Box>
</MemoryRouter>
</PreferencesEditorContextProvider>
</ThemeProvider>
</StoreContextProvider>
);

export const Basic = () => (
<ThemeProvider theme={theme}>
<PreferencesEditorContextProvider>
<MemoryRouter>
<Inspector />
<Box display="flex" justifyContent="flex-end">
<InspectorButton />
</Box>
<Box p={2}>
<DatagridConfigurable
resource="books1"
data={data}
sort={{ field: 'title', order: 'ASC' }}
bulkActionButtons={false}
>
<TextField source="id" />
<TextField source="title" label="Original title" />
<TextField source="author" />
<TextField source="year" />
<EditButton />
</DatagridConfigurable>
</Box>
</MemoryRouter>
</PreferencesEditorContextProvider>
</ThemeProvider>
<Wrapper>
<DatagridConfigurable
resource="books1"
data={data}
sort={{ field: 'title', order: 'ASC' }}
bulkActionButtons={false}
>
<TextField source="id" />
<TextField source="title" label="Original title" />
<TextField source="author" />
<TextField source="year" />
<EditButton />
</DatagridConfigurable>
</Wrapper>
);

export const Omit = () => (
<PreferencesEditorContextProvider>
<MemoryRouter>
<Inspector />
<Box display="flex" justifyContent="flex-end">
<InspectorButton />
</Box>
<Box p={2}>
<DatagridConfigurable
resource="books2"
data={data}
sort={{ field: 'title', order: 'ASC' }}
bulkActionButtons={false}
omit={['title']}
>
<TextField source="id" />
<TextField source="title" label="Original title" />
<AuthorField />
<TextField source="year" />
</DatagridConfigurable>
</Box>
</MemoryRouter>
</PreferencesEditorContextProvider>
<Wrapper>
<DatagridConfigurable
resource="books2"
data={data}
sort={{ field: 'title', order: 'ASC' }}
bulkActionButtons={false}
omit={['title']}
>
<TextField source="id" />
<TextField source="title" label="Original title" />
<AuthorField />
<TextField source="year" />
</DatagridConfigurable>
</Wrapper>
);

export const PreferenceKey = () => (
<PreferencesEditorContextProvider>
<MemoryRouter>
<Inspector />
<Box display="flex" justifyContent="flex-end">
<InspectorButton />
</Box>
<Box p={2} display="flex" justifyContent="space-between">
<DatagridConfigurable
resource="books3"
data={data}
sort={{ field: 'title', order: 'ASC' }}
bulkActionButtons={false}
preferenceKey="pref1"
>
<TextField source="id" />
<TextField source="title" label="Original title" />
<TextField source="author" />
<TextField source="year" />
</DatagridConfigurable>
<DatagridConfigurable
resource="books3"
data={data}
sort={{ field: 'title', order: 'ASC' }}
bulkActionButtons={false}
preferenceKey="pref2"
>
<TextField source="id" />
<TextField source="title" label="Original title" />
<TextField source="author" />
<TextField source="year" />
</DatagridConfigurable>
</Box>
</MemoryRouter>
</PreferencesEditorContextProvider>
<Wrapper>
<Box p={2} display="flex" justifyContent="space-between">
<DatagridConfigurable
resource="books3"
data={data}
sort={{ field: 'title', order: 'ASC' }}
bulkActionButtons={false}
preferenceKey="pref1"
>
<TextField source="id" />
<TextField source="title" label="Original title" />
<TextField source="author" />
<TextField source="year" />
</DatagridConfigurable>
<DatagridConfigurable
resource="books3"
data={data}
sort={{ field: 'title', order: 'ASC' }}
bulkActionButtons={false}
preferenceKey="pref2"
>
<TextField source="id" />
<TextField source="title" label="Original title" />
<TextField source="author" />
<TextField source="year" />
</DatagridConfigurable>
</Box>
</Wrapper>
);

export const LabelElement = () => (
<Wrapper>
<DatagridConfigurable
resource="books1"
data={data}
sort={{ field: 'title', order: 'ASC' }}
bulkActionButtons={false}
>
<TextField source="id" />
<TextField source="title" label={<>Original title</>} />
<TextField source="author" />
<TextField source="year" />
<EditButton />
</DatagridConfigurable>
</Wrapper>
);
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,14 @@ export const DatagridConfigurable = ({
index: String(index),
source: child.props.source,
label:
child.props.source || child.props.label
child.props.label &&
typeof child.props.label === 'string' // this list is serializable, so we can't store ReactElement in it
? child.props.label
: translate(
: child.props.source
? // force the label to be the source
undefined
: // no source or label, generate a label
translate(
'ra.configurable.Datagrid.unlabeled',
{
column: index,
Expand Down