diff --git a/packages/react-bootstrap-table2-filter/index.js b/packages/react-bootstrap-table2-filter/index.js
index 6d9368a..af67dfc 100644
--- a/packages/react-bootstrap-table2-filter/index.js
+++ b/packages/react-bootstrap-table2-filter/index.js
@@ -3,12 +3,12 @@ import SelectFilter from './src/components/select';
import MultiSelectFilter from './src/components/multiselect';
import NumberFilter from './src/components/number';
import DateFilter from './src/components/date';
-import wrapperFactory from './src/wrapper';
+import createContext from './src/context';
import * as Comparison from './src/comparison';
import { FILTER_TYPE } from './src/const';
export default (options = {}) => ({
- wrapperFactory,
+ createContext,
options
});
diff --git a/packages/react-bootstrap-table2-filter/src/context.js b/packages/react-bootstrap-table2-filter/src/context.js
new file mode 100644
index 0000000..1459b3f
--- /dev/null
+++ b/packages/react-bootstrap-table2-filter/src/context.js
@@ -0,0 +1,94 @@
+/* eslint react/prop-types: 0 */
+/* eslint react/require-default-props: 0 */
+import React from 'react';
+import PropTypes from 'prop-types';
+
+import { filters } from './filter';
+import { LIKE, EQ } from './comparison';
+import { FILTER_TYPE } from './const';
+
+export default (
+ _,
+ isRemoteFiltering,
+ handleFilterChange
+) => {
+ const FilterContext = React.createContext();
+
+ class FilterProvider extends React.Component {
+ static propTypes = {
+ data: PropTypes.array.isRequired,
+ columns: PropTypes.array.isRequired
+ }
+
+ constructor(props) {
+ super(props);
+ this.currFilters = {};
+ this.onFilter = this.onFilter.bind(this);
+ this.onExternalFilter = this.onExternalFilter.bind(this);
+ }
+
+ onFilter(column, filterType) {
+ return (filterVal) => {
+ // watch out here if migration to context API, #334
+ const currFilters = Object.assign({}, this.currFilters);
+ const { dataField, filter } = column;
+
+ const needClearFilters =
+ !_.isDefined(filterVal) ||
+ filterVal === '' ||
+ filterVal.length === 0;
+
+ if (needClearFilters) {
+ delete currFilters[dataField];
+ } else {
+ // select default comparator is EQ, others are LIKE
+ const {
+ comparator = (filterType === FILTER_TYPE.SELECT ? EQ : LIKE),
+ caseSensitive = false
+ } = filter.props;
+ currFilters[dataField] = { filterVal, filterType, comparator, caseSensitive };
+ }
+
+ this.currFilters = currFilters;
+
+ if (isRemoteFiltering()) {
+ handleFilterChange(currFilters);
+ // when remote filtering is enable, dont set currFilters state
+ // in the componentWillReceiveProps,
+ // it's the key point that we can know the filter is changed
+ return;
+ }
+
+ this.forceUpdate();
+ };
+ }
+
+ onExternalFilter(column, filterType) {
+ return (value) => {
+ this.onFilter(column, filterType)(value);
+ };
+ }
+
+ render() {
+ let { data } = this.props;
+ if (!isRemoteFiltering()) {
+ data = filters(data, this.props.columns, _)(this.currFilters);
+ }
+ return (
+
+ { this.props.children }
+
+ );
+ }
+ }
+
+ return {
+ Provider: FilterProvider,
+ Consumer: FilterContext.Consumer
+ };
+};
diff --git a/packages/react-bootstrap-table2-filter/src/filter.js b/packages/react-bootstrap-table2-filter/src/filter.js
index c1a8666..07454c4 100644
--- a/packages/react-bootstrap-table2-filter/src/filter.js
+++ b/packages/react-bootstrap-table2-filter/src/filter.js
@@ -229,9 +229,9 @@ export const filterFactory = _ => (filterType) => {
return filterFn;
};
-export const filters = (store, columns, _) => (currFilters) => {
+export const filters = (data, columns, _) => (currFilters) => {
const factory = filterFactory(_);
- let result = store.getAllData();
+ let result = data;
let filterFn;
Object.keys(currFilters).forEach((dataField) => {
const filterObj = currFilters[dataField];
diff --git a/packages/react-bootstrap-table2-filter/src/wrapper.js b/packages/react-bootstrap-table2-filter/src/wrapper.js
deleted file mode 100644
index 0602ee8..0000000
--- a/packages/react-bootstrap-table2-filter/src/wrapper.js
+++ /dev/null
@@ -1,107 +0,0 @@
-/* eslint no-param-reassign: 0 */
-
-import React, { Component } from 'react';
-import PropTypes from 'prop-types';
-import { filters } from './filter';
-import { LIKE, EQ } from './comparison';
-import { FILTER_TYPE } from './const';
-
-export default (Base, {
- _,
- remoteResolver
-}) =>
- class FilterWrapper extends remoteResolver(Component) {
- static propTypes = {
- store: PropTypes.object.isRequired,
- columns: PropTypes.array.isRequired
- }
-
- constructor(props) {
- super(props);
- this.state = { currFilters: {}, isDataChanged: props.isDataChanged || false };
- this.onFilter = this.onFilter.bind(this);
- this.onExternalFilter = this.onExternalFilter.bind(this);
- }
-
- componentWillReceiveProps({ isDataChanged, store, columns }) {
- // consider to use lodash.isEqual
- const isRemoteFilter = this.isRemoteFiltering() || this.isRemotePagination();
- if (isRemoteFilter ||
- JSON.stringify(this.state.currFilters) !== JSON.stringify(store.filters)) {
- // I think this condition only isRemoteFilter is enough
- store.filteredData = store.getAllData();
- this.setState(() => ({ isDataChanged: true, currFilters: store.filters }));
- } else {
- if (Object.keys(this.state.currFilters).length > 0) {
- store.filteredData = filters(store, columns, _)(this.state.currFilters);
- }
- this.setState(() => ({ isDataChanged }));
- }
- }
-
- /**
- * filter the table like below:
- * onFilter(column, filterType)(filterVal)
- * @param {Object} column
- * @param {String} filterType
- * @param {String} filterVal - user input for filtering.
- */
- onFilter(column, filterType) {
- return (filterVal) => {
- const { store, columns } = this.props;
- // watch out here if migration to context API, #334
- const currFilters = Object.assign({}, store.filters);
- const { dataField, filter } = column;
-
- const needClearFilters =
- !_.isDefined(filterVal) ||
- filterVal === '' ||
- filterVal.length === 0;
-
- if (needClearFilters) {
- delete currFilters[dataField];
- } else {
- // select default comparator is EQ, others are LIKE
- const {
- comparator = (
- (filterType === FILTER_TYPE.SELECT) || (
- filterType === FILTER_TYPE.MULTISELECT) ? EQ : LIKE
- ),
- caseSensitive = false
- } = filter.props;
- currFilters[dataField] = { filterVal, filterType, comparator, caseSensitive };
- }
-
- store.filters = currFilters;
-
- if (this.isRemoteFiltering() || this.isRemotePagination()) {
- this.handleRemoteFilterChange();
- // when remote filtering is enable, dont set currFilters state
- // in the componentWillReceiveProps,
- // it's the key point that we can know the filter is changed
- return;
- }
-
- store.filteredData = filters(store, columns, _)(currFilters);
- this.setState(() => ({ currFilters, isDataChanged: true }));
- };
- }
-
- onExternalFilter(column, filterType) {
- return (value) => {
- this.onFilter(column, filterType)(value);
- };
- }
-
- render() {
- return (
-
- );
- }
- };
diff --git a/packages/react-bootstrap-table2/src/contexts/index.js b/packages/react-bootstrap-table2/src/contexts/index.js
index 20ed702..f01d7d3 100644
--- a/packages/react-bootstrap-table2/src/contexts/index.js
+++ b/packages/react-bootstrap-table2/src/contexts/index.js
@@ -1,4 +1,5 @@
/* eslint no-return-assign: 0 */
+/* eslint class-methods-use-this: 0 */
import React, { Component } from 'react';
import _ from '../utils';
import createDataContext from './data-context';
@@ -12,6 +13,7 @@ const withContext = (Base) => {
let SelectionContext;
let CellEditContext;
let SortContext;
+ let FilterContext;
return class BootstrapTableContainer extends remoteResolver(Component) {
constructor(props) {
@@ -23,6 +25,10 @@ const withContext = (Base) => {
CellEditContext = props.cellEdit.createContext(
_, dataOperator, this.isRemoteCellEdit, this.handleCellChange);
}
+ if (props.filter) {
+ FilterContext = props.filter.createContext(
+ _, this.isRemoteFiltering, this.handleRemoteFilterChange);
+ }
}
componentWillReceiveProps(nextProps) {
@@ -32,13 +38,13 @@ const withContext = (Base) => {
}
renderBase(baseProps) {
- return (rootProps, cellEditProps) => (
+ return (rootProps, cellEditProps, filterProps) => (
this.sortContext = n }
defaultSorted={ this.props.defaultSorted }
defaultSortDirection={ this.props.defaultSortDirection }
- data={ rootProps.data }
+ data={ filterProps ? filterProps.data : rootProps.data }
>
{
@@ -56,6 +62,7 @@ const withContext = (Base) => {
{ ...selectionProps }
{ ...sortProps }
{ ...cellEditProps }
+ { ...filterProps }
data={ sortProps.data }
/>
)
@@ -69,6 +76,22 @@ const withContext = (Base) => {
);
}
+ renderWithFilter(base, baseProps) {
+ return (rootProps, cellEditprops) => (
+ this.filterContext = n }
+ data={ rootProps.data }
+ >
+
+ {
+ filterProps => base(rootProps, cellEditprops, filterProps)
+ }
+
+
+ );
+ }
+
renderWithCellEdit(base, baseProps) {
return rootProps => (
{
let base = this.renderBase(baseProps);
+ if (FilterContext) {
+ base = this.renderWithFilter(base, baseProps);
+ }
+
if (CellEditContext) {
base = this.renderWithCellEdit(base, baseProps);
}
diff --git a/packages/react-bootstrap-table2/src/props-resolver/remote-resolver.js b/packages/react-bootstrap-table2/src/props-resolver/remote-resolver.js
index 4d0e833..a6c94f6 100644
--- a/packages/react-bootstrap-table2/src/props-resolver/remote-resolver.js
+++ b/packages/react-bootstrap-table2/src/props-resolver/remote-resolver.js
@@ -19,6 +19,7 @@ export default ExtendBase =>
sortField: this.sortContext.state.sortColumn ?
this.sortContext.state.sortColumn.dataField :
null,
+ filters: this.filterContext ? this.filterContext.currFilters : {},
...state,
data: this.props.data
};
@@ -29,9 +30,9 @@ export default ExtendBase =>
return remote === true || (_.isObject(remote) && remote.pagination);
}
- isRemoteFiltering() {
+ isRemoteFiltering = () => {
const { remote } = this.props;
- return remote === true || (_.isObject(remote) && remote.filter);
+ return remote === true || (_.isObject(remote) && remote.filter) || this.isRemotePagination();
}
isRemoteSort = () => {
@@ -48,8 +49,8 @@ export default ExtendBase =>
this.props.onTableChange('pagination', this.getNewestState());
}
- handleRemoteFilterChange() {
- const newState = {};
+ handleRemoteFilterChange = (filters) => {
+ const newState = { filters };
if (this.isRemotePagination()) {
const options = this.props.pagination.options || {};
newState.page = _.isDefined(options.pageStartIndex) ? options.pageStartIndex : 1;