mirror of
https://github.com/gosticks/react-bootstrap-table2.git
synced 2025-10-16 11:55:39 +00:00
2018/04/01 release
2018/04/01 release
This commit is contained in:
commit
1d87ce9ffc
@ -23,6 +23,7 @@
|
||||
* [rowClasses](#rowClasses)
|
||||
* [rowEvents](#rowEvents)
|
||||
* [defaultSorted](#defaultSorted)
|
||||
* [defaultSortDirection](#defaultSortDirection)
|
||||
* [pagination](#pagination)
|
||||
* [filter](#filter)
|
||||
* [onTableChange](#onTableChange)
|
||||
@ -168,6 +169,9 @@ const defaultSorted = [{
|
||||
}];
|
||||
```
|
||||
|
||||
### <a name='defaultSortDirection'>defaultSortDirection - [String]</a>
|
||||
Default sort direction when user click on header column at first time, available value is `asc` and `desc`. Default is `desc`.
|
||||
|
||||
### <a name='pagination'>pagination - [Object]</a>
|
||||
`pagination` allow user to render a pagination panel on the bottom of table. But pagination functionality is separated from core of `react-bootstrap-table2` so that you are suppose to install `react-bootstrap-table2-paginator` additionally.
|
||||
|
||||
|
||||
@ -32,6 +32,8 @@ Available properties in a column object:
|
||||
* [validator](#validator)
|
||||
* [editCellStyle](#editCellStyle)
|
||||
* [editCellClasses](#editCellClasses)
|
||||
* [editorStyle](#editorStyle)
|
||||
* [editorClasses](#editorClasses)
|
||||
* [filter](#filter)
|
||||
* [filterValue](#filterValue)
|
||||
|
||||
@ -552,6 +554,12 @@ Or take a callback function
|
||||
}
|
||||
```
|
||||
|
||||
## <a name='editorStyle'>column.editorStyle - [Object | Function]</a>
|
||||
This is almost same as [`column.editCellStyle`](#editCellStyle), but `column.editorStyle` is custom the style on editor instead of cell(`td`).
|
||||
|
||||
## <a name='editorClasses'>column.editorClasses - [Object | Function]</a>
|
||||
This is almost same as [`column.editCellClasses`](#editCellClasses), but `column.editorClasses` is custom the class on editor instead of cell(`td`).
|
||||
|
||||
## <a name='filter'>column.filter - [Object]</a>
|
||||
Configure `column.filter` will able to setup a column level filter on the header column. Currently, `react-bootstrap-table2` support following filters:
|
||||
|
||||
|
||||
@ -49,13 +49,15 @@ How user save their new editings? We offer two ways:
|
||||
* Cell Level (Configure [column.editable](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/column-props.html#columneditable-bool-function) as a callback function)
|
||||
|
||||
## Customize Style/Class
|
||||
Currently, we only support the editing cell style/class customization, in the future, we will offer more customizations.
|
||||
|
||||
### Editing Cell
|
||||
|
||||
* Customize the editing cell style via [column.editCellStyle](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/column-props.html#columneditcellstyle-object-function)
|
||||
* Customize the editing cell classname via [column.editCellClasses](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/column-props.html#columneditcellclasses-string-function)
|
||||
|
||||
### Editor
|
||||
* Customize the editor style via [column.editorStyle](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/column-props.html#columneditorstyle-object-function)
|
||||
* Customize the editor classname via [column.editoClasses](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/column-props.html#columneditorclasses-string-function)
|
||||
|
||||
## Validation
|
||||
|
||||
[`column.validator`](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/column-props.html#columnvalidator-function) will help you to work on it!
|
||||
@ -14,7 +14,9 @@ export default _ =>
|
||||
class EditingCell extends Component {
|
||||
static propTypes = {
|
||||
row: PropTypes.object.isRequired,
|
||||
rowIndex: PropTypes.number.isRequired,
|
||||
column: PropTypes.object.isRequired,
|
||||
columnIndex: PropTypes.number.isRequired,
|
||||
onUpdate: PropTypes.func.isRequired,
|
||||
onEscape: PropTypes.func.isRequired,
|
||||
timeToCloseMessage: PropTypes.number,
|
||||
@ -123,7 +125,7 @@ export default _ =>
|
||||
|
||||
render() {
|
||||
const { invalidMessage } = this.state;
|
||||
const { row, column, className, style } = this.props;
|
||||
const { row, column, className, style, rowIndex, columnIndex } = this.props;
|
||||
const { dataField } = column;
|
||||
|
||||
const value = _.get(row, dataField);
|
||||
@ -133,7 +135,21 @@ export default _ =>
|
||||
};
|
||||
|
||||
const hasError = _.isDefined(invalidMessage);
|
||||
const editorClass = hasError ? cs('animated', 'shake') : null;
|
||||
let customEditorClass = column.editorClasses || '';
|
||||
if (_.isFunction(column.editorClasses)) {
|
||||
customEditorClass = column.editorClasses(value, row, rowIndex, columnIndex);
|
||||
}
|
||||
|
||||
let editorStyle = column.editorStyle || {};
|
||||
if (_.isFunction(column.editorStyle)) {
|
||||
editorStyle = column.editorStyle(value, row, rowIndex, columnIndex);
|
||||
}
|
||||
|
||||
const editorClass = cs({
|
||||
animated: hasError,
|
||||
shake: hasError
|
||||
}, customEditorClass);
|
||||
|
||||
return (
|
||||
<td
|
||||
className={ cs('react-bootstrap-table-editing-cell', className) }
|
||||
@ -143,6 +159,7 @@ export default _ =>
|
||||
<TextEditor
|
||||
ref={ node => this.editor = node }
|
||||
defaultValue={ value }
|
||||
style={ editorStyle }
|
||||
className={ editorClass }
|
||||
{ ...editorAttrs }
|
||||
/>
|
||||
|
||||
@ -28,6 +28,9 @@ describe('EditingCell', () => {
|
||||
name: 'A'
|
||||
};
|
||||
|
||||
const rowIndex = 1;
|
||||
const columnIndex = 1;
|
||||
|
||||
let column = {
|
||||
dataField: 'id',
|
||||
text: 'ID'
|
||||
@ -39,6 +42,8 @@ describe('EditingCell', () => {
|
||||
wrapper = shallow(
|
||||
<EditingCell
|
||||
row={ row }
|
||||
rowIndex={ rowIndex }
|
||||
columnIndex={ columnIndex }
|
||||
column={ column }
|
||||
onUpdate={ onUpdate }
|
||||
onEscape={ onEscape }
|
||||
@ -58,7 +63,7 @@ describe('EditingCell', () => {
|
||||
expect(textEditor.props().defaultValue).toEqual(row[column.dataField]);
|
||||
expect(textEditor.props().onKeyDown).toBeDefined();
|
||||
expect(textEditor.props().onBlur).toBeDefined();
|
||||
expect(textEditor.props().className).toBeNull();
|
||||
expect(textEditor.props().className).toEqual('');
|
||||
});
|
||||
|
||||
it('should not render EditorIndicator due to state.invalidMessage is null', () => {
|
||||
@ -92,6 +97,8 @@ describe('EditingCell', () => {
|
||||
wrapper = shallow(
|
||||
<EditingCell
|
||||
row={ row }
|
||||
rowIndex={ rowIndex }
|
||||
columnIndex={ columnIndex }
|
||||
column={ column }
|
||||
onUpdate={ onUpdate }
|
||||
onEscape={ onEscape }
|
||||
@ -112,6 +119,8 @@ describe('EditingCell', () => {
|
||||
wrapper = shallow(
|
||||
<EditingCell
|
||||
row={ row }
|
||||
rowIndex={ rowIndex }
|
||||
columnIndex={ columnIndex }
|
||||
column={ column }
|
||||
onUpdate={ onUpdate }
|
||||
onEscape={ onEscape }
|
||||
@ -126,12 +135,140 @@ describe('EditingCell', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('if column.editorClasses is defined', () => {
|
||||
let columnWithEditorClasses;
|
||||
const classes = 'test test1';
|
||||
|
||||
describe('and it is a function', () => {
|
||||
beforeEach(() => {
|
||||
columnWithEditorClasses = {
|
||||
...column,
|
||||
editorClasses: jest.fn(() => classes)
|
||||
};
|
||||
wrapper = shallow(
|
||||
<EditingCell
|
||||
row={ row }
|
||||
rowIndex={ rowIndex }
|
||||
columnIndex={ columnIndex }
|
||||
column={ columnWithEditorClasses }
|
||||
onUpdate={ onUpdate }
|
||||
onEscape={ onEscape }
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
it('should render TextEditor with correct props', () => {
|
||||
const textEditor = wrapper.find(TextEditor);
|
||||
expect(textEditor.props().className).toEqual(classes);
|
||||
});
|
||||
|
||||
it('should call column.editorClasses correctly', () => {
|
||||
expect(columnWithEditorClasses.editorClasses).toHaveBeenCalledTimes(1);
|
||||
expect(columnWithEditorClasses.editorClasses).toHaveBeenCalledWith(
|
||||
_.get(row, column.dataField),
|
||||
row,
|
||||
rowIndex,
|
||||
columnIndex
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('and it is a string', () => {
|
||||
beforeEach(() => {
|
||||
columnWithEditorClasses = {
|
||||
...column,
|
||||
editorClasses: classes
|
||||
};
|
||||
wrapper = shallow(
|
||||
<EditingCell
|
||||
row={ row }
|
||||
rowIndex={ rowIndex }
|
||||
columnIndex={ columnIndex }
|
||||
column={ columnWithEditorClasses }
|
||||
onUpdate={ onUpdate }
|
||||
onEscape={ onEscape }
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
it('should render TextEditor with correct props', () => {
|
||||
const textEditor = wrapper.find(TextEditor);
|
||||
expect(textEditor.props().className).toEqual(classes);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('if column.editorStyle is defined', () => {
|
||||
let columnWithEditorStyle;
|
||||
const style = { color: 'red' };
|
||||
|
||||
describe('and it is a function', () => {
|
||||
beforeEach(() => {
|
||||
columnWithEditorStyle = {
|
||||
...column,
|
||||
editorStyle: jest.fn(() => style)
|
||||
};
|
||||
wrapper = shallow(
|
||||
<EditingCell
|
||||
row={ row }
|
||||
rowIndex={ rowIndex }
|
||||
columnIndex={ columnIndex }
|
||||
column={ columnWithEditorStyle }
|
||||
onUpdate={ onUpdate }
|
||||
onEscape={ onEscape }
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
it('should render TextEditor with correct props', () => {
|
||||
const textEditor = wrapper.find(TextEditor);
|
||||
expect(textEditor.props().style).toEqual(style);
|
||||
});
|
||||
|
||||
it('should call column.editorStyle correctly', () => {
|
||||
expect(columnWithEditorStyle.editorStyle).toHaveBeenCalledTimes(1);
|
||||
expect(columnWithEditorStyle.editorStyle).toHaveBeenCalledWith(
|
||||
_.get(row, column.dataField),
|
||||
row,
|
||||
rowIndex,
|
||||
columnIndex
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('and it is an object', () => {
|
||||
beforeEach(() => {
|
||||
columnWithEditorStyle = {
|
||||
...column,
|
||||
editorStyle: style
|
||||
};
|
||||
wrapper = shallow(
|
||||
<EditingCell
|
||||
row={ row }
|
||||
rowIndex={ rowIndex }
|
||||
columnIndex={ columnIndex }
|
||||
column={ columnWithEditorStyle }
|
||||
onUpdate={ onUpdate }
|
||||
onEscape={ onEscape }
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
it('should render TextEditor with correct props', () => {
|
||||
const textEditor = wrapper.find(TextEditor);
|
||||
expect(textEditor.props().style).toEqual(style);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('if blurToSave prop is true', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = mount(
|
||||
<TableRowWrapper>
|
||||
<EditingCell
|
||||
row={ row }
|
||||
rowIndex={ rowIndex }
|
||||
columnIndex={ columnIndex }
|
||||
column={ column }
|
||||
onUpdate={ onUpdate }
|
||||
onEscape={ onEscape }
|
||||
@ -167,6 +304,8 @@ describe('EditingCell', () => {
|
||||
wrapper = mount(
|
||||
<EditingCell
|
||||
row={ row }
|
||||
rowIndex={ rowIndex }
|
||||
columnIndex={ columnIndex }
|
||||
column={ column }
|
||||
onUpdate={ onUpdate }
|
||||
onEscape={ onEscape }
|
||||
|
||||
61
packages/react-bootstrap-table2-example/examples/cell-edit/editor-class-table.js
vendored
Normal file
61
packages/react-bootstrap-table2-example/examples/cell-edit/editor-class-table.js
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
/* eslint no-unused-vars: 0 */
|
||||
import React from 'react';
|
||||
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
import cellEditFactory from 'react-bootstrap-table2-editor';
|
||||
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',
|
||||
editorClasses: 'editing-name'
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price',
|
||||
editorClasses: (cell, row, rowIndex, colIndex) =>
|
||||
(cell > 2101 ? 'editing-price-bigger-than-2101' : 'editing-price-small-than-2101')
|
||||
}];
|
||||
|
||||
const sourceCode = `\
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
import cellEditFactory from 'react-bootstrap-table2-editor';
|
||||
|
||||
const columns = [{
|
||||
dataField: 'id',
|
||||
text: 'Product ID'
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name',
|
||||
editorClasses: 'editing-name'
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price',
|
||||
editorClasses: (cell, row, rowIndex, colIndex) =>
|
||||
(cell > 2101 ? 'editing-price-bigger-than-2101' : 'editing-price-small-than-2101')
|
||||
}];
|
||||
|
||||
<BootstrapTable
|
||||
keyField="id"
|
||||
data={ products }
|
||||
columns={ columns }
|
||||
cellEdit={ cellEditFactory({ mode: 'click' }) }
|
||||
/>
|
||||
`;
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<BootstrapTable
|
||||
keyField="id"
|
||||
data={ products }
|
||||
columns={ columns }
|
||||
cellEdit={ cellEditFactory({ mode: 'click' }) }
|
||||
/>
|
||||
<Code>{ sourceCode }</Code>
|
||||
</div>
|
||||
);
|
||||
69
packages/react-bootstrap-table2-example/examples/cell-edit/editor-style-table.js
vendored
Normal file
69
packages/react-bootstrap-table2-example/examples/cell-edit/editor-style-table.js
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
/* eslint no-unused-vars: 0 */
|
||||
import React from 'react';
|
||||
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
import cellEditFactory from 'react-bootstrap-table2-editor';
|
||||
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',
|
||||
editorStyle: {
|
||||
backgroundColor: '#20B2AA'
|
||||
}
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price',
|
||||
editorStyle: (cell, row, rowIndex, colIndex) => {
|
||||
const backgroundColor = cell > 2101 ? '#00BFFF' : '#00FFFF';
|
||||
return { backgroundColor };
|
||||
}
|
||||
}];
|
||||
|
||||
const sourceCode = `\
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
import cellEditFactory from 'react-bootstrap-table2-editor';
|
||||
|
||||
const columns = [{
|
||||
dataField: 'id',
|
||||
text: 'Product ID'
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name',
|
||||
editorStyle: {
|
||||
backgroundColor: '#20B2AA'
|
||||
}
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price',
|
||||
editorStyle: (cell, row, rowIndex, colIndex) => {
|
||||
const backgroundColor = cell > 2101 ? '#00BFFF' : '#00FFFF';
|
||||
return { backgroundColor };
|
||||
}
|
||||
}];
|
||||
|
||||
<BootstrapTable
|
||||
keyField="id"
|
||||
data={ products }
|
||||
columns={ columns }
|
||||
cellEdit={ cellEditFactory({ mode: 'click' }) }
|
||||
/>
|
||||
`;
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<BootstrapTable
|
||||
keyField="id"
|
||||
data={ products }
|
||||
columns={ columns }
|
||||
cellEdit={ cellEditFactory({ mode: 'click' }) }
|
||||
/>
|
||||
<Code>{ sourceCode }</Code>
|
||||
</div>
|
||||
);
|
||||
62
packages/react-bootstrap-table2-example/examples/row-selection/selection-no-data.js
vendored
Normal file
62
packages/react-bootstrap-table2-example/examples/row-selection/selection-no-data.js
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
/* eslint no-unused-vars: 0 */
|
||||
import React from 'react';
|
||||
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
import Code from 'components/common/code-block';
|
||||
|
||||
const columns = [{
|
||||
dataField: 'id',
|
||||
text: 'Product ID'
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name'
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price'
|
||||
}];
|
||||
|
||||
const selectRow1 = {
|
||||
mode: 'checkbox',
|
||||
clickToSelect: true
|
||||
};
|
||||
|
||||
const sourceCode1 = `\
|
||||
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 selectRow = {
|
||||
mode: 'checkbox',
|
||||
clickToSelect: true
|
||||
};
|
||||
|
||||
<BootstrapTable
|
||||
keyField='id'
|
||||
data={ [] }
|
||||
columns={ columns }
|
||||
selectRow={ selectRow }
|
||||
noDataIndication={ 'no results found' }
|
||||
/>
|
||||
`;
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<BootstrapTable
|
||||
keyField="id"
|
||||
data={ [] }
|
||||
columns={ columns }
|
||||
selectRow={ selectRow1 }
|
||||
noDataIndication={ 'no results found' }
|
||||
/>
|
||||
<Code>{ sourceCode1 }</Code>
|
||||
</div>
|
||||
);
|
||||
67
packages/react-bootstrap-table2-example/examples/sort/default-sort-direction.js
vendored
Normal file
67
packages/react-bootstrap-table2-example/examples/sort/default-sort-direction.js
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
/* eslint react/prefer-stateless-function: 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',
|
||||
sort: true
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name',
|
||||
sort: true
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price',
|
||||
sort: true
|
||||
}];
|
||||
|
||||
|
||||
const sourceCode = `\
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
|
||||
const columns = [{
|
||||
dataField: 'id',
|
||||
text: 'Product ID',
|
||||
sort: true
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name',
|
||||
sort: true
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price',
|
||||
sort: true
|
||||
}];
|
||||
|
||||
const defaultSorted = [{
|
||||
dataField: 'name',
|
||||
order: 'desc'
|
||||
}];
|
||||
|
||||
<BootstrapTable
|
||||
keyField="id"
|
||||
data={ products }
|
||||
columns={ columns }
|
||||
defaultSortDirection="asc"
|
||||
/>
|
||||
`;
|
||||
|
||||
|
||||
class DefaultSortDirectionTable extends React.PureComponent {
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<BootstrapTable keyField="id" data={ products } columns={ columns } defaultSortDirection="asc" />
|
||||
<Code>{ sourceCode }</Code>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default DefaultSortDirectionTable;
|
||||
@ -57,6 +57,7 @@ import RowEventTable from 'examples/rows/row-event';
|
||||
// table sort
|
||||
import EnableSortTable from 'examples/sort/enable-sort-table';
|
||||
import DefaultSortTable from 'examples/sort/default-sort-table';
|
||||
import DefaultSortDirectionTable from 'examples/sort/default-sort-direction';
|
||||
import SortEvents from 'examples/sort/sort-events';
|
||||
import CustomSortTable from 'examples/sort/custom-sort-table';
|
||||
import HeaderSortingClassesTable from 'examples/sort/header-sorting-classes';
|
||||
@ -73,6 +74,8 @@ import CellEditHooks from 'examples/cell-edit/cell-edit-hooks-table';
|
||||
import CellEditValidator from 'examples/cell-edit/cell-edit-validator-table';
|
||||
import CellEditStyleTable from 'examples/cell-edit/cell-edit-style-table';
|
||||
import CellEditClassTable from 'examples/cell-edit/cell-edit-class-table';
|
||||
import EditorStyleTable from 'examples/cell-edit/editor-style-table';
|
||||
import EditorClassTable from 'examples/cell-edit/editor-class-table';
|
||||
|
||||
// work on row selection
|
||||
import SingleSelectionTable from 'examples/row-selection/single-selection';
|
||||
@ -81,6 +84,7 @@ import ClickToSelectTable from 'examples/row-selection/click-to-select';
|
||||
import DefaultSelectTable from 'examples/row-selection/default-select';
|
||||
import SelectionManagement from 'examples/row-selection/selection-management';
|
||||
import ClickToSelectWithCellEditTable from 'examples/row-selection/click-to-select-with-cell-edit';
|
||||
import SelectionNoDataTable from 'examples/row-selection/selection-no-data';
|
||||
import SelectionStyleTable from 'examples/row-selection/selection-style';
|
||||
import SelectionClassTable from 'examples/row-selection/selection-class';
|
||||
import NonSelectableRowsTable from 'examples/row-selection/non-selectable-rows';
|
||||
@ -172,6 +176,7 @@ storiesOf('Work on Rows', module)
|
||||
storiesOf('Sort Table', module)
|
||||
.add('Enable Sort', () => <EnableSortTable />)
|
||||
.add('Default Sort Table', () => <DefaultSortTable />)
|
||||
.add('Default Sort Direction Table', () => <DefaultSortDirectionTable />)
|
||||
.add('Sort Events', () => <SortEvents />)
|
||||
.add('Custom Sort Fuction', () => <CustomSortTable />)
|
||||
.add('Custom Classes on Sorting Header Column', () => <HeaderSortingClassesTable />)
|
||||
@ -186,8 +191,10 @@ storiesOf('Cell Editing', module)
|
||||
.add('Cell Level Editable', () => <CellLevelEditable />)
|
||||
.add('Rich Hook Functions', () => <CellEditHooks />)
|
||||
.add('Validation', () => <CellEditValidator />)
|
||||
.add('Custom Cell Style When Editing', () => <CellEditStyleTable />)
|
||||
.add('Custom Cell Classes When Editing', () => <CellEditClassTable />);
|
||||
.add('Custom Cell Style', () => <CellEditStyleTable />)
|
||||
.add('Custom Cell Classes', () => <CellEditClassTable />)
|
||||
.add('Custom Editor Classes', () => <EditorClassTable />)
|
||||
.add('Custom Editor Style', () => <EditorStyleTable />);
|
||||
|
||||
storiesOf('Row Selection', module)
|
||||
.add('Single Selection', () => <SingleSelectionTable />)
|
||||
@ -196,6 +203,7 @@ storiesOf('Row Selection', module)
|
||||
.add('Default Select', () => <DefaultSelectTable />)
|
||||
.add('Selection Management', () => <SelectionManagement />)
|
||||
.add('Click to Select and Edit Cell', () => <ClickToSelectWithCellEditTable />)
|
||||
.add('Selection without Data', () => <SelectionNoDataTable />)
|
||||
.add('Selection Style', () => <SelectionStyleTable />)
|
||||
.add('Selection Class', () => <SelectionClassTable />)
|
||||
.add('Selection Background Color', () => <SelectionBgColorTable />)
|
||||
|
||||
@ -21,7 +21,7 @@ export const filterByText = _ => (
|
||||
if (caseSensitive) {
|
||||
return cellStr.includes(filterVal);
|
||||
}
|
||||
return cellStr.toLocaleUpperCase().includes(filterVal.toLocaleUpperCase());
|
||||
return cellStr.toLocaleUpperCase().indexOf(filterVal.toLocaleUpperCase()) !== -1;
|
||||
});
|
||||
|
||||
export const filterByNumber = _ => (
|
||||
@ -106,7 +106,13 @@ export const filters = (store, columns, _) => (currFilters) => {
|
||||
Object.keys(currFilters).forEach((dataField) => {
|
||||
const filterObj = currFilters[dataField];
|
||||
filterFn = factory(filterObj.filterType);
|
||||
const { filterValue } = columns.find(col => col.dataField === dataField);
|
||||
let filterValue;
|
||||
for (let i = 0; i < columns.length; i += 1) {
|
||||
if (columns[i].dataField === dataField) {
|
||||
filterValue = columns[i].filterValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
result = filterFn(result, dataField, filterObj, filterValue);
|
||||
});
|
||||
return result;
|
||||
|
||||
3
packages/react-bootstrap-table2/src/body.js
vendored
3
packages/react-bootstrap-table2/src/body.js
vendored
@ -35,6 +35,9 @@ const Body = (props) => {
|
||||
|
||||
if (isEmpty) {
|
||||
const indication = _.isFunction(noDataIndication) ? noDataIndication() : noDataIndication;
|
||||
if (!indication) {
|
||||
return null;
|
||||
}
|
||||
content = <RowSection content={ indication } colSpan={ visibleColumnSize } />;
|
||||
} else {
|
||||
const nonEditableRows = cellEdit.nonEditableRows || [];
|
||||
|
||||
@ -149,6 +149,7 @@ BootstrapTable.propTypes = {
|
||||
dataField: PropTypes.string.isRequired,
|
||||
order: PropTypes.oneOf([Const.SORT_DESC, Const.SORT_ASC]).isRequired
|
||||
})),
|
||||
defaultSortDirection: PropTypes.oneOf([Const.SORT_DESC, Const.SORT_ASC]),
|
||||
overlay: PropTypes.func,
|
||||
onTableChange: PropTypes.func,
|
||||
onSort: PropTypes.func,
|
||||
|
||||
@ -130,6 +130,8 @@ HeaderCell.propTypes = {
|
||||
editable: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
|
||||
editCellStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),
|
||||
editCellClasses: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
|
||||
editorStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),
|
||||
editorClasses: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
|
||||
validator: PropTypes.func,
|
||||
filter: PropTypes.object,
|
||||
filterValue: PropTypes.func
|
||||
|
||||
@ -1,6 +1,11 @@
|
||||
export default ExtendBase =>
|
||||
class ColumnResolver extends ExtendBase {
|
||||
visibleColumnSize() {
|
||||
return this.props.columns.filter(c => !c.hidden).length;
|
||||
visibleColumnSize(includeSelectColumn = true) {
|
||||
const columnLen = this.props.columns.filter(c => !c.hidden).length;
|
||||
if (!includeSelectColumn) return columnLen;
|
||||
if (this.props.selectRow && !this.props.selectRow.hideSelectColumn) {
|
||||
return columnLen + 1;
|
||||
}
|
||||
return columnLen;
|
||||
}
|
||||
};
|
||||
|
||||
@ -5,12 +5,12 @@ import _ from '../utils';
|
||||
export default ExtendBase =>
|
||||
class TableResolver extends ColumnResolver(ExtendBase) {
|
||||
validateProps() {
|
||||
const { columns, keyField } = this.props;
|
||||
const { keyField } = this.props;
|
||||
if (!keyField) {
|
||||
throw new Error('Please specify a field as key via keyField');
|
||||
}
|
||||
if (this.visibleColumnSize(columns) <= 0) {
|
||||
throw new Error('No any visible columns detect');
|
||||
if (this.visibleColumnSize(false) <= 0) {
|
||||
throw new Error('No visible columns detected');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
2
packages/react-bootstrap-table2/src/row.js
vendored
2
packages/react-bootstrap-table2/src/row.js
vendored
@ -79,7 +79,9 @@ class Row extends eventDelegater(Component) {
|
||||
<EditingCell
|
||||
key={ `${content}-${index}` }
|
||||
row={ row }
|
||||
rowIndex={ rowIndex }
|
||||
column={ column }
|
||||
columnIndex={ index }
|
||||
className={ editCellclasses }
|
||||
style={ editCellstyle }
|
||||
{ ...rest }
|
||||
|
||||
@ -15,7 +15,7 @@ export default Base =>
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
const { columns, defaultSorted, store } = this.props;
|
||||
const { columns, defaultSorted, defaultSortDirection, store } = this.props;
|
||||
// defaultSorted is an array, it's ready to use as multi / single sort
|
||||
// when we start to support multi sort, please update following code to use array.forEach
|
||||
if (defaultSorted && defaultSorted.length > 0) {
|
||||
@ -23,7 +23,7 @@ export default Base =>
|
||||
const order = defaultSorted[0].order;
|
||||
const column = columns.filter(col => col.dataField === dataField);
|
||||
if (column.length > 0) {
|
||||
store.setSort(column[0], order);
|
||||
store.setSort(column[0], order, defaultSortDirection);
|
||||
|
||||
if (column[0].onSort) {
|
||||
column[0].onSort(store.sortField, store.sortOrder);
|
||||
@ -39,8 +39,13 @@ export default Base =>
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const sortedColumn = nextProps.columns.find(
|
||||
column => column.dataField === nextProps.store.sortField);
|
||||
let sortedColumn;
|
||||
for (let i = 0; i < nextProps.columns.length; i += 1) {
|
||||
if (nextProps.columns[i].dataField === nextProps.store.sortField) {
|
||||
sortedColumn = nextProps.columns[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sortedColumn && sortedColumn.sort) {
|
||||
nextProps.store.sortBy(sortedColumn);
|
||||
}
|
||||
@ -48,7 +53,7 @@ export default Base =>
|
||||
|
||||
handleSort(column) {
|
||||
const { store } = this.props;
|
||||
store.setSort(column);
|
||||
store.setSort(column, undefined, this.props.defaultSortDirection);
|
||||
|
||||
if (column.onSort) {
|
||||
column.onSort(store.sortField, store.sortOrder);
|
||||
|
||||
@ -21,8 +21,8 @@ export default class Store {
|
||||
if (row) _.set(row, dataField, newValue);
|
||||
}
|
||||
|
||||
setSort({ dataField }, order) {
|
||||
this.sortOrder = nextOrder(this)(dataField, order);
|
||||
setSort({ dataField }, order, defaultOrder) {
|
||||
this.sortOrder = nextOrder(this)(dataField, order, defaultOrder);
|
||||
this.sortField = dataField;
|
||||
}
|
||||
|
||||
|
||||
@ -37,11 +37,11 @@ export const sort = ({ data, sortOrder, sortField }) => (sortFunc) => {
|
||||
return _data;
|
||||
};
|
||||
|
||||
export const nextOrder = store => (field, order) => {
|
||||
export const nextOrder = store => (field, order, defaultOrder = Const.SORT_DESC) => {
|
||||
if (order) return order;
|
||||
|
||||
if (field !== store.sortField) {
|
||||
return Const.SORT_DESC;
|
||||
return defaultOrder;
|
||||
}
|
||||
return store.sortOrder === Const.SORT_DESC ? Const.SORT_ASC : Const.SORT_DESC;
|
||||
};
|
||||
|
||||
@ -53,12 +53,10 @@ describe('Body', () => {
|
||||
/>);
|
||||
});
|
||||
|
||||
it('should render successfully', () => {
|
||||
it('should not render', () => {
|
||||
expect(wrapper.length).toBe(1);
|
||||
expect(wrapper.find('tbody').length).toBe(1);
|
||||
expect(wrapper.find(RowSection).length).toBe(1);
|
||||
expect(wrapper.find(RowSection).prop('colSpan')).toBe(columns.length);
|
||||
expect(wrapper.find(RowSection).prop('content')).toBe(null);
|
||||
expect(wrapper.find('tbody').length).toBe(0);
|
||||
expect(wrapper.find(RowSection).length).toBe(0);
|
||||
});
|
||||
|
||||
describe('when noDataIndication props is defined', () => {
|
||||
|
||||
@ -56,7 +56,7 @@ describe('TableResolver', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('if columns is all unvisible', () => {
|
||||
describe('if no columns are visible', () => {
|
||||
beforeEach(() => {
|
||||
const mockElement = React.createElement(BootstrapTableMock, {
|
||||
data, keyField, columns: []
|
||||
@ -67,7 +67,7 @@ describe('TableResolver', () => {
|
||||
it('should throw error', () => {
|
||||
expect(() =>
|
||||
wrapper.instance().validateProps()
|
||||
).toThrow(new Error('No any visible columns detect'));
|
||||
).toThrow(new Error('No visible columns detected'));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -56,10 +56,15 @@ describe('Store Base', () => {
|
||||
expect(store.sortOrder).toEqual(Const.SORT_DESC);
|
||||
});
|
||||
|
||||
it('should force assign sortOrder correctly if second argument is passed', () => {
|
||||
it('should force assign sortOrder correctly if second argument is given', () => {
|
||||
store.setSort({ dataField }, Const.SORT_DESC);
|
||||
expect(store.sortOrder).toEqual(Const.SORT_DESC);
|
||||
});
|
||||
|
||||
it('should force assign sortOrder correctly if third argument is given', () => {
|
||||
store.setSort({ dataField }, undefined, Const.SORT_ASC);
|
||||
expect(store.sortOrder).toEqual(Const.SORT_ASC);
|
||||
});
|
||||
});
|
||||
|
||||
describe('sortBy', () => {
|
||||
|
||||
@ -63,6 +63,10 @@ describe('Sort Function', () => {
|
||||
expect(nextOrder(store)('name')).toBe(Const.SORT_DESC);
|
||||
});
|
||||
|
||||
it('should return correcly order when store.sortField is not eq next sort field and default sort direction is given', () => {
|
||||
expect(nextOrder(store)('name', undefined, Const.SORT_ASC)).toBe(Const.SORT_ASC);
|
||||
});
|
||||
|
||||
it('should return correcly order when store.sortField is eq next sort field', () => {
|
||||
store.sortField = 'name';
|
||||
store.sortOrder = Const.SORT_DESC;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user