Skip to content

Commit

Permalink
feat(react-grid): support stretching virtual table to parent element (#…
Browse files Browse the repository at this point in the history
…1261)

Closes #996
  • Loading branch information
kvet authored and SergeyAlexeev committed Jul 25, 2018
1 parent dc6114b commit ded7357
Show file tree
Hide file tree
Showing 24 changed files with 216 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ VirtualTable.Container = TableContainer;

VirtualTable.propTypes = {
estimatedRowHeight: PropTypes.number,
height: PropTypes.number,
height: PropTypes.oneOfType([PropTypes.number, PropTypes.oneOf(['auto'])]),
headTableComponent: PropTypes.func,
messages: PropTypes.shape({
noData: PropTypes.string,
Expand Down
16 changes: 14 additions & 2 deletions packages/dx-react-grid-bootstrap3/src/templates/layout.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,30 @@ import * as React from 'react';
import * as PropTypes from 'prop-types';
import classNames from 'classnames';

export const Root = ({ children, className, ...restProps }) => (
<div className={classNames('panel panel-default', className)} {...restProps}>
export const Root = ({
children, className, style, ...restProps
}) => (
<div
className={classNames('panel panel-default', className)}
style={{
display: 'flex',
flexDirection: 'column',
...style,
}}
{...restProps}
>
{children}
</div>
);

Root.propTypes = {
children: PropTypes.node,
className: PropTypes.string,
style: PropTypes.object,
};

Root.defaultProps = {
children: undefined,
className: undefined,
style: null,
};
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,15 @@ export const Pager = ({
totalCount,
getMessage,
className,
style,
...restProps
}) => (
<div
className={classNames('clearfix', 'panel-footer', className)}
className={classNames('clearfix panel-footer', className)}
style={{
flex: 'none',
...style,
}}
{...restProps}
>
{!!pageSizes.length && (
Expand Down Expand Up @@ -49,8 +54,10 @@ Pager.propTypes = {
totalCount: PropTypes.number.isRequired,
getMessage: PropTypes.func.isRequired,
className: PropTypes.string,
style: PropTypes.object,
};

Pager.defaultProps = {
className: undefined,
style: null,
};
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export const TableContainer = ({
overflow: 'auto',
WebkitOverflowScrolling: 'touch',
border: 0,
margin: 0,
...style,
}}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export class TableHeaderCell extends React.PureComponent {
{showGroupingControls && (
<div
style={{
flex: '0 0 auto',
flex: 'none',
}}
>
<GroupingControl
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export const Toolbar = ({
position: 'relative',
minHeight: '55px',
padding: '0px 15px',
flex: 'none',
...style,
}}
{...restProps}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ VirtualTable.Container = TableContainer;

VirtualTable.propTypes = {
estimatedRowHeight: PropTypes.number,
height: PropTypes.number,
height: PropTypes.oneOfType([PropTypes.number, PropTypes.oneOf(['auto'])]),
headTableComponent: PropTypes.func,
messages: PropTypes.shape({
noData: PropTypes.string,
Expand Down
6 changes: 5 additions & 1 deletion packages/dx-react-grid-bootstrap4/src/templates/layout.jsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
import * as React from 'react';
import * as PropTypes from 'prop-types';
import classNames from 'classnames';

export const Root = ({ children, ...restProps }) => (
export const Root = ({ children, className, ...restProps }) => (
<div
className={classNames('d-flex flex-column', className)}
{...restProps}
>
{children}
</div>
);

Root.propTypes = {
className: PropTypes.string,
children: PropTypes.oneOfType([
PropTypes.node,
PropTypes.arrayOf(PropTypes.node),
]),
};

Root.defaultProps = {
className: undefined,
children: undefined,
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ import { Root } from './layout';

describe('Layout', () => {
describe('Root', () => {
it('should pass className to the root element', () => {
const tree = shallow((
<Root className="custom-class" />
));

expect(tree.is('.custom-class'))
.toBeTruthy();
});
it('should pass rest props to the root element', () => {
const tree = shallow((
<Root data={{ a: 1 }} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const Pager = ({
...restProps
}) => (
<div
className={classNames('clearfix', 'card-footer', className)}
className={classNames('clearfix card-footer dx-g-bs4-paging-panel', className)}
{...restProps}
>
{!!pageSizes.length && (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import * as React from 'react';<%&additionalImports%>
import {
Grid,
VirtualTable,
TableHeaderRow,
} from '@devexpress/dx-react-grid-<%&themeName%>';

import {
generateRows,
defaultColumnValues,
} from '../../../demo-data/generator';

const getRowId = row => row.id;

export default class Demo extends React.PureComponent {
constructor(props) {
super(props);

this.state = {
columns: [
{ name: 'id', title: 'ID' },
{ name: 'name', title: 'Name' },
{ name: 'sex', title: 'Sex' },
{ name: 'city', title: 'City' },
{ name: 'car', title: 'Car' },
],
rows: generateRows({
columnValues: { id: ({ index }) => index, ...defaultColumnValues },
length: 100000,
}),
};
}

render() {
const { rows, columns } = this.state;

return (
<<%&wrapperTag%> style={{ height: '600px' }}>
<Grid
rows={rows}
columns={columns}
getRowId={getRowId}
style={{ height: '100%' }}
>
<VirtualTable
height="auto"
/>
<TableHeaderRow />
</Grid>
</<%&wrapperTag%>>
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ VirtualTable.StubRow = TableStubRow;

VirtualTable.propTypes = {
estimatedRowHeight: PropTypes.number,
height: PropTypes.number,
height: PropTypes.oneOfType([PropTypes.number, PropTypes.oneOf(['auto'])]),
headTableComponent: PropTypes.func,
messages: PropTypes.shape({
noData: PropTypes.string,
Expand Down
32 changes: 26 additions & 6 deletions packages/dx-react-grid-material-ui/src/templates/layout.jsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,36 @@
import * as React from 'react';
import * as PropTypes from 'prop-types';
import classNames from 'classnames';
import { withStyles } from '@material-ui/core/styles';

export const Root = ({ children, ...restProps }) => (
<div {...restProps}>
const styles = {
root: {
overflow: 'auto',
WebkitOverflowScrolling: 'touch',
display: 'flex',
flexDirection: 'column',
},
};

const RootBase = ({
children, classes, className, ...restProps
}) => (
<div
className={classNames(classes.root, className)}
{...restProps}
>
{children}
</div>
);

Root.propTypes = {
children: PropTypes.node,
RootBase.propTypes = {
children: PropTypes.node.isRequired,
classes: PropTypes.object.isRequired,
className: PropTypes.string,
};

Root.defaultProps = {
children: undefined,
RootBase.defaultProps = {
className: undefined,
};

export const Root = withStyles(styles)(RootBase);
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const styles = theme => ({
pager: {
overflow: 'hidden',
padding: theme.spacing.unit * 1.5,
flex: 'none',
},
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { getBorderColor } from '../utils';
const styles = theme => ({
toolbar: {
borderBottom: getBorderColor(theme),
flex: 'none',
},
});

Expand Down
6 changes: 6 additions & 0 deletions packages/dx-react-grid/docs/guides/virtual-scrolling.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,9 @@ The following example demonstrates the basic Grid with virtual scrolling:
The Grid also supports column virtualization, which is demonstrated in the following demo:

.embedded-demo({ "path": "grid-virtual-scrolling/column-virtualization", "showThemeSelector": true })

## Stretching out to Parent Element Size

If the Grid should have the same size as the container element, set the `VirtualTable` plugin's `height` property to "auto" and the Grid element's style setting to `height: 100%`.

.embedded-demo({ "path": "grid-virtual-scrolling/stretching-to-parent-element", "showThemeSelector": true })
2 changes: 1 addition & 1 deletion packages/dx-react-grid/docs/reference/virtual-table.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { VirtualTable } from '@devexpress/dx-react-grid-material-ui';

Name | Type | Default | Description
-----|------|---------|------------
height | number | 530 | The virtual table's height.
height | number &#124; string | 530 | The virtual table's height.
estimatedRowHeight | number | `49` for [Bootstrap4](https://www.npmjs.com/package/@devexpress/dx-react-grid-bootstrap4); `37` for [Bootstrap](https://www.npmjs.com/package/@devexpress/dx-react-grid-bootstrap3); `48` for [Material UI](https://www.npmjs.com/package/@devexpress/dx-react-grid-material-ui) | Estimated row height. Specify the average value for a table whose rows have different heights.
columnExtensions? | Array&lt;[Table.ColumnExtension](table.md#tablecolumnextension)&gt; | | Additional column properties that the plugin can handle.
tableComponent | ComponentType&lt;object&gt; | | A component that renders a table.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { Sizer, RefHolder } from '@devexpress/dx-react-core';
import { getCollapsedGrid } from '@devexpress/dx-grid-core';
import { ColumnGroup } from './column-group';

const AUTO_HEIGHT = 'auto';

export class VirtualTableLayout extends React.PureComponent {
constructor(props) {
super(props);
Expand Down Expand Up @@ -163,7 +165,7 @@ export class VirtualTableLayout extends React.PureComponent {
bodyRows,
columns,
minColumnWidth,
height,
height: propHeight,
containerComponent: Container,
headTableComponent: HeadTable,
tableComponent: Table,
Expand All @@ -175,8 +177,14 @@ export class VirtualTableLayout extends React.PureComponent {
const { viewportLeft, viewportTop } = this.state;

return (
<Sizer>
{({ width }) => {
<Sizer
style={{
display: 'flex',
flex: 'auto',
}}
>
{({ width, height: intrisicHeight }) => {
const height = propHeight === AUTO_HEIGHT ? intrisicHeight : propHeight;
const headHeight = headerRows.reduce((acc, row) => acc + this.getRowHeight(row), 0);
const getColSpan = (
tableRow, tableColumn,
Expand Down Expand Up @@ -206,7 +214,7 @@ export class VirtualTableLayout extends React.PureComponent {

return (
<Container
style={{ height: `${height}px` }}
style={{ ...(propHeight === AUTO_HEIGHT ? null : { height: `${height}px` }) }}
onScroll={this.updateViewport}
>
{!!headerRows.length && this.renderRowsBlock(collapsedHeaderGrid, HeadTable, Head)}
Expand All @@ -222,7 +230,7 @@ export class VirtualTableLayout extends React.PureComponent {
VirtualTableLayout.propTypes = {
minWidth: PropTypes.number.isRequired,
minColumnWidth: PropTypes.number.isRequired,
height: PropTypes.number.isRequired,
height: PropTypes.oneOfType([PropTypes.number, PropTypes.oneOf(['auto'])]).isRequired,
headerRows: PropTypes.array,
bodyRows: PropTypes.array.isRequired,
columns: PropTypes.array.isRequired,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jest.mock('./column-group', () => ({
jest.mock('@devexpress/dx-react-core', () => {
const { Component } = require.requireActual('react');
return {
Sizer: ({ children }) => children({ width: 400, height: 100 }),
Sizer: ({ children }) => children({ width: 400, height: 120 }),
// eslint-disable-next-line react/prefer-stateless-function
RefHolder: class extends Component {
render() {
Expand Down Expand Up @@ -136,6 +136,33 @@ describe('VirtualTableLayout', () => {
});
});

it('should pass correct viewport at startup when height is auto', () => {
const tree = shallow((
<VirtualTableLayout
{...defaultProps}
headerRows={defaultProps.bodyRows.slice(0, 1)}
height="auto"
/>
));

tree.find('Sizer').dive();

expect(getCollapsedGrid.mock.calls[getCollapsedGrid.mock.calls.length - 2][0])
.toMatchObject({
top: 0,
left: 0,
height: defaultProps.estimatedRowHeight,
width: 400,
});
expect(getCollapsedGrid.mock.calls[getCollapsedGrid.mock.calls.length - 1][0])
.toMatchObject({
top: 0,
left: 0,
height: 120 - defaultProps.estimatedRowHeight,
width: 400,
});
});

it('should pass correct viewport at on viewport change', () => {
const tree = shallow((
<VirtualTableLayout
Expand Down
Loading

0 comments on commit ded7357

Please sign in to comment.