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

feat(react-grid): add tableRowTemplate to the TableView plugin #317

Merged
10 changes: 9 additions & 1 deletion packages/dx-react-grid-bootstrap3/src/plugins/table-view.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,25 @@ import { combineTemplates } from '@devexpress/dx-react-core';
import { TableView as TableViewBase } from '@devexpress/dx-react-grid';
import { Table } from '../templates/table';
import { TableCell } from '../templates/table-cell';
import { TableRow } from '../templates/table-row';
import { TableStubCell } from '../templates/table-stub-cell';
import { TableStubHeaderCell } from '../templates/table-stub-header-cell';
import { TableNoDataCell } from '../templates/table-no-data-cell';

const tableLayoutTemplate = props => <Table {...props} />;
const defaultRowTemplate = props => <TableRow {...props} />;
const defaultCellTemplate = props => <TableCell {...props} />;
const stubCellTemplate = props => <TableStubCell {...props} />;
const stubHeaderCellTemplate = props => <TableStubHeaderCell {...props} />;
const noDataCellTemplate = props => <TableNoDataCell {...props} />;

export const TableView = ({ tableCellTemplate, ...props }) => (
export const TableView = ({ tableCellTemplate, tableRowTemplate, ...props }) => (
<TableViewBase
tableLayoutTemplate={tableLayoutTemplate}
tableRowTemplate={combineTemplates(
tableRowTemplate,
defaultRowTemplate,
)}
tableCellTemplate={combineTemplates(
tableCellTemplate,
defaultCellTemplate,
Expand All @@ -30,8 +36,10 @@ export const TableView = ({ tableCellTemplate, ...props }) => (

TableView.propTypes = {
tableCellTemplate: PropTypes.func,
tableRowTemplate: PropTypes.func,
};

TableView.defaultProps = {
tableCellTemplate: undefined,
tableRowTemplate: undefined,
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,25 @@ import { combineTemplates } from '@devexpress/dx-react-core';
import { TableView as TableViewBase } from '@devexpress/dx-react-grid';
import { VirtualTable } from '../templates/virtual-table';
import { TableCell } from '../templates/table-cell';
import { TableRow } from '../templates/table-row';
import { TableNoDataCell } from '../templates/table-no-data-cell';
import { TableStubCell } from '../templates/table-stub-cell';
import { TableStubHeaderCell } from '../templates/table-stub-header-cell';

const tableLayoutTemplate = props => <VirtualTable {...props} />;
const defaultRowTemplate = props => <TableRow {...props} />;
const defaultCellTemplate = props => <TableCell {...props} />;
const noDataCellTemplate = props => <TableNoDataCell {...props} />;
const stubCellTemplate = props => <TableStubCell {...props} />;
const stubHeaderCellTemplate = props => <TableStubHeaderCell {...props} />;

export const VirtualTableView = ({ tableCellTemplate, ...props }) => (
export const VirtualTableView = ({ tableCellTemplate, tableRowTemplate, ...props }) => (
<TableViewBase
tableLayoutTemplate={tableLayoutTemplate}
tableRowTemplate={combineTemplates(
tableRowTemplate,
defaultRowTemplate,
)}
tableCellTemplate={combineTemplates(
tableCellTemplate,
defaultCellTemplate,
Expand All @@ -29,7 +35,9 @@ export const VirtualTableView = ({ tableCellTemplate, ...props }) => (
);
VirtualTableView.propTypes = {
tableCellTemplate: PropTypes.func,
tableRowTemplate: PropTypes.func,
};
VirtualTableView.defaultProps = {
tableCellTemplate: undefined,
tableRowTemplate: undefined,
};
20 changes: 20 additions & 0 deletions packages/dx-react-grid-bootstrap3/src/templates/table-row.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react';
import PropTypes from 'prop-types';

export const TableRow = ({ children, tableRow, ...restProps }) => (
<tr
className={tableRow.selected ? 'active' : ''}
{...restProps}
>
{children}
</tr>
);

TableRow.propTypes = {
tableRow: PropTypes.object.isRequired,
children: PropTypes.node,
};

TableRow.defaultProps = {
children: null,
};
31 changes: 31 additions & 0 deletions packages/dx-react-grid-bootstrap3/src/templates/table-row.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React from 'react';
import { mount } from 'enzyme';
import { setupConsole } from '@devexpress/dx-testing';
import { TableRow } from './table-row';

describe('TableRow', () => {
const mountTableRow = ({ tableRow }) => (
mount(
<TableRow
tableRow={tableRow}
/>,
)
);

let resetConsole;
beforeAll(() => {
resetConsole = setupConsole({ ignore: ['validateDOMNesting'] });
});

afterAll(() => {
resetConsole();
});

it('should have correct className', () => {
let tree = mountTableRow({ tableRow: {} });
expect(tree.find('tr').hasClass('active')).toBeFalsy();

tree = mountTableRow({ tableRow: { selected: true } });
expect(tree.find('tr').hasClass('active')).toBeTruthy();
});
});
11 changes: 2 additions & 9 deletions packages/dx-react-grid-bootstrap3/src/templates/table.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,12 @@ const headTemplate = ({ children, ...restProps }) => (
const bodyTemplate = ({ children, ...restProps }) => (
<tbody {...restProps}>{children}</tbody>
);
const rowTemplate = ({ children, row, ...restProps }) => (
<tr
className={row.selected ? 'active' : ''}
{...restProps}
>
{children}
</tr>
);
/* eslint-enable react/prop-types */

export const Table = ({
headerRows, bodyRows, getRowId,
columns,
cellTemplate,
rowTemplate,
onClick,
allowColumnReordering, setColumnOrder,
}) => (
Expand Down Expand Up @@ -64,6 +56,7 @@ Table.propTypes = {
bodyRows: PropTypes.array.isRequired,
columns: PropTypes.array.isRequired,
cellTemplate: PropTypes.func.isRequired,
rowTemplate: PropTypes.func.isRequired,
getRowId: PropTypes.func.isRequired,
onClick: PropTypes.func,
allowColumnReordering: PropTypes.bool.isRequired,
Expand Down
51 changes: 51 additions & 0 deletions packages/dx-react-grid-bootstrap3/src/templates/table.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React from 'react';
import { mount } from 'enzyme';
import { setupConsole } from '@devexpress/dx-testing';
import { TableLayout } from '@devexpress/dx-react-grid';
import { Table } from './table';

jest.mock('@devexpress/dx-react-grid', () => ({
TableLayout: jest.fn(),
}));

describe('Table', () => {
let resetConsole;
beforeAll(() => {
resetConsole = setupConsole({ ignore: ['validateDOMNesting'] });
});
afterAll(() => {
resetConsole();
});

afterEach(() => {
jest.resetAllMocks();
});

it('should pass rowTemplate to TableLayout', () => {
const rowTemplateMock = jest.fn();
const rowTemplateArgs = {
row: 'row',
children: null,
};
TableLayout.mockImplementation(({ rowTemplate }) => (
<table>
{rowTemplate(rowTemplateArgs)}
</table>
));

mount(
<Table
rowTemplate={rowTemplateMock}
headerRows={[]}
bodyRows={[]}
columns={[]}
cellTemplate={() => {}}
getRowId={() => {}}
allowColumnReordering={false}
setColumnOrder={() => {}}
/>,
);

expect(rowTemplateMock).toBeCalledWith(rowTemplateArgs);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export class VirtualTable extends React.Component {
};
}
render() {
const { headerRows, bodyRows, columns, cellTemplate } = this.props;
const { headerRows, bodyRows, columns, cellTemplate, rowTemplate } = this.props;

const columnWidths = calculateColumnWidths(columns, this.state.viewportWidth);
const scrollWidth = columnWidths.reduce((accum, width) => accum + width, 0);
Expand All @@ -54,7 +54,7 @@ export class VirtualTable extends React.Component {
return (
<VirtualBox
rootTag="tr"

rootTagTemplate={params => (rowTemplate({ tableRow: row, ...params }))}
position={position}
crossSize={this.rowHeight(row)}
direction="horizontal"
Expand Down Expand Up @@ -159,4 +159,5 @@ VirtualTable.propTypes = {
bodyRows: PropTypes.array.isRequired,
columns: PropTypes.array.isRequired,
cellTemplate: PropTypes.func.isRequired,
rowTemplate: PropTypes.func.isRequired,
};
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ export class VirtualBox extends React.Component {
};
}
render() {
const { direction, position, stick, iref } = this.props;
const { direction, position, stick, iref, rootTagTemplate } = this.props;
const viewport = this.context.virtualHost.viewport;

const positionProp = direction === 'horizontal' ? 'left' : 'top';
Expand Down Expand Up @@ -166,17 +166,31 @@ export class VirtualBox extends React.Component {
});

const RootTag = this.props.rootTag;
const rootTagProps = {
style: {
position: 'relative',
...this.props.style,
[sizeProp]: `${fullSize}px`,
display: 'block',
},
className: this.props.className,
};

if (rootTagTemplate) {
return rootTagTemplate({
...rootTagProps,
children: visibleItems,
});
}

return (
<RootTag
className={this.props.className}
style={{
position: 'relative',
...this.props.style,
[sizeProp]: `${fullSize}px`,
display: 'block',
}}
{...(iref ? { ref: iref } : {})}
{
...{
...(iref ? { ref: iref } : {}),
...rootTagProps,
}
}
>
{visibleItems}
</RootTag>
Expand All @@ -185,6 +199,7 @@ export class VirtualBox extends React.Component {
}
VirtualBox.defaultProps = {
rootTag: 'div',
rootTagTemplate: undefined,
className: '',
style: {},
position: 0,
Expand All @@ -194,6 +209,7 @@ VirtualBox.defaultProps = {
};
VirtualBox.propTypes = {
rootTag: PropTypes.string,
rootTagTemplate: PropTypes.func,
className: PropTypes.string,
style: PropTypes.object,
position: PropTypes.number,
Expand Down
10 changes: 9 additions & 1 deletion packages/dx-react-grid-material-ui/src/plugins/table-view.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,23 @@ import { combineTemplates } from '@devexpress/dx-react-core';
import { TableView as TableViewBase } from '@devexpress/dx-react-grid';
import { Table } from '../templates/table';
import { TableCell } from '../templates/table-cell';
import { TableRow } from '../templates/table-row';
import { TableStubCell } from '../templates/table-stub-cell';
import { TableNoDataCell } from '../templates/table-no-data-cell';

const tableLayoutTemplate = props => <Table {...props} />;
const defaultRowTemplate = props => <TableRow {...props} />;
const defaultCellTemplate = props => <TableCell {...props} />;
const stubCellTemplate = props => <TableStubCell {...props} />;
const noDataCellTemplate = props => <TableNoDataCell {...props} />;

export const TableView = ({ tableCellTemplate, ...props }) => (
export const TableView = ({ tableCellTemplate, tableRowTemplate, ...props }) => (
<TableViewBase
tableLayoutTemplate={tableLayoutTemplate}
tableRowTemplate={combineTemplates(
tableRowTemplate,
defaultRowTemplate,
)}
tableCellTemplate={combineTemplates(
tableCellTemplate,
defaultCellTemplate,
Expand All @@ -27,7 +33,9 @@ export const TableView = ({ tableCellTemplate, ...props }) => (
);
TableView.propTypes = {
tableCellTemplate: PropTypes.func,
tableRowTemplate: PropTypes.func,
};
TableView.defaultProps = {
tableCellTemplate: undefined,
tableRowTemplate: undefined,
};
27 changes: 27 additions & 0 deletions packages/dx-react-grid-material-ui/src/templates/table-row.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from 'react';
import PropTypes from 'prop-types';

import {
TableRow as TableRowMUI,
} from 'material-ui';
import { withStyles } from 'material-ui/styles';

const TableRowBase = ({ children, tableRow, ...restProps }) => (
<TableRowMUI
selected={tableRow.selected}
{...restProps}
>
{children}
</TableRowMUI>
);

TableRowBase.propTypes = {
tableRow: PropTypes.object.isRequired,
children: PropTypes.node,
};

TableRowBase.defaultProps = {
children: null,
};

export const TableRow = withStyles({}, { name: 'TableRow' })(TableRowBase);
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React from 'react';
import { TableRow as TableRowMUI } from 'material-ui';
import { createMount } from 'material-ui/test-utils';
import { setupConsole } from '@devexpress/dx-testing';
import { TableRow } from './table-row';

describe('TableRow', () => {
let resetConsole;
let mount;

const mountTableCell = ({ tableRow }) => (
mount(
<TableRow
tableRow={tableRow}
/>,
)
);
beforeAll(() => {
resetConsole = setupConsole({ ignore: ['validateDOMNesting'] });
mount = createMount();
});
afterAll(() => {
resetConsole();
mount.cleanUp();
});

it('should have correct selected prop', () => {
let tree = mountTableCell({ tableRow: { } });
expect(tree.find(TableRowMUI).prop('selected')).toBeFalsy();

tree = mountTableCell({ tableRow: { selected: true } });
expect(tree.find(TableRowMUI).prop('selected')).toBeTruthy();
});
});
Loading