diff --git a/packages/react-bootstrap-table2-filter/src/filter.js b/packages/react-bootstrap-table2-filter/src/filter.js index 6ca025d..03914a8 100644 --- a/packages/react-bootstrap-table2-filter/src/filter.js +++ b/packages/react-bootstrap-table2-filter/src/filter.js @@ -1,9 +1,17 @@ import { FILTER_TYPE } from './const'; import { LIKE, EQ } from './comparison'; -export const filterByText = _ => (data, dataField, { filterVal, comparator = LIKE }) => +export const filterByText = _ => ( + data, + dataField, + { filterVal, comparator = LIKE }, + customFilterValue +) => data.filter((row) => { - const cell = _.get(row, dataField); + let cell = _.get(row, dataField); + if (customFilterValue) { + cell = customFilterValue(cell, row); + } const cellStr = _.isDefined(cell) ? cell.toString() : ''; if (comparator === EQ) { return cellStr === filterVal; @@ -23,14 +31,15 @@ export const filterFactory = _ => (filterType) => { return filterFn; }; -export const filters = (store, _) => (currFilters) => { +export const filters = (store, columns, _) => (currFilters) => { const factory = filterFactory(_); let result = store.getAllData(); let filterFn; Object.keys(currFilters).forEach((dataField) => { const filterObj = currFilters[dataField]; filterFn = factory(filterObj.filterType); - result = filterFn(result, dataField, filterObj); + const { filterValue } = columns.find(col => col.dataField === dataField); + result = filterFn(result, dataField, filterObj, filterValue); }); return result; }; diff --git a/packages/react-bootstrap-table2-filter/src/wrapper.js b/packages/react-bootstrap-table2-filter/src/wrapper.js index 3f9363b..0cd8f44 100644 --- a/packages/react-bootstrap-table2-filter/src/wrapper.js +++ b/packages/react-bootstrap-table2-filter/src/wrapper.js @@ -5,6 +5,7 @@ import { filters } from './filter'; export default class FilterWrapper extends Component { static propTypes = { store: PropTypes.object.isRequired, + columns: PropTypes.array.isRequired, baseElement: PropTypes.func.isRequired, _: PropTypes.object.isRequired } @@ -20,7 +21,7 @@ export default class FilterWrapper extends Component { } onFilter(column, filterVal, filterType) { - const { store, _ } = this.props; + const { store, columns, _ } = this.props; const { currFilters } = this.state; const { dataField, filter } = column; @@ -31,7 +32,7 @@ export default class FilterWrapper extends Component { currFilters[dataField] = { filterVal, filterType, comparator }; } - store.filteredData = filters(store, _)(currFilters); + store.filteredData = filters(store, columns, _)(currFilters); store.filtering = Object.keys(currFilters).length > 0; this.setState(() => ({ currFilters, isDataChanged: true })); diff --git a/packages/react-bootstrap-table2-filter/test/filter.test.js b/packages/react-bootstrap-table2-filter/test/filter.test.js index 7f55a55..508c25f 100644 --- a/packages/react-bootstrap-table2-filter/test/filter.test.js +++ b/packages/react-bootstrap-table2-filter/test/filter.test.js @@ -1,3 +1,4 @@ +import sinon from 'sinon'; import _ from 'react-bootstrap-table2/src/utils'; import Store from 'react-bootstrap-table2/src/store'; @@ -18,16 +19,27 @@ describe('filter', () => { let store; let filterFn; let currFilters; + let columns; beforeEach(() => { store = new Store('id'); store.data = data; currFilters = {}; + columns = [{ + dataField: 'id', + text: 'ID' + }, { + dataField: 'name', + text: 'Name' + }, { + dataField: 'price', + text: 'Price' + }]; }); describe('text filter', () => { beforeEach(() => { - filterFn = filters(store, _); + filterFn = filters(store, columns, _); }); describe(`when default comparator is ${LIKE}`, () => { @@ -36,7 +48,7 @@ describe('filter', () => { filterVal: '3', filterType: FILTER_TYPE.TEXT }; - + const result = filterFn(currFilters); expect(result).toBeDefined(); expect(result).toHaveLength(2); @@ -50,11 +62,33 @@ describe('filter', () => { filterType: FILTER_TYPE.TEXT, comparator: EQ }; - + const result = filterFn(currFilters); expect(result).toBeDefined(); expect(result).toHaveLength(1); }); }); + + describe('column.filterValue is defined', () => { + beforeEach(() => { + columns[1].filterValue = sinon.stub(); + filterFn = filters(store, columns, _); + }); + + it('should calling custom filterValue callback correctly', () => { + currFilters.name = { + filterVal: '3', + filterType: FILTER_TYPE.TEXT + }; + + const result = filterFn(currFilters); + expect(result).toBeDefined(); + expect(columns[1].filterValue.callCount).toBe(data.length); + const calls = columns[1].filterValue.getCalls(); + calls.forEach((call, i) => { + expect(call.calledWith(data[i].name, data[i])).toBeTruthy(); + }); + }); + }); }); }); diff --git a/packages/react-bootstrap-table2/src/header-cell.js b/packages/react-bootstrap-table2/src/header-cell.js index d72f35b..80f819c 100644 --- a/packages/react-bootstrap-table2/src/header-cell.js +++ b/packages/react-bootstrap-table2/src/header-cell.js @@ -134,7 +134,8 @@ HeaderCell.propTypes = { editCellStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.func]), editCellClasses: PropTypes.oneOfType([PropTypes.string, PropTypes.func]), validator: PropTypes.func, - filter: PropTypes.object + filter: PropTypes.object, + filterValue: PropTypes.func }).isRequired, index: PropTypes.number.isRequired, onSort: PropTypes.func,