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

Added initialWidth and isResizable configurables to EuiDataGridColumn #2696

Merged
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- Converted `EuiTextArea` to Typescript ([#2695](https://github.com/elastic/eui/pull/2695))
- Converted `EuiPage` and related child components to TypeScript ([#2669](https://github.com/elastic/eui/pull/2669))
- Added `annotation` glyph ([#2691](https://github.com/elastic/eui/pull/2691))
- Added `initialWidth` and `isResizable` configurations to `EuiDataGrid`'s columns ([#2696](https://github.com/elastic/eui/pull/2696))

**Bug fixes**

Expand Down
96 changes: 96 additions & 0 deletions src-docs/src/views/datagrid/column_widths.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import React, { Component } from 'react';
import { fake } from 'faker';

import { EuiDataGrid, EuiAvatar } from '../../../../src/components/';

const columns = [
{
id: 'avatar',
initialWidth: 40,
isResizable: false,
},
{
id: 'name',
initialWidth: 100,
},
{
id: 'email',
},
{
id: 'city',
},
{
id: 'country',
},
{
id: 'account',
},
];

const data = [];

for (let i = 1; i < 5; i++) {
data.push({
avatar: (
<EuiAvatar
size="s"
imageUrl={fake('{{internet.avatar}}')}
name={fake('{{name.lastName}}, {{name.firstName}}')}
/>
),
name: fake('{{name.lastName}}, {{name.firstName}} {{name.suffix}}'),
email: fake('{{internet.email}}'),
city: fake('{{address.city}}'),
country: fake('{{address.country}}'),
account: fake('{{finance.account}}'),
});
}

export default class DataGrid extends Component {
constructor(props) {
super(props);
this.state = {
pagination: {
pageIndex: 0,
pageSize: 50,
},

visibleColumns: columns.map(({ id }) => id),
};
}

setPageIndex = pageIndex =>
this.setState(({ pagination }) => ({
pagination: { ...pagination, pageIndex },
}));

setPageSize = pageSize =>
this.setState(({ pagination }) => ({
pagination: { ...pagination, pageSize },
}));

setVisibleColumns = visibleColumns => this.setState({ visibleColumns });

render() {
const { pagination } = this.state;

return (
<EuiDataGrid
aria-label="DataGrid demonstrating column sizing constraints"
columns={columns}
columnVisibility={{
visibleColumns: this.state.visibleColumns,
setVisibleColumns: this.setVisibleColumns,
}}
rowCount={data.length}
renderCellValue={({ rowIndex, columnId }) => data[rowIndex][columnId]}
pagination={{
...pagination,
pageSizeOptions: [5, 10, 25],
onChangeItemsPerPage: this.setPageSize,
onChangePage: this.setPageIndex,
}}
/>
);
}
}
2 changes: 2 additions & 0 deletions src-docs/src/views/datagrid/datagrid.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ const columns = [
},
{
id: 'version',
initialWidth: 65,
isResizable: false,
},
];

Expand Down
3 changes: 2 additions & 1 deletion src-docs/src/views/datagrid/datagrid_example.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ const gridSnippet = `
rowCount={200}
// Required. Sets up three columns, the last of which has a custom schema we later define down below.
// The second column B won't allow clicking in to see the content in a popup.
columns={[{ id: 'A' }, { id: 'B', isExpandable: false }, {id: 'C', schema: 'franchise'}]}
// The first column defines an starting width of 150px and prevents the user from resizing it
columns={[{ id: 'A', initialWidth: 150, isResizable: false }, { id: 'B', isExpandable: false }, {id: 'C', schema: 'franchise'}]}
// Optional. This allows you to initially hide columns. Users can still turn them on.
columnVisibility={{
visibleColumns: ['A', 'C'],
Expand Down
71 changes: 70 additions & 1 deletion src-docs/src/views/datagrid/datagrid_styling_example.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,24 @@ import DataGridControls from './additional_controls';
const dataGridControlsSource = require('!!raw-loader!./additional_controls');
const dataGridControlsHtml = renderToHtml(DataGridControls);

import { DataGridStyle, DataGridToolbarVisibilityOptions } from './props';
import DataGridColumnWidths from './column_widths';
const dataGridColumnWidthsSource = require('!!raw-loader!./column_widths');
const dataGridColumnWidthsHtml = renderToHtml(DataGridColumnWidths);

import {
DataGridStyle,
DataGridToolbarVisibilityOptions,
DataGridColumn,
} from './props';

const gridSnippet = `<EuiDataGrid
{...usualProps}
columns={[
// three columns are available, but restrict Avatar to 50px and don't let users resize it
{ id: 'Avatar', initialWidth: 50, isResizable: false },
{ id: 'Name' },
{ id: 'Email' },
]}
// This can work as a shape.
toolbarVisibility={{
showColumnSelector: false
Expand Down Expand Up @@ -91,6 +105,21 @@ const controlsSnippet = `<EuiDataGrid
/>
`;

const widthsSnippet = `<EuiDataGrid
{...usualGridProps}
columns={[
{
id: 'Column A',
initialWidth: 100, // start at 100px
},
{
id: 'Column B',
isResizable: false, // don't let users resize this column
},
]}
/>
`;

export const DataGridStylingExample = {
title: 'Data grid styling and toolbar',
sections: [
Expand Down Expand Up @@ -188,5 +217,45 @@ export const DataGridStylingExample = {
snippet: controlsSnippet,
demo: <DataGridControls />,
},
{
source: [
{
type: GuideSectionTypes.JS,
code: dataGridColumnWidthsSource,
},
{
type: GuideSectionTypes.HTML,
code: dataGridColumnWidthsHtml,
},
],
title: 'Column width constraints',
text: (
<Fragment>
<p>
By default, visible columns are given equal widths to fill up
available space in the grid and can be resized by the user to any
desired width. There are two parameters on{' '}
<EuiCode>EuiDataGridColumn</EuiCode> to change this default
behavior. <EuiCode>initialWidth</EuiCode> is a numeric value
providing the starting width of a column, in pixels. Second, the{' '}
<EuiCode>isResizable</EuiCode> value can be set to{' '}
<EuiCode>false</EuiCode> to remove the user&apos;s ability to resize
column.
</p>
<p>
Below, the first column is given an initial width and is not
resizable. The second column is also given an initial width but its
width can still be changed.
</p>
</Fragment>
),
components: { DataGridColumnWidths },
snippet: widthsSnippet,
props: {
EuiDataGrid,
EuiDataGridColumn: DataGridColumn,
},
demo: <DataGridColumnWidths />,
},
],
};
113 changes: 84 additions & 29 deletions src/components/datagrid/data_grid.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1126,12 +1126,12 @@ Array [
});
});

describe('column resizing', () => {
it('resizes a column by grab handles', () => {
describe('column sizing', () => {
it('uses a columns initialWidth', () => {
const component = mount(
<EuiDataGrid
aria-labelledby="#test"
columns={[{ id: 'Column 1' }, { id: 'Column 2' }]}
columns={[{ id: 'Column 1', initialWidth: 400 }, { id: 'Column 2' }]}
columnVisibility={{
visibleColumns: ['Column 1', 'Column 2'],
setVisibleColumns: () => {},
Expand All @@ -1143,42 +1143,97 @@ Array [

const originalCellWidths = extractColumnWidths(component);
expect(originalCellWidths).toEqual({
'Column 1': 100,
'Column 1': 400,
'Column 2': 100,
});
});

describe('resizing', () => {
it('resizes a column by grab handles', () => {
const component = mount(
<EuiDataGrid
aria-labelledby="#test"
columns={[{ id: 'Column 1' }, { id: 'Column 2' }]}
columnVisibility={{
visibleColumns: ['Column 1', 'Column 2'],
setVisibleColumns: () => {},
}}
rowCount={3}
renderCellValue={() => 'value'}
/>
);

resizeColumn(component, 'Column 1', 150);
const originalCellWidths = extractColumnWidths(component);
expect(originalCellWidths).toEqual({
'Column 1': 100,
'Column 2': 100,
});

const updatedCellWidths = extractColumnWidths(component);
expect(updatedCellWidths).toEqual({
'Column 1': 150,
'Column 2': 100,
resizeColumn(component, 'Column 1', 150);

const updatedCellWidths = extractColumnWidths(component);
expect(updatedCellWidths).toEqual({
'Column 1': 150,
'Column 2': 100,
});
});
});

it('does not trigger value re-renders', () => {
const renderCellValue = jest.fn(() => 'value');
it('is prevented by isResizable:false', () => {
const component = mount(
<EuiDataGrid
aria-labelledby="#test"
columns={[
{ id: 'Column 1', isResizable: false },
{ id: 'Column 2' },
]}
columnVisibility={{
visibleColumns: ['Column 1', 'Column 2'],
setVisibleColumns: () => {},
}}
rowCount={3}
renderCellValue={() => 'value'}
/>
);

const originalCellWidths = extractColumnWidths(component);
expect(originalCellWidths).toEqual({
'Column 1': 100,
'Column 2': 100,
});

const component = mount(
<EuiDataGrid
aria-labelledby="#test"
columns={[{ id: 'ColumnA' }]}
columnVisibility={{
visibleColumns: ['ColumnA'],
setVisibleColumns: () => {},
}}
rowCount={3}
renderCellValue={renderCellValue}
/>
);
// verify there is no resizer on Column 1 but that there is on Column 2
expect(
component.find('EuiDataGridColumnResizer[columnId="Column 1"]').length
).toBe(0);
expect(
component.find('EuiDataGridColumnResizer[columnId="Column 2"]').length
).toBe(1);
});

expect(renderCellValue).toHaveBeenCalledTimes(3);
renderCellValue.mockClear();
it('does not trigger value re-renders', () => {
const renderCellValue = jest.fn(() => 'value');

resizeColumn(component, 'ColumnA', 200);
const component = mount(
<EuiDataGrid
aria-labelledby="#test"
columns={[{ id: 'ColumnA' }]}
columnVisibility={{
visibleColumns: ['ColumnA'],
setVisibleColumns: () => {},
}}
rowCount={3}
renderCellValue={renderCellValue}
/>
);

expect(extractColumnWidths(component)).toEqual({ ColumnA: 200 });
expect(renderCellValue).toHaveBeenCalledTimes(0);
expect(renderCellValue).toHaveBeenCalledTimes(3);
renderCellValue.mockClear();

resizeColumn(component, 'ColumnA', 200);

expect(extractColumnWidths(component)).toEqual({ ColumnA: 200 });
expect(renderCellValue).toHaveBeenCalledTimes(0);
});
});
});

Expand Down
Loading