diff --git a/docs/columns.md b/docs/columns.md
index 906536ef4..525ec4d30 100644
--- a/docs/columns.md
+++ b/docs/columns.md
@@ -49,6 +49,7 @@ Available properties in a column object:
* [editorRenderer](#editorRenderer)
* [filter](#filter)
* [filterValue](#filterValue)
+* [searchable](#searchable)
* [csvType](#csvType)
* [csvFormatter](#csvFormatter)
* [csvText](#csvText)
@@ -917,6 +918,9 @@ A final `String` value you want to be filtered.
}
```
+## column.searchable - [Boolean]
+Default the column is searchable. Give `false` to disable search functionality on specified column.
+
## column.csvType - [Object]
Default is `String`. Currently, the available value is `String` and `Number`. If `Number` assigned, the cell value will not wrapped with double quote.
diff --git a/docs/row-expand.md b/docs/row-expand.md
index 0110fa1f0..a4b49d528 100644
--- a/docs/row-expand.md
+++ b/docs/row-expand.md
@@ -18,6 +18,7 @@
* [expandColumnPosition](#expandColumnPosition)
* [expandColumnRenderer](#expandColumnRenderer)
* [expandHeaderColumnRenderer](#expandHeaderColumnRenderer)
+* [className](#className)
* [parentClassName](#parentClassName)
### expandRow.renderer - [Function]
@@ -168,6 +169,27 @@ const expandRow = {
};
```
+### expandRow.className - [String | Function]
+Apply the custom class name on the expanding row. For example:
+
+```js
+const expandRow = {
+ renderer: (row) => ...,
+ className: 'foo'
+};
+```
+following usage is more flexible way for customing the class name:
+
+```js
+const expandRow = {
+ renderer: (row) => ...,
+ className: (isExpanded, row, rowIndex) => {
+ if (rowIndex > 2) return 'foo';
+ return 'bar';
+ }
+};
+```
+
### expandRow.parentClassName - [String | Function]
Apply the custom class name on parent row of expanded row. For example:
diff --git a/packages/react-bootstrap-table2-example/examples/column-filter/select-filter-option-type.js b/packages/react-bootstrap-table2-example/examples/column-filter/select-filter-option-type.js
new file mode 100644
index 000000000..5591d4a86
--- /dev/null
+++ b/packages/react-bootstrap-table2-example/examples/column-filter/select-filter-option-type.js
@@ -0,0 +1,150 @@
+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 = {
+ 0: 'good',
+ 1: 'Bad',
+ 2: 'unknown'
+};
+
+const selectOptionsArr = [{
+ value: 0,
+ label: 'good'
+}, {
+ value: 1,
+ label: 'Bad'
+}, {
+ value: 2,
+ label: 'unknown'
+}];
+
+const columns1 = [{
+ dataField: 'id',
+ text: 'Product ID'
+}, {
+ dataField: 'name',
+ text: 'Product Name'
+}, {
+ dataField: 'quality',
+ text: 'Product Quailty',
+ formatter: cell => selectOptions[cell],
+ filter: selectFilter({
+ options: selectOptions
+ })
+}];
+
+const columns2 = [{
+ dataField: 'id',
+ text: 'Product ID'
+}, {
+ dataField: 'name',
+ text: 'Product Name'
+}, {
+ dataField: 'quality',
+ text: 'Product Quailty',
+ formatter: cell => selectOptionsArr.filter(opt => opt.value === cell)[0].label || '',
+ filter: selectFilter({
+ options: selectOptionsArr
+ })
+}];
+
+const columns3 = [{
+ dataField: 'id',
+ text: 'Product ID'
+}, {
+ dataField: 'name',
+ text: 'Product Name'
+}, {
+ dataField: 'quality',
+ text: 'Product Quailty',
+ formatter: cell => selectOptionsArr.filter(opt => opt.value === cell)[0].label || '',
+ filter: selectFilter({
+ options: () => selectOptionsArr
+ })
+}];
+
+const sourceCode = `\
+import BootstrapTable from 'react-bootstrap-table-next';
+import filterFactory, { selectFilter } from 'react-bootstrap-table2-filter';
+
+// Object map options
+const selectOptions = {
+ 0: 'good',
+ 1: 'Bad',
+ 2: 'unknown'
+};
+
+// Array options
+const selectOptionsArr = [{
+ value: 0,
+ label: 'good'
+}, {
+ value: 1,
+ label: 'Bad'
+}, {
+ value: 2,
+ label: 'unknown'
+}];
+
+const columns1 = [..., {
+ dataField: 'quality',
+ text: 'Product Quailty',
+ formatter: cell => selectOptions[cell],
+ filter: selectFilter({
+ options: selectOptions
+ })
+}];
+
+
+const columns2 = [..., {
+ dataField: 'quality',
+ text: 'Product Quailty',
+ formatter: cell => selectOptionsArr.filter(opt => opt.value === cell)[0].label || '',
+ filter: selectFilter({
+ options: selectOptionsArr
+ })
+}];
+
+
+const columns3 = [..., {
+ dataField: 'quality',
+ text: 'Product Quailty',
+ formatter: cell => selectOptionsArr.filter(opt => opt.value === cell)[0].label || '',
+ filter: selectFilter({
+ options: () => selectOptionsArr
+ })
+}];
+
+`;
+
+export default () => (
+
+
Options as an object
+
+ Options as an array
+
+ Options as a function which return an array
+
+ { sourceCode }
+
+);
diff --git a/packages/react-bootstrap-table2-example/examples/row-expand/expanding-row-classname.js b/packages/react-bootstrap-table2-example/examples/row-expand/expanding-row-classname.js
new file mode 100644
index 000000000..c6e977dd2
--- /dev/null
+++ b/packages/react-bootstrap-table2-example/examples/row-expand/expanding-row-classname.js
@@ -0,0 +1,106 @@
+import React from 'react';
+
+import BootstrapTable from 'react-bootstrap-table-next';
+import Code from 'components/common/code-block';
+import { productsExpandRowsGenerator } from 'utils/common';
+
+const products = productsExpandRowsGenerator();
+
+const columns = [{
+ dataField: 'id',
+ text: 'Product ID'
+}, {
+ dataField: 'name',
+ text: 'Product Name'
+}, {
+ dataField: 'price',
+ text: 'Product Price'
+}];
+
+const expandRow1 = {
+ className: 'expanding-foo',
+ renderer: row => (
+
+
{ `This Expand row is belong to rowKey ${row.id}` }
+
You can render anything here, also you can add additional data on every row object
+
expandRow.renderer callback will pass the origin row object to you
+
+ )
+};
+
+const expandRow2 = {
+ className: (isExpanded, row, rowIndex) => {
+ if (rowIndex > 2) return 'expanding-foo';
+ return 'expanding-bar';
+ },
+ renderer: row => (
+
+
{ `This Expand row is belong to rowKey ${row.id}` }
+
You can render anything here, also you can add additional data on every row object
+
expandRow.renderer callback will pass the origin row object to you
+
+ )
+};
+
+
+const sourceCode1 = `\
+import BootstrapTable from 'react-bootstrap-table-next';
+
+const columns = // omit...
+
+const expandRow = {
+ className: 'expanding-foo',
+ renderer: row => (
+ .....
+ )
+};
+
+
+`;
+
+const sourceCode2 = `\
+import BootstrapTable from 'react-bootstrap-table-next';
+
+const columns = // omit...
+
+const expandRow = {
+ className: (isExpanded, row, rowIndex) => {
+ if (rowIndex > 2) return 'expanding-foo';
+ return 'expanding-bar';
+ },
+ renderer: row => (
+ ...
+ )
+};
+
+
+`;
+
+export default () => (
+
+
+ { sourceCode1 }
+
+ { sourceCode2 }
+
+);
diff --git a/packages/react-bootstrap-table2-example/examples/search/searchable-column.js b/packages/react-bootstrap-table2-example/examples/search/searchable-column.js
new file mode 100644
index 000000000..dc9b29340
--- /dev/null
+++ b/packages/react-bootstrap-table2-example/examples/search/searchable-column.js
@@ -0,0 +1,87 @@
+/* eslint react/prop-types: 0 */
+import React from 'react';
+
+import BootstrapTable from 'react-bootstrap-table-next';
+import ToolkitProvider, { Search } from 'react-bootstrap-table2-toolkit';
+import Code from 'components/common/code-block';
+import { productsGenerator } from 'utils/common';
+
+const { SearchBar } = Search;
+const products = productsGenerator();
+
+const columns = [{
+ dataField: 'id',
+ text: 'Product ID'
+}, {
+ dataField: 'name',
+ text: 'Product Name',
+ searchable: false
+}, {
+ dataField: 'price',
+ text: 'Product Price',
+ searchable: false
+}];
+
+const sourceCode = `\
+import BootstrapTable from 'react-bootstrap-table-next';
+import ToolkitProvider, { Search } from 'react-bootstrap-table2-toolkit';
+
+const { SearchBar } = Search;
+const columns = [{
+ dataField: 'id',
+ text: 'Product ID'
+}, {
+ dataField: 'name',
+ text: 'Product Name',
+ searchable: false
+}, {
+ dataField: 'price',
+ text: 'Product Price',
+ searchable: false
+}];
+
+
+ {
+ props => (
+
+
Input something at below input field:
+
+
+
+
+ )
+ }
+
+`;
+
+export default () => (
+
+
+ {
+ props => (
+
+
Column name and price is unsearchable
+
+
+
+
+ )
+ }
+
+
{ sourceCode }
+
+);
diff --git a/packages/react-bootstrap-table2-example/stories/index.js b/packages/react-bootstrap-table2-example/stories/index.js
index 6acd9b910..283278c48 100644
--- a/packages/react-bootstrap-table2-example/stories/index.js
+++ b/packages/react-bootstrap-table2-example/stories/index.js
@@ -68,6 +68,7 @@ import TextFilterCaseSensitive from 'examples/column-filter/text-filter-caseSens
import CustomTextFilter from 'examples/column-filter/custom-text-filter';
import CustomFilterValue from 'examples/column-filter/custom-filter-value';
import SelectFilter from 'examples/column-filter/select-filter';
+import ConfigureSelectFilterOptions from 'examples/column-filter/select-filter-option-type';
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';
@@ -166,6 +167,7 @@ import CustomExpandColumn from 'examples/row-expand/custom-expand-column';
import ExpandColumnPosition from 'examples/row-expand/expand-column-position';
import ExpandHooks from 'examples/row-expand/expand-hooks';
import ParentRowClassName from 'examples/row-expand/parent-row-classname';
+import ExpandingRowClassName from 'examples/row-expand/expanding-row-classname';
// pagination
import PaginationTable from 'examples/pagination';
@@ -192,6 +194,7 @@ import DefaultCustomSearch from 'examples/search/default-custom-search';
import FullyCustomSearch from 'examples/search/fully-custom-search';
import SearchFormattedData from 'examples/search/search-formatted';
import CustomSearchValue from 'examples/search/custom-search-value';
+import SearchableColumn from 'examples/search/searchable-column';
// CSV
import ExportCSV from 'examples/csv';
@@ -300,6 +303,7 @@ storiesOf('Column Filter', module)
.add('Text Filter with Case Sensitive', () => )
// add another filter type example right here.
.add('Select Filter', () => )
+ .add('Configure Select Filter Options', () => )
.add('Select Filter with Default Value', () => )
.add('Select Filter with Comparator', () => )
.add('MultiSelect Filter', () => )
@@ -417,7 +421,8 @@ storiesOf('Row Expand', module)
.add('Custom Expand Indicator', () => )
.add('Expand Column Position', () => )
.add('Expand Hooks', () => )
- .add('Custom Parent Row ClassName', () => );
+ .add('Custom Parent Row ClassName', () => )
+ .add('Custom Expanding Row ClassName', () => );
storiesOf('Pagination', module)
.addDecorator(bootstrapStyle())
@@ -443,6 +448,7 @@ storiesOf('Table Search', module)
.add('Clear Search Button', () => )
.add('Default Search Table', () => )
.add('Default Custom Search', () => )
+ .add('Searchable Column', () => )
.add('Fully Custom Search', () => )
.add('Search Formatted Value', () => )
.add('Custom Search Value', () => );
diff --git a/packages/react-bootstrap-table2-example/stories/stylesheet/row-expand/_index.scss b/packages/react-bootstrap-table2-example/stories/stylesheet/row-expand/_index.scss
index 0693da350..a5a5f2f98 100644
--- a/packages/react-bootstrap-table2-example/stories/stylesheet/row-expand/_index.scss
+++ b/packages/react-bootstrap-table2-example/stories/stylesheet/row-expand/_index.scss
@@ -1,7 +1,7 @@
-.parent-expand-foo {
+.expanding-foo, .parent-expand-foo {
background-color: coral;
}
-.parent-expand-bar {
+.expanding-bar, .parent-expand-bar {
background-color: aqua;
}
\ No newline at end of file
diff --git a/packages/react-bootstrap-table2-filter/README.md b/packages/react-bootstrap-table2-filter/README.md
index b38007ec0..46097baee 100644
--- a/packages/react-bootstrap-table2-filter/README.md
+++ b/packages/react-bootstrap-table2-filter/README.md
@@ -115,7 +115,9 @@ const qualityFilter = selectFilter({
// omit...
```
-> Note, the selectOptions can be an array also:
+> Note, the selectOptions can be an array or a function which return an array:
+
+### Array as options
```js
const selectOptions = [
@@ -133,6 +135,24 @@ const columns = [
})
}];
```
+### Function as options
+
+```js
+const selectOptions = [
+ { value: 0, label: 'good' },
+ { value: 1, label: 'Bad' },
+ { value: 2, label: 'unknown' }
+];
+const columns = [
+ ..., {
+ dataField: 'quality',
+ text: 'Product Quailty',
+ formatter: cell => selectOptions.find(opt => opt.value === cell).label,
+ filter: selectFilter({
+ options: () => selectOptions
+ })
+}];
+```
The benifit is `react-bootstrap-table2` will render the select options by the order of array.
diff --git a/packages/react-bootstrap-table2-filter/src/components/select.js b/packages/react-bootstrap-table2-filter/src/components/select.js
index 7b83827cc..7b49a8c68 100644
--- a/packages/react-bootstrap-table2-filter/src/components/select.js
+++ b/packages/react-bootstrap-table2-filter/src/components/select.js
@@ -1,6 +1,7 @@
/* eslint react/require-default-props: 0 */
/* eslint no-return-assign: 0 */
/* eslint react/no-unused-prop-types: 0 */
+/* eslint class-methods-use-this: 0 */
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { LIKE, EQ } from '../comparison';
@@ -44,7 +45,8 @@ class SelectFilter extends Component {
constructor(props) {
super(props);
this.filter = this.filter.bind(this);
- const isSelected = getOptionValue(props.options, this.getDefaultValue()) !== undefined;
+ this.options = this.getOptions(props);
+ const isSelected = getOptionValue(this.options, this.getDefaultValue()) !== undefined;
this.state = { isSelected };
}
@@ -69,19 +71,30 @@ class SelectFilter extends Component {
componentDidUpdate(prevProps) {
let needFilter = false;
- if (this.props.defaultValue !== prevProps.defaultValue) {
+ const {
+ column,
+ onFilter,
+ defaultValue
+ } = this.props;
+ const nextOptions = this.getOptions(this.props);
+ if (defaultValue !== prevProps.defaultValue) {
needFilter = true;
- } else if (!optionsEquals(this.props.options, prevProps.options)) {
+ } else if (!optionsEquals(nextOptions, this.options)) {
+ this.options = nextOptions;
needFilter = true;
}
if (needFilter) {
const value = this.selectInput.value;
if (value) {
- this.props.onFilter(this.props.column, FILTER_TYPE.SELECT)(value);
+ onFilter(column, FILTER_TYPE.SELECT)(value);
}
}
}
+ getOptions(props) {
+ return typeof props.options === 'function' ? props.options(props.column) : props.options;
+ }
+
getDefaultValue() {
const { filterState, defaultValue } = this.props;
if (filterState && typeof filterState.filterVal !== 'undefined') {
@@ -90,25 +103,6 @@ class SelectFilter extends Component {
return defaultValue;
}
- getOptions() {
- const optionTags = [];
- const { options, placeholder, column, withoutEmptyOption } = this.props;
- if (!withoutEmptyOption) {
- optionTags.push((
-
- ));
- }
- if (Array.isArray(options)) {
- options.forEach(({ value, label }) =>
- optionTags.push());
- } else {
- Object.keys(options).forEach(key =>
- optionTags.push()
- );
- }
- return optionTags;
- }
-
cleanFiltered() {
const value = (this.props.defaultValue !== undefined) ? this.props.defaultValue : '';
this.setState(() => ({ isSelected: value !== '' }));
@@ -128,6 +122,26 @@ class SelectFilter extends Component {
this.props.onFilter(this.props.column, FILTER_TYPE.SELECT)(value);
}
+ renderOptions() {
+ const optionTags = [];
+ const { options } = this;
+ const { placeholder, column, withoutEmptyOption } = this.props;
+ if (!withoutEmptyOption) {
+ optionTags.push((
+
+ ));
+ }
+ if (Array.isArray(options)) {
+ options.forEach(({ value, label }) =>
+ optionTags.push());
+ } else {
+ Object.keys(options).forEach(key =>
+ optionTags.push()
+ );
+ }
+ return optionTags;
+ }
+
render() {
const {
style,
@@ -163,7 +177,7 @@ class SelectFilter extends Component {
onClick={ e => e.stopPropagation() }
defaultValue={ this.getDefaultValue() || '' }
>
- { this.getOptions() }
+ { this.renderOptions() }
);
diff --git a/packages/react-bootstrap-table2-filter/src/filter.js b/packages/react-bootstrap-table2-filter/src/filter.js
index 0e2a72a74..8769e4fd6 100644
--- a/packages/react-bootstrap-table2-filter/src/filter.js
+++ b/packages/react-bootstrap-table2-filter/src/filter.js
@@ -234,6 +234,7 @@ export const filters = (data, columns, _) => (currFilters) => {
let result = data;
let filterFn;
Object.keys(currFilters).forEach((dataField) => {
+ let currentResult;
const filterObj = currFilters[dataField];
filterFn = factory(filterObj.filterType);
let filterValue;
@@ -248,9 +249,12 @@ export const filters = (data, columns, _) => (currFilters) => {
}
}
if (customFilter) {
- result = customFilter(filterObj.filterVal, result);
- } else {
+ currentResult = customFilter(filterObj.filterVal, result);
+ }
+ if (typeof currentResult === 'undefined') {
result = filterFn(result, dataField, filterObj, filterValue);
+ } else {
+ result = currentResult;
}
});
return result;
diff --git a/packages/react-bootstrap-table2/src/bootstrap-table.js b/packages/react-bootstrap-table2/src/bootstrap-table.js
index 42d419e48..692c29f3b 100644
--- a/packages/react-bootstrap-table2/src/bootstrap-table.js
+++ b/packages/react-bootstrap-table2/src/bootstrap-table.js
@@ -191,6 +191,7 @@ BootstrapTable.propTypes = {
Const.INDICATOR_POSITION_LEFT,
Const.INDICATOR_POSITION_RIGHT
]),
+ className: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
parentClassName: PropTypes.oneOfType([PropTypes.string, PropTypes.func])
}),
rowStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),
diff --git a/packages/react-bootstrap-table2/src/cell.js b/packages/react-bootstrap-table2/src/cell.js
index c3684bd20..d72a68fb9 100644
--- a/packages/react-bootstrap-table2/src/cell.js
+++ b/packages/react-bootstrap-table2/src/cell.js
@@ -28,6 +28,7 @@ class Cell extends eventDelegater(Component) {
shouldUpdate =
(nextProps.column.formatter ? !_.isEqual(this.props.row, nextProps.row) : false) ||
this.props.column.hidden !== nextProps.column.hidden ||
+ this.props.column.isDummyField !== nextProps.column.isDummyField ||
this.props.rowIndex !== nextProps.rowIndex ||
this.props.columnIndex !== nextProps.columnIndex ||
this.props.className !== nextProps.className ||
diff --git a/packages/react-bootstrap-table2/src/contexts/index.js b/packages/react-bootstrap-table2/src/contexts/index.js
index 1df8d6ca4..1793dfbd2 100644
--- a/packages/react-bootstrap-table2/src/contexts/index.js
+++ b/packages/react-bootstrap-table2/src/contexts/index.js
@@ -91,6 +91,13 @@ const withContext = Base =>
this.PaginationContext = nextProps.pagination.createContext(
this.isRemotePagination, this.handleRemotePageChange);
}
+ if (!nextProps.cellEdit && this.props.cellEdit) {
+ this.CellEditContext = null;
+ }
+ if (nextProps.cellEdit && !this.props.cellEdit) {
+ this.CellEditContext = nextProps.cellEdit.createContext(
+ _, dataOperator, this.isRemoteCellEdit, this.handleRemoteCellChange);
+ }
}
renderBase() {
diff --git a/packages/react-bootstrap-table2/src/header-cell.js b/packages/react-bootstrap-table2/src/header-cell.js
index 18f69c0be..f2b51062c 100644
--- a/packages/react-bootstrap-table2/src/header-cell.js
+++ b/packages/react-bootstrap-table2/src/header-cell.js
@@ -161,7 +161,8 @@ HeaderCell.propTypes = {
validator: PropTypes.func,
filter: PropTypes.object,
filterRenderer: PropTypes.func,
- filterValue: PropTypes.func
+ filterValue: PropTypes.func,
+ searchable: PropTypes.bool
}).isRequired,
index: PropTypes.number.isRequired,
onSort: PropTypes.func,
diff --git a/packages/react-bootstrap-table2/src/row-expand/expand-row.js b/packages/react-bootstrap-table2/src/row-expand/expand-row.js
index 3699adae7..140ce9036 100644
--- a/packages/react-bootstrap-table2/src/row-expand/expand-row.js
+++ b/packages/react-bootstrap-table2/src/row-expand/expand-row.js
@@ -1,10 +1,11 @@
+import cs from 'classnames';
import React from 'react';
import PropTypes from 'prop-types';
import { CSSTransition } from 'react-transition-group';
-const ExpandRow = ({ children, expanded, onClosed, ...rest }) => (
+const ExpandRow = ({ children, expanded, onClosed, className, ...rest }) => (
- |
+ |
(
ExpandRow.propTypes = {
children: PropTypes.node,
expanded: PropTypes.bool,
- onClosed: PropTypes.func
+ onClosed: PropTypes.func,
+ className: PropTypes.string
};
ExpandRow.defaultProps = {
children: null,
expanded: false,
- onClosed: null
+ onClosed: null,
+ className: ''
};
export default ExpandRow;
diff --git a/packages/react-bootstrap-table2/src/row-expand/row-consumer.js b/packages/react-bootstrap-table2/src/row-expand/row-consumer.js
index 8f30dc11e..0db8b64bf 100644
--- a/packages/react-bootstrap-table2/src/row-expand/row-consumer.js
+++ b/packages/react-bootstrap-table2/src/row-expand/row-consumer.js
@@ -8,6 +8,7 @@ import ExpansionContext from '../contexts/row-expand-context';
export default (Component) => {
const renderWithExpansion = (props, expandRow) => {
let parentClassName = '';
+ let className = '';
const key = props.value;
const expanded = _.contains(expandRow.expanded, key);
@@ -17,6 +18,10 @@ export default (Component) => {
parentClassName = _.isFunction(expandRow.parentClassName) ?
expandRow.parentClassName(expanded, props.row, props.rowIndex) :
(expandRow.parentClassName || '');
+
+ className = _.isFunction(expandRow.className) ?
+ expandRow.className(expanded, props.row, props.rowIndex) :
+ (expandRow.className || '');
}
return [
@@ -33,6 +38,7 @@ export default (Component) => {
colSpan={ props.visibleColumnSize }
expanded={ expanded }
onClosed={ () => expandRow.onClosed(key) }
+ className={ className }
>
{ expandRow.renderer(props.row, props.rowIndex) }
: null
|