diff --git a/docs/row-selection.md b/docs/row-selection.md
index 9a09361..c8b97e3 100644
--- a/docs/row-selection.md
+++ b/docs/row-selection.md
@@ -211,18 +211,44 @@ const selectRow = {
};
```
+> If you want to reject current select action, just return `false`:
+
+```js
+const selectRow = {
+ mode: 'checkbox',
+ onSelect: (row, isSelect, rowIndex, e) => {
+ if (SOME_CONDITION) {
+ return false;
+ }
+ }
+};
+```
+
### selectRow.onSelectAll - [Function]
This callback function will be called when select/unselect all and it only work when you configure [`selectRow.mode`](#mode) as `checkbox`.
```js
const selectRow = {
mode: 'checkbox',
- onSelectAll: (isSelect, results, e) => {
+ onSelectAll: (isSelect, rows, e) => {
// ...
}
};
```
+> If you want to control the final selection result, just return a row key array:
+
+```js
+const selectRow = {
+ mode: 'checkbox',
+ onSelectAll: (isSelect, rows, e) => {
+ if (isSelect && SOME_CONDITION) {
+ return [1, 3, 4]; // finally, key 1, 3, 4 will being selected
+ }
+ }
+};
+```
+
### selectRow.hideSelectColumn - [Bool]
Default is `false`, if you don't want to have a selection column, give this prop as `true`
diff --git a/packages/react-bootstrap-table2-example/examples/column-filter/select-filter-preserve-option-order.js b/packages/react-bootstrap-table2-example/examples/column-filter/select-filter-preserve-option-order.js
new file mode 100644
index 0000000..f7a0fca
--- /dev/null
+++ b/packages/react-bootstrap-table2-example/examples/column-filter/select-filter-preserve-option-order.js
@@ -0,0 +1,70 @@
+/* eslint max-len: 0 */
+import React from 'react';
+import BootstrapTable from 'react-bootstrap-table-next';
+import filterFactory, { selectFilter } from 'react-bootstrap-table2-filter';
+import Code from 'components/common/code-block';
+import { productsQualityGenerator } from 'utils/common';
+
+const products = productsQualityGenerator(6);
+
+const selectOptions = [
+ { label: 0, value: 'good' },
+ { label: 1, value: 'Bad' },
+ { label: 2, value: 'unknown' }
+];
+
+const columns = [{
+ dataField: 'id',
+ text: 'Product ID'
+}, {
+ dataField: 'name',
+ text: 'Product Name'
+}, {
+ dataField: 'quality',
+ text: 'Product Quailty',
+ formatter: cell => selectOptions.find(opt => opt.label === cell).value,
+ filter: selectFilter({
+ options: selectOptions
+ })
+}];
+
+const sourceCode = `\
+import BootstrapTable from 'react-bootstrap-table-next';
+import filterFactory, { selectFilter } from 'react-bootstrap-table2-filter';
+
+const selectOptions = [
+ { label: 0, value: 'good' },
+ { label: 1, value: 'Bad' },
+ { label: 2, value: 'unknown' }
+];
+
+const columns = [{
+ dataField: 'id',
+ text: 'Product ID'
+}, {
+ dataField: 'name',
+ text: 'Product Name'
+}, {
+ dataField: 'quality',
+ text: 'Product Quailty',
+ formatter: cell => selectOptions.find(opt => opt.label === cell).value,
+ filter: selectFilter({
+ options: selectOptions
+ })
+}];
+
+
+`;
+
+export default () => (
+
+
selectFilter.options accept an Array and we keep that order when rendering the options
+
+ { sourceCode }
+
+);
diff --git a/packages/react-bootstrap-table2-example/examples/row-selection/selection-advance-management.js b/packages/react-bootstrap-table2-example/examples/row-selection/selection-advance-management.js
new file mode 100644
index 0000000..22af899
--- /dev/null
+++ b/packages/react-bootstrap-table2-example/examples/row-selection/selection-advance-management.js
@@ -0,0 +1,88 @@
+/* eslint no-alert: 0 */
+/* eslint consistent-return: 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 sourceCode = `\
+import BootstrapTable from 'react-bootstrap-table-next';
+
+class AdvSelectionManagment extends React.Component {
+ handleOnSelect = (row, isSelect) => {
+ if (isSelect && row.id < 3) {
+ alert('Oops, You can not select Product ID which less than 3');
+ return false; // return false to deny current select action
+ }
+ return true; // return true or dont return to approve current select action
+ }
+
+ handleOnSelectAll = (isSelect, rows) => {
+ if (isSelect) {
+ return rows.filter(r => r.id >= 3).map(r => r.id);
+ }
+ }
+
+ render() {
+ const selectRow = {
+ mode: 'checkbox',
+ clickToSelect: true,
+ onSelect: this.handleOnSelect,
+ onSelectAll: this.handleOnSelectAll
+ };
+ return (
+
+
You can not select Product ID less than 3
+
+ { sourceCode }
+
+ );
+ }
+}
+`;
+
+export default class AdvSelectionManagment extends React.Component {
+ handleOnSelect = (row, isSelect) => {
+ if (isSelect && row.id < 3) {
+ alert('Oops, You can not select Product ID which less than 3');
+ return false; // return false to deny current select action
+ }
+ return true; // return true or dont return to approve current select action
+ }
+
+ handleOnSelectAll = (isSelect, rows) => {
+ if (isSelect) {
+ return rows.filter(r => r.id >= 3).map(r => r.id);
+ }
+ }
+
+ render() {
+ const selectRow = {
+ mode: 'checkbox',
+ clickToSelect: true,
+ onSelect: this.handleOnSelect,
+ onSelectAll: this.handleOnSelectAll
+ };
+ return (
+
+
You can not select Product ID less than 3
+
+ { sourceCode }
+
+ );
+ }
+}
diff --git a/packages/react-bootstrap-table2-example/stories/index.js b/packages/react-bootstrap-table2-example/stories/index.js
index 7ba6b1b..2757280 100644
--- a/packages/react-bootstrap-table2-example/stories/index.js
+++ b/packages/react-bootstrap-table2-example/stories/index.js
@@ -55,6 +55,7 @@ import CustomFilterValue from 'examples/column-filter/custom-filter-value';
import SelectFilter from 'examples/column-filter/select-filter';
import SelectFilterWithDefaultValue from 'examples/column-filter/select-filter-default-value';
import SelectFilterComparator from 'examples/column-filter/select-filter-like-comparator';
+import SelectFilterWithPreservedOptionsOrder from 'examples/column-filter/select-filter-preserve-option-order';
import CustomSelectFilter from 'examples/column-filter/custom-select-filter';
import MultiSelectFilter from 'examples/column-filter/multi-select-filter';
import MultiSelectFilterDefaultValue from 'examples/column-filter/multi-select-filter-default-value';
@@ -118,6 +119,7 @@ import MultipleSelectionTable from 'examples/row-selection/multiple-selection';
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 AdvanceSelectionManagement from 'examples/row-selection/selection-advance-management';
import ClickToSelectWithCellEditTable from 'examples/row-selection/click-to-select-with-cell-edit';
import SelectionWithExpansionTable from 'examples/row-selection/selection-with-expansion';
import SelectionNoDataTable from 'examples/row-selection/selection-no-data';
@@ -262,6 +264,7 @@ storiesOf('Column Filter', module)
.add('Programmatically Multi Select Filter', () => )
.add('Custom Filter', () => )
.add('Advance Custom Filter', () => )
+ .add('Preserved Option Order on Select Filter', () => )
.add('Clear All Filters', () => );
storiesOf('Work on Rows', module)
@@ -312,6 +315,7 @@ storiesOf('Row Selection', module)
.add('Click to Select', () => )
.add('Default Select', () => )
.add('Selection Management', () => )
+ .add('Advance Selection Management', () => )
.add('Click to Select and Edit Cell', () => )
.add('Row Select and Expand', () => )
.add('Selection without Data', () => )
diff --git a/packages/react-bootstrap-table2-filter/README.md b/packages/react-bootstrap-table2-filter/README.md
index 8369efd..f73b962 100644
--- a/packages/react-bootstrap-table2-filter/README.md
+++ b/packages/react-bootstrap-table2-filter/README.md
@@ -115,6 +115,27 @@ const qualityFilter = selectFilter({
// omit...
```
+> Note, the selectOptions can be an array also:
+
+```js
+const selectOptions = [
+ { label: 0, value: 'good' },
+ { label: 1, value: 'Bad' },
+ { label: 2, value: 'unknown' }
+];
+const columns = [
+ ..., {
+ dataField: 'quality',
+ text: 'Product Quailty',
+ formatter: cell => selectOptions.find(opt => opt.label === cell).value,
+ filter: selectFilter({
+ options: selectOptions
+ })
+}];
+```
+
+The benifit is `react-bootstrap-table2` will render the select options by the order of array.
+
## MultiSelect Filter
A quick example:
diff --git a/packages/react-bootstrap-table2-filter/src/components/select.js b/packages/react-bootstrap-table2-filter/src/components/select.js
index e505138..a30e691 100644
--- a/packages/react-bootstrap-table2-filter/src/components/select.js
+++ b/packages/react-bootstrap-table2-filter/src/components/select.js
@@ -7,6 +7,14 @@ import { LIKE, EQ } from '../comparison';
import { FILTER_TYPE } from '../const';
function optionsEquals(currOpts, prevOpts) {
+ if (Array.isArray(currOpts)) {
+ for (let i = 0; i < currOpts.length; i += 1) {
+ if (currOpts[i].label !== prevOpts[i].label) {
+ return false;
+ }
+ }
+ return currOpts.length === prevOpts.length;
+ }
const keys = Object.keys(currOpts);
for (let i = 0; i < keys.length; i += 1) {
if (currOpts[keys[i]] !== prevOpts[keys[i]]) {
@@ -16,11 +24,21 @@ function optionsEquals(currOpts, prevOpts) {
return Object.keys(currOpts).length === Object.keys(prevOpts).length;
}
+function getOptionValue(options, key) {
+ if (Array.isArray(options)) {
+ const result = options
+ .filter(({ label }) => label === key)
+ .map(({ value }) => value);
+ return result[0];
+ }
+ return options[key];
+}
+
class SelectFilter extends Component {
constructor(props) {
super(props);
this.filter = this.filter.bind(this);
- const isSelected = props.options[props.defaultValue] !== undefined;
+ const isSelected = getOptionValue(props.options, props.defaultValue) !== undefined;
this.state = { isSelected };
}
@@ -66,9 +84,14 @@ class SelectFilter extends Component {
));
}
- Object.keys(options).forEach(key =>
- optionTags.push()
- );
+ if (Array.isArray(options)) {
+ options.forEach(({ value, label }) =>
+ optionTags.push());
+ } else {
+ Object.keys(options).forEach(key =>
+ optionTags.push()
+ );
+ }
return optionTags;
}
@@ -128,7 +151,7 @@ class SelectFilter extends Component {
SelectFilter.propTypes = {
onFilter: PropTypes.func.isRequired,
column: PropTypes.object.isRequired,
- options: PropTypes.object.isRequired,
+ options: PropTypes.oneOfType([PropTypes.object, PropTypes.array]).isRequired,
comparator: PropTypes.oneOf([LIKE, EQ]),
placeholder: PropTypes.string,
style: PropTypes.object,
diff --git a/packages/react-bootstrap-table2/src/contexts/selection-context.js b/packages/react-bootstrap-table2/src/contexts/selection-context.js
index ce8d354..f266824 100644
--- a/packages/react-bootstrap-table2/src/contexts/selection-context.js
+++ b/packages/react-bootstrap-table2/src/contexts/selection-context.js
@@ -43,20 +43,23 @@ class SelectionProvider extends React.Component {
let currSelected = [...this.state.selected];
- if (mode === ROW_SELECT_SINGLE) { // when select mode is radio
- currSelected = [rowKey];
- } else if (checked) { // when select mode is checkbox
- currSelected.push(rowKey);
- } else {
- currSelected = currSelected.filter(value => value !== rowKey);
- }
-
- if (onSelect) {
- const row = dataOperator.getRowByRowId(data, keyField, rowKey);
- onSelect(row, checked, rowIndex, e);
- }
-
- this.setState(() => ({ selected: currSelected }));
+ this.setState(() => {
+ let result = true;
+ if (onSelect) {
+ const row = dataOperator.getRowByRowId(data, keyField, rowKey);
+ result = onSelect(row, checked, rowIndex, e);
+ }
+ if (result === true || result === undefined) {
+ if (mode === ROW_SELECT_SINGLE) { // when select mode is radio
+ currSelected = [rowKey];
+ } else if (checked) { // when select mode is checkbox
+ currSelected.push(rowKey);
+ } else {
+ currSelected = currSelected.filter(value => value !== rowKey);
+ }
+ }
+ return { selected: currSelected };
+ });
}
handleAllRowsSelect = (e, isUnSelect) => {
@@ -78,19 +81,24 @@ class SelectionProvider extends React.Component {
currSelected = selected.filter(s => typeof data.find(d => d[keyField] === s) === 'undefined');
}
- if (onSelectAll) {
- onSelectAll(
- !isUnSelect,
- dataOperator.getSelectedRows(
- data,
- keyField,
- isUnSelect ? this.state.selected : currSelected
- ),
- e
- );
- }
-
- this.setState(() => ({ selected: currSelected }));
+ this.setState(() => {
+ let result;
+ if (onSelectAll) {
+ result = onSelectAll(
+ !isUnSelect,
+ dataOperator.getSelectedRows(
+ data,
+ keyField,
+ isUnSelect ? this.state.selected : currSelected
+ ),
+ e
+ );
+ if (Array.isArray(result)) {
+ currSelected = result;
+ }
+ }
+ return { selected: currSelected };
+ });
}
render() {