diff --git a/docs/migration.md b/docs/migration.md
index fb294c3..65d1040 100644
--- a/docs/migration.md
+++ b/docs/migration.md
@@ -85,7 +85,7 @@ Please see [available filter configuration](https://react-bootstrap-table.github
- [ ] Regex Filter
- [x] Select Filter
- [x] Custom Select Filter
-- [ ] Number Filter
+- [X] Number Filter
- [ ] Date Filter
- [ ] Array Filter
- [ ] Programmatically Filter
diff --git a/packages/react-bootstrap-table2-example/examples/column-filter/custom-number-filter.js b/packages/react-bootstrap-table2-example/examples/column-filter/custom-number-filter.js
new file mode 100644
index 0000000..29c361d
--- /dev/null
+++ b/packages/react-bootstrap-table2-example/examples/column-filter/custom-number-filter.js
@@ -0,0 +1,74 @@
+import React from 'react';
+import BootstrapTable from 'react-bootstrap-table-next';
+import filterFactory, { numberFilter, Comparator } from 'react-bootstrap-table2-filter';
+import Code from 'components/common/code-block';
+import { productsGenerator } from 'utils/common';
+
+const products = productsGenerator(8);
+
+const columns = [{
+ dataField: 'id',
+ text: 'Product ID'
+}, {
+ dataField: 'name',
+ text: 'Product Name'
+}, {
+ dataField: 'price',
+ text: 'Product Price',
+ filter: numberFilter({
+ options: [2100, 2103, 2105],
+ delay: 600,
+ placeholder: 'custom placeholder',
+ withoutEmptyComparatorOption: true,
+ comparators: [Comparator.EQ, Comparator.GT, Comparator.LT],
+ style: { display: 'inline-grid' },
+ className: 'custom-numberfilter-class',
+ comparatorStyle: { backgroundColor: 'antiquewhite' },
+ comparatorClassName: 'custom-comparator-class',
+ numberStyle: { backgroundColor: 'cadetblue', margin: '0px' },
+ numberClassName: 'custom-number-class'
+ })
+}];
+
+const sourceCode = `\
+import BootstrapTable from 'react-bootstrap-table-next';
+import filterFactory, { numberFilter, Comparator } from 'react-bootstrap-table2-filter';
+
+const columns = [{
+ dataField: 'id',
+ text: 'Product ID'
+}, {
+ dataField: 'name',
+ text: 'Product Name'
+}, {
+ dataField: 'price',
+ text: 'Product Price',
+ filter: numberFilter({
+ options: [2100, 2103, 2105],
+ delay: 600,
+ placeholder: 'custom placeholder',
+ withoutEmptyComparatorOption: true,
+ comparators: [Comparator.EQ, Comparator.GT, Comparator.LT],
+ style: { display: 'inline-grid' },
+ className: 'custom-numberfilter-class',
+ comparatorStyle: { backgroundColor: 'antiquewhite' },
+ comparatorClassName: 'custom-comparator-class',
+ numberStyle: { backgroundColor: 'cadetblue', margin: '0px' },
+ numberClassName: 'custom-number-class'
+ })
+}];
+
+
+`;
+
+export default () => (
+
+
+ { sourceCode }
+
+);
diff --git a/packages/react-bootstrap-table2-example/examples/column-filter/number-filter-default-value.js b/packages/react-bootstrap-table2-example/examples/column-filter/number-filter-default-value.js
new file mode 100644
index 0000000..463b472
--- /dev/null
+++ b/packages/react-bootstrap-table2-example/examples/column-filter/number-filter-default-value.js
@@ -0,0 +1,54 @@
+import React from 'react';
+import BootstrapTable from 'react-bootstrap-table-next';
+import filterFactory, { numberFilter, Comparator } from 'react-bootstrap-table2-filter';
+import Code from 'components/common/code-block';
+import { productsGenerator } from 'utils/common';
+
+const products = productsGenerator(8);
+
+const columns = [{
+ dataField: 'id',
+ text: 'Product ID'
+}, {
+ dataField: 'name',
+ text: 'Product Name'
+}, {
+ dataField: 'price',
+ text: 'Product Price',
+ filter: numberFilter({
+ defaultValue: { number: 2103, comparator: Comparator.GT }
+ })
+}];
+
+const sourceCode = `\
+import BootstrapTable from 'react-bootstrap-table-next';
+import filterFactory, { numberFilter, Comparator } from 'react-bootstrap-table2-filter';
+
+const columns = [{
+ dataField: 'id',
+ text: 'Product ID'
+}, {
+ dataField: 'name',
+ text: 'Product Name'
+}, {
+ dataField: 'price',
+ text: 'Product Price',
+ filter: numberFilter({
+ defaultValue: { number: 2103, comparator: Comparator.GT }
+ })
+}];
+
+
+`;
+
+export default () => (
+
+
+ { sourceCode }
+
+);
diff --git a/packages/react-bootstrap-table2-example/examples/column-filter/number-filter.js b/packages/react-bootstrap-table2-example/examples/column-filter/number-filter.js
new file mode 100644
index 0000000..b01167f
--- /dev/null
+++ b/packages/react-bootstrap-table2-example/examples/column-filter/number-filter.js
@@ -0,0 +1,50 @@
+import React from 'react';
+import BootstrapTable from 'react-bootstrap-table-next';
+import filterFactory, { numberFilter } from 'react-bootstrap-table2-filter';
+import Code from 'components/common/code-block';
+import { productsGenerator } from 'utils/common';
+
+const products = productsGenerator(8);
+
+const columns = [{
+ dataField: 'id',
+ text: 'Product ID'
+}, {
+ dataField: 'name',
+ text: 'Product Name'
+}, {
+ dataField: 'price',
+ text: 'Product Price',
+ filter: numberFilter()
+}];
+
+const sourceCode = `\
+import BootstrapTable from 'react-bootstrap-table-next';
+import filterFactory, { numberFilter } from 'react-bootstrap-table2-filter';
+
+const columns = [{
+ dataField: 'id',
+ text: 'Product ID'
+}, {
+ dataField: 'name',
+ text: 'Product Name'
+}, {
+ dataField: 'price',
+ text: 'Product Price',
+ filter: numberFilter()
+}];
+
+
+`;
+
+export default () => (
+
+
+ { sourceCode }
+
+);
diff --git a/packages/react-bootstrap-table2-example/stories/index.js b/packages/react-bootstrap-table2-example/stories/index.js
index f5e3db7..f4a000a 100644
--- a/packages/react-bootstrap-table2-example/stories/index.js
+++ b/packages/react-bootstrap-table2-example/stories/index.js
@@ -43,6 +43,9 @@ 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 CustomSelectFilter from 'examples/column-filter/custom-select-filter';
+import NumberFilter from 'examples/column-filter/number-filter';
+import NumberFilterWithDefaultValue from 'examples/column-filter/number-filter-default-value';
+import CustomNumberFilter from 'examples/column-filter/custom-number-filter';
// work on rows
import RowStyleTable from 'examples/rows/row-style';
@@ -143,12 +146,15 @@ storiesOf('Column Filter', module)
.add('Text Filter', () => )
.add('Text Filter with Default Value', () => )
.add('Text Filter with Comparator', () => )
- .add('Custom Text Filter', () => )
// add another filter type example right here.
.add('Select Filter', () => )
.add('Select Filter with Default Value', () => )
.add('Select Filter with Comparator', () => )
+ .add('Number Filter', () => )
+ .add('Number Filter with Default Value', () => )
+ .add('Custom Text Filter', () => )
.add('Custom Select Filter', () => )
+ .add('Custom Number Filter', () => )
.add('Custom Filter Value', () => );
storiesOf('Work on Rows', module)
diff --git a/packages/react-bootstrap-table2-filter/README.md b/packages/react-bootstrap-table2-filter/README.md
index 7557419..f98ecc7 100644
--- a/packages/react-bootstrap-table2-filter/README.md
+++ b/packages/react-bootstrap-table2-filter/README.md
@@ -18,6 +18,7 @@ You can get all types of filters via import and these filters are a factory func
* TextFilter
* SelectFilter
+* NumberFilter
* **Coming soon!**
## Add CSS
@@ -107,5 +108,44 @@ const qualityFilter = selectFilter({
withoutEmptyOption: true // hide the default select option
});
+// omit...
+```
+
+## Number Filter
+
+```js
+import filterFactory, { numberFilter } from 'react-bootstrap-table2-filter';
+
+const columns = [..., {
+ dataField: 'price',
+ text: 'Product Price',
+ filter: numberFilter()
+}];
+
+
+```
+
+Numner filter is same as other filter, you can custom the number filter via `numberFilter` factory function:
+
+```js
+import filterFactory, { selectFilter, Comparator } from 'react-bootstrap-table2-filter';
+// omit...
+
+const numberFilter = numberFilter({
+ options: [2100, 2103, 2105], // if options defined, will render number select instead of number input
+ delay: 600, // how long will trigger filtering after user typing, default is 500 ms
+ placeholder: 'custom placeholder', // placeholder for number input
+ withoutEmptyComparatorOption: true, // dont render empty option for comparator
+ withoutEmptyNumberOption: true, // dont render empty option for numner select if it is defined
+ comparators: [Comparator.EQ, Comparator.GT, Comparator.LT], // Custom the comparators
+ style: { display: 'inline-grid' }, // custom the style on number filter
+ className: 'custom-numberfilter-class', // custom the class on number filter
+ comparatorStyle: { backgroundColor: 'antiquewhite' }, // custom the style on comparator select
+ comparatorClassName: 'custom-comparator-class', // custom the class on comparator select
+ numberStyle: { backgroundColor: 'cadetblue', margin: '0px' }, // custom the style on number input/select
+ numberClassName: 'custom-number-class', // custom the class on ber input/select
+ defaultValue: { number: 2103, comparator: Comparator.GT } // default value
+})
+
// omit...
```
\ No newline at end of file
diff --git a/packages/react-bootstrap-table2-filter/index.js b/packages/react-bootstrap-table2-filter/index.js
index 068b508..a2bc666 100644
--- a/packages/react-bootstrap-table2-filter/index.js
+++ b/packages/react-bootstrap-table2-filter/index.js
@@ -1,5 +1,6 @@
import TextFilter from './src/components/text';
import SelectFilter from './src/components/select';
+import NumberFilter from './src/components/number';
import wrapperFactory from './src/wrapper';
import * as Comparison from './src/comparison';
@@ -19,3 +20,8 @@ export const selectFilter = (props = {}) => ({
Filter: SelectFilter,
props
});
+
+export const numberFilter = (props = {}) => ({
+ Filter: NumberFilter,
+ props
+});
diff --git a/packages/react-bootstrap-table2-filter/src/comparison.js b/packages/react-bootstrap-table2-filter/src/comparison.js
index cc24214..7e599e7 100644
--- a/packages/react-bootstrap-table2-filter/src/comparison.js
+++ b/packages/react-bootstrap-table2-filter/src/comparison.js
@@ -1,2 +1,7 @@
export const LIKE = 'LIKE';
export const EQ = '=';
+export const NE = '!=';
+export const GT = '>';
+export const GE = '>=';
+export const LT = '<';
+export const LE = '<=';
diff --git a/packages/react-bootstrap-table2-filter/src/components/number.js b/packages/react-bootstrap-table2-filter/src/components/number.js
new file mode 100644
index 0000000..3c2b612
--- /dev/null
+++ b/packages/react-bootstrap-table2-filter/src/components/number.js
@@ -0,0 +1,249 @@
+/* eslint no-return-assign: 0 */
+
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import * as Comparator from '../comparison';
+import { FILTER_TYPE, FILTER_DELAY } from '../const';
+
+const legalComparators = [
+ Comparator.EQ,
+ Comparator.NE,
+ Comparator.GT,
+ Comparator.GE,
+ Comparator.LT,
+ Comparator.LE
+];
+
+class NumberFilter extends Component {
+ constructor(props) {
+ super(props);
+ this.comparators = props.comparators || legalComparators;
+ this.timeout = null;
+ let isSelected = props.defaultValue !== undefined && props.defaultValue.number !== undefined;
+ if (props.options && isSelected) {
+ isSelected = props.options.indexOf(props.defaultValue.number) > -1;
+ }
+ this.state = { isSelected };
+ this.onChangeNumber = this.onChangeNumber.bind(this);
+ this.onChangeNumberSet = this.onChangeNumberSet.bind(this);
+ this.onChangeComparator = this.onChangeComparator.bind(this);
+ }
+
+ componentDidMount() {
+ const { column, onFilter } = this.props;
+ const comparator = this.numberFilterComparator.value;
+ const number = this.numberFilter.value;
+ if (comparator && number) {
+ onFilter(column, { number, comparator }, FILTER_TYPE.NUMBER);
+ }
+ }
+
+ componentWillUnmount() {
+ clearTimeout(this.timeout);
+ }
+
+ onChangeNumber(e) {
+ const { delay, column, onFilter } = this.props;
+ const comparator = this.numberFilterComparator.value;
+ if (comparator === '') {
+ return;
+ }
+ if (this.timeout) {
+ clearTimeout(this.timeout);
+ }
+ const filterValue = e.target.value;
+ this.timeout = setTimeout(() => {
+ onFilter(column, { number: filterValue, comparator }, FILTER_TYPE.NUMBER);
+ }, delay);
+ }
+
+ onChangeNumberSet(e) {
+ const { column, onFilter } = this.props;
+ const comparator = this.numberFilterComparator.value;
+ const { value } = e.target;
+ this.setState(() => ({ isSelected: (value !== '') }));
+ // if (comparator === '') {
+ // return;
+ // }
+ onFilter(column, { number: value, comparator }, FILTER_TYPE.NUMBER);
+ }
+
+ onChangeComparator(e) {
+ const { column, onFilter } = this.props;
+ const value = this.numberFilter.value;
+ const comparator = e.target.value;
+ // if (value === '') {
+ // return;
+ // }
+ onFilter(column, { number: value, comparator }, FILTER_TYPE.NUMBER);
+ }
+
+ getComparatorOptions() {
+ const optionTags = [];
+ const { withoutEmptyComparatorOption } = this.props;
+ if (!withoutEmptyComparatorOption) {
+ optionTags.push();
+ }
+ for (let i = 0; i < this.comparators.length; i += 1) {
+ optionTags.push(
+
+ );
+ }
+ return optionTags;
+ }
+
+ getNumberOptions() {
+ const optionTags = [];
+ const { options, column, withoutEmptyNumberOption } = this.props;
+ if (!withoutEmptyNumberOption) {
+ optionTags.push(
+
+ );
+ }
+ for (let i = 0; i < options.length; i += 1) {
+ optionTags.push();
+ }
+ return optionTags;
+ }
+
+ applyFilter(filterObj) {
+ const { column, onFilter } = this.props;
+ const { number, comparator } = filterObj;
+ this.setState(() => ({ isSelected: (number !== '') }));
+ this.numberFilterComparator.value = comparator;
+ this.numberFilter.value = number;
+ onFilter(column, { number, comparator }, FILTER_TYPE.NUMBER);
+ }
+
+ cleanFiltered() {
+ const { column, onFilter, defaultValue } = this.props;
+ const value = defaultValue ? defaultValue.number : '';
+ const comparator = defaultValue ? defaultValue.comparator : '';
+ this.setState(() => ({ isSelected: (value !== '') }));
+ this.numberFilterComparator.value = comparator;
+ this.numberFilter.value = value;
+ onFilter(column, { number: value, comparator }, FILTER_TYPE.NUMBER);
+ }
+
+ render() {
+ const { isSelected } = this.state;
+ const {
+ defaultValue,
+ column,
+ options,
+ style,
+ className,
+ numberStyle,
+ numberClassName,
+ comparatorStyle,
+ comparatorClassName,
+ placeholder
+ } = this.props;
+ const selectClass = `
+ select-filter
+ number-filter-input
+ form-control
+ ${numberClassName}
+ ${!isSelected ? 'placeholder-selected' : ''}
+ `;
+
+ return (
+
+
+ {
+ options ?
+ :
+ this.numberFilter = n }
+ type="number"
+ style={ numberStyle }
+ className={ `number-filter-input form-control ${numberClassName}` }
+ placeholder={ placeholder || `Enter ${column.text}...` }
+ onChange={ this.onChangeNumber }
+ defaultValue={ defaultValue ? defaultValue.number : '' }
+ />
+ }
+
+ );
+ }
+}
+
+NumberFilter.propTypes = {
+ onFilter: PropTypes.func.isRequired,
+ column: PropTypes.object.isRequired,
+ options: PropTypes.arrayOf(PropTypes.number),
+ defaultValue: PropTypes.shape({
+ number: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
+ comparator: PropTypes.oneOf([...legalComparators, ''])
+ }),
+ delay: PropTypes.number,
+ /* eslint consistent-return: 0 */
+ comparators: (props, propName) => {
+ if (!props[propName]) {
+ return;
+ }
+ for (let i = 0; i < props[propName].length; i += 1) {
+ let comparatorIsValid = false;
+ for (let j = 0; j < legalComparators.length; j += 1) {
+ if (legalComparators[j] === props[propName][i] || props[propName][i] === '') {
+ comparatorIsValid = true;
+ break;
+ }
+ }
+ if (!comparatorIsValid) {
+ return new Error(`Number comparator provided is not supported.
+ Use only ${legalComparators}`);
+ }
+ }
+ },
+ placeholder: PropTypes.string,
+ withoutEmptyComparatorOption: PropTypes.bool,
+ withoutEmptyNumberOption: PropTypes.bool,
+ style: PropTypes.object,
+ className: PropTypes.string,
+ comparatorStyle: PropTypes.object,
+ comparatorClassName: PropTypes.string,
+ numberStyle: PropTypes.object,
+ numberClassName: PropTypes.string
+};
+
+NumberFilter.defaultProps = {
+ delay: FILTER_DELAY,
+ options: undefined,
+ defaultValue: {
+ number: undefined,
+ comparator: ''
+ },
+ withoutEmptyComparatorOption: false,
+ withoutEmptyNumberOption: false,
+ comparators: legalComparators,
+ placeholder: undefined,
+ style: undefined,
+ className: '',
+ comparatorStyle: undefined,
+ comparatorClassName: '',
+ numberStyle: undefined,
+ numberClassName: ''
+};
+
+export default NumberFilter;
diff --git a/packages/react-bootstrap-table2-filter/src/const.js b/packages/react-bootstrap-table2-filter/src/const.js
index 64e8361..a459270 100644
--- a/packages/react-bootstrap-table2-filter/src/const.js
+++ b/packages/react-bootstrap-table2-filter/src/const.js
@@ -1,6 +1,7 @@
export const FILTER_TYPE = {
TEXT: 'TEXT',
- SELECT: 'SELECT'
+ SELECT: 'SELECT',
+ NUMBER: 'NUMBER'
};
export const FILTER_DELAY = 500;
diff --git a/packages/react-bootstrap-table2-filter/src/filter.js b/packages/react-bootstrap-table2-filter/src/filter.js
index 03914a8..95d0200 100644
--- a/packages/react-bootstrap-table2-filter/src/filter.js
+++ b/packages/react-bootstrap-table2-filter/src/filter.js
@@ -1,5 +1,7 @@
+/* eslint eqeqeq: 0 */
+/* eslint no-console: 0 */
import { FILTER_TYPE } from './const';
-import { LIKE, EQ } from './comparison';
+import { LIKE, EQ, NE, GT, GE, LT, LE } from './comparison';
export const filterByText = _ => (
data,
@@ -19,12 +21,75 @@ export const filterByText = _ => (
return cellStr.indexOf(filterVal) > -1;
});
+export const filterByNumber = _ => (
+ data,
+ dataField,
+ { filterVal: { comparator, number } },
+ customFilterValue
+) =>
+ data.filter((row) => {
+ if (number === '' || !comparator) return true;
+ let valid = true;
+ let cell = _.get(row, dataField);
+ if (customFilterValue) {
+ cell = customFilterValue(cell, row);
+ }
+
+ switch (comparator) {
+ case EQ: {
+ if (cell != number) {
+ valid = false;
+ }
+ break;
+ }
+ case GT: {
+ if (cell <= number) {
+ valid = false;
+ }
+ break;
+ }
+ case GE: {
+ if (cell < number) {
+ valid = false;
+ }
+ break;
+ }
+ case LT: {
+ if (cell >= number) {
+ valid = false;
+ }
+ break;
+ }
+ case LE: {
+ if (cell > number) {
+ valid = false;
+ }
+ break;
+ }
+ case NE: {
+ if (cell == number) {
+ valid = false;
+ }
+ break;
+ }
+ default: {
+ console.error('Number comparator provided is not supported');
+ break;
+ }
+ }
+ return valid;
+ });
+
export const filterFactory = _ => (filterType) => {
let filterFn;
switch (filterType) {
case FILTER_TYPE.TEXT:
+ case FILTER_TYPE.SELECT:
filterFn = filterByText(_);
break;
+ case FILTER_TYPE.NUMBER:
+ filterFn = filterByNumber(_);
+ break;
default:
filterFn = filterByText(_);
}
diff --git a/packages/react-bootstrap-table2-filter/style/react-bootstrap-table2-filter.scss b/packages/react-bootstrap-table2-filter/style/react-bootstrap-table2-filter.scss
index 16aa6dd..70d4a03 100644
--- a/packages/react-bootstrap-table2-filter/style/react-bootstrap-table2-filter.scss
+++ b/packages/react-bootstrap-table2-filter/style/react-bootstrap-table2-filter.scss
@@ -3,7 +3,9 @@
}
.react-bootstrap-table > table > thead > tr > th .select-filter option[value=''],
-.react-bootstrap-table > table > thead > tr > th .select-filter.placeholder-selected {
+.react-bootstrap-table > table > thead > tr > th .select-filter.placeholder-selected,
+.react-bootstrap-table > table > thead > tr > th .filter::-webkit-input-placeholder,
+.react-bootstrap-table > table > thead > tr > th .number-filter-input::-webkit-input-placeholder {
color: lightgrey;
font-style: italic;
}
@@ -11,4 +13,19 @@
.react-bootstrap-table > table > thead > tr > th .select-filter.placeholder-selected option:not([value='']) {
color: initial;
font-style: initial;
+}
+
+.react-bootstrap-table > table > thead > tr > th .number-filter {
+ display: flex;
+}
+
+.react-bootstrap-table > table > thead > tr > th .number-filter-input {
+ margin-left: 5px;
+ float: left;
+ width: calc(100% - 67px - 5px);
+}
+
+.react-bootstrap-table > table > thead > tr > th .number-filter-comparator {
+ width: 67px;
+ float: left;
}
\ No newline at end of file
diff --git a/packages/react-bootstrap-table2-filter/test/components/number.test.js b/packages/react-bootstrap-table2-filter/test/components/number.test.js
new file mode 100644
index 0000000..6ba66f7
--- /dev/null
+++ b/packages/react-bootstrap-table2-filter/test/components/number.test.js
@@ -0,0 +1,310 @@
+import 'jsdom-global/register';
+import React from 'react';
+import sinon from 'sinon';
+import { mount } from 'enzyme';
+import NumberFilter from '../../src/components/number';
+import { FILTER_TYPE } from '../../src/const';
+import * as Comparator from '../../src/comparison';
+
+
+describe('Number Filter', () => {
+ let wrapper;
+ const onFilter = sinon.stub();
+ const column = {
+ dataField: 'price',
+ text: 'Product Price'
+ };
+
+ afterEach(() => {
+ onFilter.reset();
+ });
+
+ describe('initialization', () => {
+ beforeEach(() => {
+ wrapper = mount(
+
+ );
+ });
+
+ it('should have correct state', () => {
+ expect(wrapper.state().isSelected).toBeFalsy();
+ });
+
+ it('should rendering component successfully', () => {
+ expect(wrapper).toHaveLength(1);
+ expect(wrapper.find('select')).toHaveLength(1);
+ expect(wrapper.find('input[type="number"]')).toHaveLength(1);
+ expect(wrapper.find('.number-filter')).toHaveLength(1);
+ });
+
+ it('should rendering comparator options correctly', () => {
+ const select = wrapper.find('select');
+ expect(select.find('option')).toHaveLength(wrapper.prop('comparators').length + 1);
+ });
+ });
+
+ describe('when withoutEmptyComparatorOption prop is true', () => {
+ beforeEach(() => {
+ wrapper = mount(
+
+ );
+ });
+
+ it('should rendering comparator options correctly', () => {
+ const select = wrapper.find('select');
+ expect(select.find('option')).toHaveLength(wrapper.prop('comparators').length);
+ });
+ });
+
+ describe('when defaultValue.number props is defined', () => {
+ const number = 203;
+
+ beforeEach(() => {
+ wrapper = mount(
+
+ );
+ });
+
+ it('should rendering input successfully', () => {
+ expect(wrapper).toHaveLength(1);
+ const input = wrapper.find('input[type="number"]');
+ expect(input).toHaveLength(1);
+ expect(input.props().defaultValue).toEqual(number);
+ });
+ });
+
+ describe('when defaultValue.comparator props is defined', () => {
+ const comparator = Comparator.EQ;
+
+ beforeEach(() => {
+ wrapper = mount(
+
+ );
+ });
+
+ it('should rendering comparator select successfully', () => {
+ expect(wrapper).toHaveLength(1);
+ const select = wrapper.find('.number-filter-comparator');
+ expect(select).toHaveLength(1);
+ expect(select.props().defaultValue).toEqual(comparator);
+ });
+ });
+
+ describe('when defaultValue.number and defaultValue.comparator props is defined', () => {
+ const number = 203;
+ const comparator = Comparator.EQ;
+
+ beforeEach(() => {
+ wrapper = mount(
+
+ );
+ });
+
+ it('should have correct state', () => {
+ expect(wrapper.state().isSelected).toBeTruthy();
+ });
+
+ it('should calling onFilter on componentDidMount', () => {
+ expect(onFilter.calledOnce).toBeTruthy();
+ expect(onFilter.calledWith(
+ column, { number: `${number}`, comparator }, FILTER_TYPE.NUMBER)).toBeTruthy();
+ });
+ });
+
+ describe('when options props is defined', () => {
+ const options = [2100, 2103, 2105];
+
+ beforeEach(() => {
+ wrapper = mount(
+
+ );
+ });
+
+ it('should rendering number options instead of number input', () => {
+ expect(wrapper).toHaveLength(1);
+ const select = wrapper.find('.select-filter.placeholder-selected');
+ expect(select).toHaveLength(1);
+ expect(select.find('option')).toHaveLength(options.length + 1);
+ });
+
+ describe('when withoutEmptyNumberOption props is defined', () => {
+ beforeEach(() => {
+ wrapper = mount(
+
+ );
+ });
+
+ it('should rendering number options instead of number input', () => {
+ const select = wrapper.find('.select-filter.placeholder-selected');
+ expect(select).toHaveLength(1);
+ expect(select.find('option')).toHaveLength(options.length);
+ });
+ });
+
+ describe('when defaultValue.number props is defined', () => {
+ const number = 203;
+
+ beforeEach(() => {
+ wrapper = mount(
+
+ );
+ });
+
+ it('should rendering number options successfully', () => {
+ const select = wrapper.find('.select-filter.placeholder-selected');
+ expect(select).toHaveLength(1);
+ expect(select.props().defaultValue).toEqual(number);
+ });
+ });
+
+ describe('when defaultValue.number and defaultValue.comparator props is defined', () => {
+ const number = options[1];
+ const comparator = Comparator.EQ;
+
+ beforeEach(() => {
+ wrapper = mount(
+
+ );
+ });
+
+ it('should rendering number options successfully', () => {
+ let select = wrapper.find('.placeholder-selected');
+ expect(select).toHaveLength(0);
+
+ select = wrapper.find('.select-filter');
+ expect(select).toHaveLength(1);
+ });
+ });
+ });
+
+ describe('when style props is defined', () => {
+ const style = { backgroundColor: 'red' };
+ beforeEach(() => {
+ wrapper = mount(
+
+ );
+ });
+
+ it('should rendering component successfully', () => {
+ expect(wrapper).toHaveLength(1);
+ expect(wrapper.find('.number-filter').prop('style')).toEqual(style);
+ });
+ });
+
+ describe('when numberStyle props is defined', () => {
+ const numberStyle = { backgroundColor: 'red' };
+ beforeEach(() => {
+ wrapper = mount(
+
+ );
+ });
+
+ it('should rendering component successfully', () => {
+ expect(wrapper).toHaveLength(1);
+ expect(wrapper.find('.number-filter-input').prop('style')).toEqual(numberStyle);
+ });
+ });
+
+ describe('when comparatorStyle props is defined', () => {
+ const comparatorStyle = { backgroundColor: 'red' };
+ beforeEach(() => {
+ wrapper = mount(
+
+ );
+ });
+
+ it('should rendering component successfully', () => {
+ expect(wrapper).toHaveLength(1);
+ expect(wrapper.find('select').prop('style')).toEqual(comparatorStyle);
+ });
+ });
+
+ describe('when className props is defined', () => {
+ const className = 'test';
+ beforeEach(() => {
+ wrapper = mount(
+
+ );
+ });
+
+ it('should rendering component successfully', () => {
+ expect(wrapper).toHaveLength(1);
+ expect(wrapper.hasClass(className)).toBeTruthy();
+ });
+ });
+
+ describe('when numberClassName props is defined', () => {
+ const className = 'test';
+ beforeEach(() => {
+ wrapper = mount(
+
+ );
+ });
+
+ it('should rendering component successfully', () => {
+ expect(wrapper).toHaveLength(1);
+ expect(wrapper.find('.number-filter-input').prop('className').indexOf(className) > -1).toBeTruthy();
+ });
+ });
+
+ describe('when comparatorClassName props is defined', () => {
+ const className = 'test';
+ beforeEach(() => {
+ wrapper = mount(
+
+ );
+ });
+
+ it('should rendering component successfully', () => {
+ expect(wrapper).toHaveLength(1);
+ expect(wrapper.find('select').prop('className').indexOf(className) > -1).toBeTruthy();
+ });
+ });
+});
diff --git a/packages/react-bootstrap-table2-filter/test/filter.test.js b/packages/react-bootstrap-table2-filter/test/filter.test.js
index e834f17..28be4a5 100644
--- a/packages/react-bootstrap-table2-filter/test/filter.test.js
+++ b/packages/react-bootstrap-table2-filter/test/filter.test.js
@@ -4,7 +4,7 @@ import Store from 'react-bootstrap-table-next/src/store';
import { filters } from '../src/filter';
import { FILTER_TYPE } from '../src/const';
-import { LIKE, EQ } from '../src/comparison';
+import { LIKE, EQ, GT, GE, LT, LE, NE } from '../src/comparison';
const data = [];
for (let i = 0; i < 20; i += 1) {
@@ -37,7 +37,7 @@ describe('filter', () => {
}];
});
- describe('text filter', () => {
+ describe('filterByText', () => {
beforeEach(() => {
filterFn = filters(store, columns, _);
});
@@ -91,4 +91,114 @@ describe('filter', () => {
});
});
});
+
+ describe('filterByNumber', () => {
+ beforeEach(() => {
+ filterFn = filters(store, columns, _);
+ });
+
+ describe('when currFilters.filterVal.comparator is empty', () => {
+ it('should returning correct result', () => {
+ currFilters.price = {
+ filterVal: { comparator: '', number: '203' },
+ filterType: FILTER_TYPE.NUMBER
+ };
+
+ let result = filterFn(currFilters);
+ expect(result).toHaveLength(data.length);
+
+ currFilters.price.filterVal.comparator = undefined;
+ result = filterFn(currFilters);
+ expect(result).toHaveLength(data.length);
+ });
+ });
+
+ describe('when currFilters.filterVal.number is empty', () => {
+ it('should returning correct result', () => {
+ currFilters.price = {
+ filterVal: { comparator: EQ, number: '' },
+ filterType: FILTER_TYPE.NUMBER
+ };
+
+ const result = filterFn(currFilters);
+ expect(result).toHaveLength(data.length);
+ });
+ });
+
+ describe(`when currFilters.filterVal.comparator is ${EQ}`, () => {
+ it('should returning correct result', () => {
+ currFilters.price = {
+ filterVal: { comparator: EQ, number: '203' },
+ filterType: FILTER_TYPE.NUMBER
+ };
+
+ let result = filterFn(currFilters);
+ expect(result).toHaveLength(1);
+
+ currFilters.price.filterVal.number = '0';
+ result = filterFn(currFilters);
+ expect(result).toHaveLength(0);
+ });
+ });
+
+ describe(`when currFilters.filterVal.comparator is ${GT}`, () => {
+ it('should returning correct result', () => {
+ currFilters.price = {
+ filterVal: { comparator: GT, number: '203' },
+ filterType: FILTER_TYPE.NUMBER
+ };
+
+ const result = filterFn(currFilters);
+ expect(result).toHaveLength(16);
+ });
+ });
+
+ describe(`when currFilters.filterVal.comparator is ${GE}`, () => {
+ it('should returning correct result', () => {
+ currFilters.price = {
+ filterVal: { comparator: GE, number: '203' },
+ filterType: FILTER_TYPE.NUMBER
+ };
+
+ const result = filterFn(currFilters);
+ expect(result).toHaveLength(17);
+ });
+ });
+
+ describe(`when currFilters.filterVal.comparator is ${LT}`, () => {
+ it('should returning correct result', () => {
+ currFilters.price = {
+ filterVal: { comparator: LT, number: '203' },
+ filterType: FILTER_TYPE.NUMBER
+ };
+
+ const result = filterFn(currFilters);
+ expect(result).toHaveLength(3);
+ });
+ });
+
+ describe(`when currFilters.filterVal.comparator is ${LE}`, () => {
+ it('should returning correct result', () => {
+ currFilters.price = {
+ filterVal: { comparator: LE, number: '203' },
+ filterType: FILTER_TYPE.NUMBER
+ };
+
+ const result = filterFn(currFilters);
+ expect(result).toHaveLength(4);
+ });
+ });
+
+ describe(`when currFilters.filterVal.comparator is ${NE}`, () => {
+ it('should returning correct result', () => {
+ currFilters.price = {
+ filterVal: { comparator: NE, number: '203' },
+ filterType: FILTER_TYPE.NUMBER
+ };
+
+ const result = filterFn(currFilters);
+ expect(result).toHaveLength(19);
+ });
+ });
+ });
});