Compare commits

..

20 Commits

Author SHA1 Message Date
AllenFang
d3161f02eb Publish
- react-bootstrap-table2-example@1.0.12
 - react-bootstrap-table-next@1.4.3
2018-12-21 16:51:04 +08:00
Allen
28ba6d5677 Merge pull request #721 from react-bootstrap-table/develop
20181221 release
2018-12-21 16:49:35 +08:00
AllenFang
4ddbfd4972 fix #711 2018-12-21 16:23:38 +08:00
AllenFang
d84dc46ff1 Merge branch 'vinzentt-fix-nonExpandable-indicator-and-behaviour' into develop 2018-12-20 23:52:42 +08:00
AllenFang
e0163625d4 add expandable for expandColumnRenderer 2018-12-20 23:47:30 +08:00
AllenFang
24ab58a464 row expandable already calculated from row expand consumer, just use it instead do the logic again 2018-12-20 23:45:20 +08:00
Allen
6e19368733 Merge branch 'develop' into fix-nonExpandable-indicator-and-behaviour 2018-12-20 23:27:48 +08:00
AllenFang
bc4697bf95 fix #701 2018-12-20 23:20:12 +08:00
AllenFang
9d2a6a1b23 Publish
- react-bootstrap-table2-example@1.0.11
 - react-bootstrap-table-next@1.4.2
2018-12-05 23:31:35 +08:00
Allen
bb752fcec8 Merge pull request #699 from react-bootstrap-table/develop
20181205 release
2018-12-05 23:30:19 +08:00
Vincent Degroote
aedd1f5942 Add expandColumn in storybook example for nonExpandable rows 2018-12-05 11:37:32 +01:00
Vincent Degroote
5a5f10f609 fix tests when nonExpndable is not given 2018-12-05 11:23:38 +01:00
Vincent Degroote
e041a3d736 revert not needed changes 2018-12-05 10:55:04 +01:00
Vincent Degroote
f175fd4186 Hide expand indicator if row is not expandable and prevent it from being expanded 2018-12-05 10:50:52 +01:00
AllenFang
5a6b7e122d fix #680 2018-12-02 17:45:42 +08:00
AllenFang
a7ae524c49 fix #675 2018-12-02 17:29:25 +08:00
AllenFang
a23599f52f fix #669 2018-12-02 17:04:32 +08:00
EricH
c50853b16d Fix typo in doc example code (#691) 2018-12-02 15:48:52 +08:00
NickChen
3f74542c98 Merge pull request #670 from react-bootstrap-table/enhancement/remove-unnecessary-props-bootstrap4
LGTM
2018-11-18 18:04:24 +08:00
Chun-MingChen
47aa41b8fa Remove unnecessary props 'bootstrap4' 2018-11-18 17:55:27 +08:00
19 changed files with 183 additions and 42 deletions

View File

@@ -27,6 +27,7 @@
* [rowStyle](#rowStyle) * [rowStyle](#rowStyle)
* [rowClasses](#rowClasses) * [rowClasses](#rowClasses)
* [rowEvents](#rowEvents) * [rowEvents](#rowEvents)
* [hiddenRows](#hiddenRows)
* [defaultSorted](#defaultSorted) * [defaultSorted](#defaultSorted)
* [defaultSortDirection](#defaultSortDirection) * [defaultSortDirection](#defaultSortDirection)
* [pagination](#pagination) * [pagination](#pagination)
@@ -181,6 +182,14 @@ const rowEvents = {
<BootstrapTable data={ data } columns={ columns } rowEvents={ rowEvents } /> <BootstrapTable data={ data } columns={ columns } rowEvents={ rowEvents } />
``` ```
### <a name='hiddenRows'>hiddenRows - [Array]</a>
Hide rows, this props accept an array of row keys:
```js
const hiddenRows = [1, 4];
<BootstrapTable data={ data } columns={ columns } hiddenRows={ hiddenRows } />
```
### <a name='defaultSorted'>defaultSorted - [Array]</a> ### <a name='defaultSorted'>defaultSorted - [Array]</a>
`defaultSorted` accept an object array which allow you to define the default sort columns when first render. `defaultSorted` accept an object array which allow you to define the default sort columns when first render.

View File

@@ -92,13 +92,16 @@ const expandRow = {
``` ```
### <a name='expandColumnRenderer'>expandRow.expandColumnRenderer - [Function]</a> ### <a name='expandColumnRenderer'>expandRow.expandColumnRenderer - [Function]</a>
Provide a callback function which allow you to custom the expand indicator. This callback only have one argument which is an object and contain one property `expanded` which indicate if current row is expanded Provide a callback function which allow you to custom the expand indicator. This callback only have one argument which is an object and contain these properties:
* `expanded`: If current row is expanded or not
* `rowKey`: Current row key
* `expandable`: If currnet row is expandable or not
```js ```js
const expandRow = { const expandRow = {
renderer: (row) => ... renderer: (row) => ...
expandColumnRenderer: ({ expanded }) => ( expandColumnRenderer: ({ expanded, rowKey, expandable }) => (
// .... // ....
) )
}; };

View File

@@ -103,7 +103,7 @@ const columns = [{
}, { }, {
dataField: 'quality', dataField: 'quality',
text: 'Product Quality', text: 'Product Quality',
editorRenderer: (editorProps, value, row, rowIndex, columnIndex) => ( editorRenderer: (editorProps, value, row, column, rowIndex, columnIndex) => (
<QualityRanger { ...editorProps } value={ value } /> <QualityRanger { ...editorProps } value={ value } />
) )
}]; }];

View File

@@ -2,9 +2,9 @@ import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next'; import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block'; import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common'; import { productsGenerator, withOnSale } from 'utils/common';
const products = productsGenerator(); const products = withOnSale(productsGenerator());
function priceFormatter(cell, row) { function priceFormatter(cell, row) {
if (row.onSale) { if (row.onSale) {

View File

@@ -1,4 +1,5 @@
/* eslint react/prop-types: 0 */ /* eslint react/prop-types: 0 */
/* eslint no-unused-vars: 0 */
import React from 'react'; import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next'; import BootstrapTable from 'react-bootstrap-table-next';
@@ -33,7 +34,7 @@ const expandRow = {
} }
return <b>+</b>; return <b>+</b>;
}, },
expandColumnRenderer: ({ expanded }) => { expandColumnRenderer: ({ expanded, rowKey, expandable }) => {
if (expanded) { if (expanded) {
return ( return (
<b>-</b> <b>-</b>

View File

@@ -25,6 +25,7 @@ const expandRow = {
<p>expandRow.renderer callback will pass the origin row object to you</p> <p>expandRow.renderer callback will pass the origin row object to you</p>
</div> </div>
), ),
showExpandColumn: true,
nonExpandable: [1, 3] nonExpandable: [1, 3]
}; };
@@ -50,6 +51,7 @@ const expandRow = {
<p>expandRow.renderer callback will pass the origin row object to you</p> <p>expandRow.renderer callback will pass the origin row object to you</p>
</div> </div>
), ),
showExpandColumn: true,
nonExpandable: [1, 3] nonExpandable: [1, 3]
}; };

View File

@@ -0,0 +1,57 @@
/* eslint no-unused-vars: 0 */
/* eslint no-console: 0 */
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
const products = productsGenerator();
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const rowEvents = {
onClick: (e, row, rowIndex) => {
console.log(`clicked on row with index: ${rowIndex}`);
},
onMouseEnter: (e, row, rowIndex) => {
console.log(`enter on row with index: ${rowIndex}`);
}
};
const sourceCode = `\
import BootstrapTable from 'react-bootstrap-table-next';
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const hiddenRowKeys = [1, 3];
<BootstrapTable keyField="id" data={ products } columns={ columns } hiddenRows={ hiddenRowKeys } />
`;
const hiddenRowKeys = [1, 3];
export default () => (
<div>
<BootstrapTable keyField="id" data={ products } columns={ columns } hiddenRows={ hiddenRowKeys } />
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -1,6 +1,6 @@
{ {
"name": "react-bootstrap-table2-example", "name": "react-bootstrap-table2-example",
"version": "1.0.10", "version": "1.0.12",
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"private": true, "private": true,

View File

@@ -1,4 +1,5 @@
/* eslint no-mixed-operators: 0 */ /* eslint no-mixed-operators: 0 */
/* eslint no-param-reassign: 0 */
/** /**
* products generator for stories * products generator for stories
@@ -22,6 +23,12 @@ export const productsGenerator = (quantity = 5, callback) => {
); );
}; };
export const withOnSale = rows => rows.map((row) => {
if (row.id > 2) row.onSale = false;
else row.onSale = true;
return row;
});
export const productsQualityGenerator = (quantity = 5) => export const productsQualityGenerator = (quantity = 5) =>
Array.from({ length: quantity }, (value, index) => ({ Array.from({ length: quantity }, (value, index) => ({
id: index, id: index,

View File

@@ -79,6 +79,7 @@ import ClearAllFilters from 'examples/column-filter/clear-all-filters';
import RowStyleTable from 'examples/rows/row-style'; import RowStyleTable from 'examples/rows/row-style';
import RowClassTable from 'examples/rows/row-class'; import RowClassTable from 'examples/rows/row-class';
import RowEventTable from 'examples/rows/row-event'; import RowEventTable from 'examples/rows/row-event';
import RowHiddenTable from 'examples/rows/row-hidden';
// table sort // table sort
import EnableSortTable from 'examples/sort/enable-sort-table'; import EnableSortTable from 'examples/sort/enable-sort-table';
@@ -271,6 +272,7 @@ storiesOf('Work on Rows', module)
.addDecorator(bootstrapStyle()) .addDecorator(bootstrapStyle())
.add('Customize Row Style', () => <RowStyleTable />) .add('Customize Row Style', () => <RowStyleTable />)
.add('Customize Row Class', () => <RowClassTable />) .add('Customize Row Class', () => <RowClassTable />)
.add('Hide Rows', () => <RowHiddenTable />)
.add('Row Event', () => <RowEventTable />); .add('Row Event', () => <RowEventTable />);
storiesOf('Sort Table', module) storiesOf('Sort Table', module)

View File

@@ -1,6 +1,6 @@
{ {
"name": "react-bootstrap-table-next", "name": "react-bootstrap-table-next",
"version": "1.4.1", "version": "1.4.3",
"description": "Next generation of react-bootstrap-table", "description": "Next generation of react-bootstrap-table",
"main": "./lib/index.js", "main": "./lib/index.js",
"repository": { "repository": {

View File

@@ -21,7 +21,7 @@ class BootstrapTable extends PropsBaseResolver(Component) {
// Exposed APIs // Exposed APIs
getData() { getData() {
return this.props.data; return this.visibleRows();
} }
render() { render() {
@@ -39,7 +39,6 @@ class BootstrapTable extends PropsBaseResolver(Component) {
renderTable() { renderTable() {
const { const {
data,
columns, columns,
keyField, keyField,
tabIndexCell, tabIndexCell,
@@ -88,7 +87,7 @@ class BootstrapTable extends PropsBaseResolver(Component) {
expandRow={ expandRow } expandRow={ expandRow }
/> />
<Body <Body
data={ data } data={ this.getData() }
keyField={ keyField } keyField={ keyField }
tabIndexCell={ tabIndexCell } tabIndexCell={ tabIndexCell }
columns={ columns } columns={ columns }

View File

@@ -23,6 +23,9 @@ class RowExpandProvider extends React.Component {
} }
handleRowExpand = (rowKey, expanded, rowIndex, e) => { handleRowExpand = (rowKey, expanded, rowIndex, e) => {
if (this.props.expandRow.nonExpandable.includes(rowKey)) {
return;
}
const { data, keyField, expandRow: { onExpand, onlyOneExpanding } } = this.props; const { data, keyField, expandRow: { onExpand, onlyOneExpanding } } = this.props;
let currExpanded = [...this.state.expanded]; let currExpanded = [...this.state.expanded];
@@ -73,6 +76,7 @@ class RowExpandProvider extends React.Component {
<RowExpandContext.Provider <RowExpandContext.Provider
value={ { value={ {
...this.props.expandRow, ...this.props.expandRow,
nonExpandable: this.props.expandRow.nonExpandable,
expanded: this.state.expanded, expanded: this.state.expanded,
isAnyExpands: dataOperator.isAnyExpands(data, keyField, this.state.expanded), isAnyExpands: dataOperator.isAnyExpands(data, keyField, this.state.expanded),
onRowExpand: this.handleRowExpand, onRowExpand: this.handleRowExpand,

View File

@@ -43,12 +43,13 @@ class SelectionProvider extends React.Component {
let currSelected = [...this.state.selected]; let currSelected = [...this.state.selected];
this.setState(() => {
let result = true; let result = true;
if (onSelect) { if (onSelect) {
const row = dataOperator.getRowByRowId(data, keyField, rowKey); const row = dataOperator.getRowByRowId(data, keyField, rowKey);
result = onSelect(row, checked, rowIndex, e); result = onSelect(row, checked, rowIndex, e);
} }
this.setState(() => {
if (result === true || result === undefined) { if (result === true || result === undefined) {
if (mode === ROW_SELECT_SINGLE) { // when select mode is radio if (mode === ROW_SELECT_SINGLE) { // when select mode is radio
currSelected = [rowKey]; currSelected = [rowKey];
@@ -81,7 +82,6 @@ class SelectionProvider extends React.Component {
currSelected = selected.filter(s => typeof data.find(d => d[keyField] === s) === 'undefined'); currSelected = selected.filter(s => typeof data.find(d => d[keyField] === s) === 'undefined');
} }
this.setState(() => {
let result; let result;
if (onSelectAll) { if (onSelectAll) {
result = onSelectAll( result = onSelectAll(
@@ -97,8 +97,7 @@ class SelectionProvider extends React.Component {
currSelected = result; currSelected = result;
} }
} }
return { selected: currSelected }; this.setState(() => ({ selected: currSelected }));
});
} }
render() { render() {

View File

@@ -18,8 +18,7 @@ const Header = (props) => {
sortOrder, sortOrder,
selectRow, selectRow,
onExternalFilter, onExternalFilter,
expandRow, expandRow
bootstrap4
} = props; } = props;
let SelectionHeaderCellComp = () => null; let SelectionHeaderCellComp = () => null;
@@ -50,7 +49,6 @@ const Header = (props) => {
return ( return (
<HeaderCell <HeaderCell
index={ i } index={ i }
bootstrap4={ bootstrap4 }
key={ column.dataField } key={ column.dataField }
column={ column } column={ column }
onSort={ onSort } onSort={ onSort }
@@ -78,8 +76,7 @@ Header.propTypes = {
selectRow: PropTypes.object, selectRow: PropTypes.object,
onExternalFilter: PropTypes.func, onExternalFilter: PropTypes.func,
className: PropTypes.string, className: PropTypes.string,
expandRow: PropTypes.object, expandRow: PropTypes.object
bootstrap4: PropTypes.bool
}; };
export default Header; export default Header;

View File

@@ -1,3 +1,4 @@
import _ from '../utils';
import ColumnResolver from './column-resolver'; import ColumnResolver from './column-resolver';
export default ExtendBase => export default ExtendBase =>
@@ -15,4 +16,13 @@ export default ExtendBase =>
isEmpty() { isEmpty() {
return this.props.data.length === 0; return this.props.data.length === 0;
} }
visibleRows() {
const { data, hiddenRows, keyField } = this.props;
if (!hiddenRows || hiddenRows.length === 0) return data;
return data.filter((row) => {
const key = _.get(row, keyField);
return !hiddenRows.includes(key);
});
}
}; };

View File

@@ -10,6 +10,7 @@ export default class ExpandCell extends Component {
static propTypes = { static propTypes = {
rowKey: PropTypes.any, rowKey: PropTypes.any,
expanded: PropTypes.bool.isRequired, expanded: PropTypes.bool.isRequired,
expandable: PropTypes.bool.isRequired,
onRowExpand: PropTypes.func.isRequired, onRowExpand: PropTypes.func.isRequired,
expandColumnRenderer: PropTypes.func, expandColumnRenderer: PropTypes.func,
rowIndex: PropTypes.number, rowIndex: PropTypes.number,
@@ -33,12 +34,12 @@ export default class ExpandCell extends Component {
handleClick(e) { handleClick(e) {
const { rowKey, expanded, onRowExpand, rowIndex } = this.props; const { rowKey, expanded, onRowExpand, rowIndex } = this.props;
e.stopPropagation();
onRowExpand(rowKey, !expanded, rowIndex, e); onRowExpand(rowKey, !expanded, rowIndex, e);
} }
render() { render() {
const { expanded, expandColumnRenderer, tabIndex } = this.props; const { expanded, expandable, expandColumnRenderer, tabIndex, rowKey } = this.props;
const attrs = {}; const attrs = {};
if (tabIndex !== -1) attrs.tabIndex = tabIndex; if (tabIndex !== -1) attrs.tabIndex = tabIndex;
@@ -46,8 +47,10 @@ export default class ExpandCell extends Component {
<td onClick={ this.handleClick } { ...attrs }> <td onClick={ this.handleClick } { ...attrs }>
{ {
expandColumnRenderer ? expandColumnRenderer({ expandColumnRenderer ? expandColumnRenderer({
expanded expandable,
}) : (expanded ? '(-)' : '(+)') expanded,
rowKey
}) : (expandable ? (expanded ? '(-)' : '(+)') : '')
} }
</td> </td>
); );

View File

@@ -31,6 +31,7 @@ export default class RowAggregator extends shouldUpdater(eventDelegater(React.Co
if ( if (
this.props.selected !== nextProps.selected || this.props.selected !== nextProps.selected ||
this.props.expanded !== nextProps.expanded || this.props.expanded !== nextProps.expanded ||
this.props.expandable !== nextProps.expandable ||
this.props.selectable !== nextProps.selectable || this.props.selectable !== nextProps.selectable ||
this.shouldUpdatedBySelfProps(nextProps) this.shouldUpdatedBySelfProps(nextProps)
) { ) {
@@ -54,6 +55,7 @@ export default class RowAggregator extends shouldUpdater(eventDelegater(React.Co
selectRow, selectRow,
expandRow, expandRow,
expanded, expanded,
expandable,
selected, selected,
selectable, selectable,
visibleColumnSize, visibleColumnSize,
@@ -84,6 +86,7 @@ export default class RowAggregator extends shouldUpdater(eventDelegater(React.Co
rowKey={ key } rowKey={ key }
rowIndex={ rowIndex } rowIndex={ rowIndex }
expanded={ expanded } expanded={ expanded }
expandable={ expandable }
tabIndex={ tabIndexCell ? tabIndexStart++ : -1 } tabIndex={ tabIndexCell ? tabIndexStart++ : -1 }
/> />
) : null ) : null

View File

@@ -25,6 +25,51 @@ describe('TableResolver', () => {
const BootstrapTableMock = extendTo(ExtendBase); const BootstrapTableMock = extendTo(ExtendBase);
let wrapper; let wrapper;
describe('visibleRows', () => {
describe('if hiddenRows prop is not existing', () => {
beforeEach(() => {
const mockElement = React.createElement(BootstrapTableMock, {
data, columns, keyField
}, null);
wrapper = shallow(mockElement);
});
it('should return correct data', () => {
expect(wrapper.instance().visibleRows()).toEqual(data);
});
});
describe('if hiddenRows prop is an empty array', () => {
beforeEach(() => {
const mockElement = React.createElement(BootstrapTableMock, {
data, columns, keyField, hiddenRows: []
}, null);
wrapper = shallow(mockElement);
});
it('should return correct data', () => {
expect(wrapper.instance().visibleRows()).toEqual(data);
});
});
describe('if hiddenRows prop is not an empty array', () => {
const hiddenRows = [1];
beforeEach(() => {
const mockElement = React.createElement(BootstrapTableMock, {
data, columns, keyField, hiddenRows
}, null);
wrapper = shallow(mockElement);
});
it('should return correct data', () => {
const result = wrapper.instance().visibleRows();
expect(result).toHaveLength(data.length - hiddenRows.length);
expect(result).toEqual(data.filter(d => !hiddenRows.includes(d.id)));
});
});
});
describe('validateProps', () => { describe('validateProps', () => {
describe('if keyField is defined and columns is all visible', () => { describe('if keyField is defined and columns is all visible', () => {
beforeEach(() => { beforeEach(() => {