Skip to content

Commit 27387c2

Browse files
authored
Merge pull request #1052 from react-bootstrap-table/bugfix/column-toggle-with-filter
fix #1030
2 parents c53d261 + 9b6d990 commit 27387c2

File tree

14 files changed

+205
-24
lines changed

14 files changed

+205
-24
lines changed
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/* eslint react/prop-types: 0 */
2+
import React from 'react';
3+
4+
import BootstrapTable from 'react-bootstrap-table-next';
5+
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
6+
import ToolkitProvider, { ColumnToggle } from 'react-bootstrap-table2-toolkit';
7+
import Code from 'components/common/code-block';
8+
import { productsGenerator } from 'utils/common';
9+
10+
const { ToggleList } = ColumnToggle;
11+
const products = productsGenerator();
12+
13+
const columns = [{
14+
dataField: 'id',
15+
text: 'Product ID'
16+
}, {
17+
dataField: 'name',
18+
text: 'Product Name',
19+
sort: true,
20+
filter: textFilter()
21+
}, {
22+
dataField: 'price',
23+
text: 'Product Price',
24+
sort: true,
25+
filter: textFilter()
26+
}];
27+
28+
const sourceCode = `\
29+
import BootstrapTable from 'react-bootstrap-table-next';
30+
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
31+
import ToolkitProvider, { ColumnToggle } from 'react-bootstrap-table2-toolkit';
32+
33+
const { ToggleList } = ColumnToggle;
34+
const columns = [{
35+
dataField: 'id',
36+
text: 'Product ID'
37+
}, {
38+
dataField: 'name',
39+
text: 'Product Name',
40+
sort: true,
41+
filter: textFilter()
42+
}, {
43+
dataField: 'price',
44+
text: 'Product Price',
45+
sort: true,
46+
filter: textFilter()
47+
}];
48+
49+
<ToolkitProvider
50+
keyField="id"
51+
data={ products }
52+
columns={ columns }
53+
columnToggle
54+
>
55+
{
56+
props => (
57+
<div>
58+
<ToggleList { ...props.columnToggleProps } />
59+
<hr />
60+
<BootstrapTable
61+
{ ...props.baseProps }
62+
filter={ filterFactory() }
63+
/>
64+
</div>
65+
)
66+
}
67+
</ToolkitProvider>
68+
`;
69+
70+
export default () => (
71+
<div>
72+
<h3>Table will keep the filter/sort state when column toggle</h3>
73+
<ToolkitProvider
74+
keyField="id"
75+
data={ products }
76+
columns={ columns }
77+
columnToggle
78+
>
79+
{
80+
props => (
81+
<div>
82+
<ToggleList { ...props.columnToggleProps } />
83+
<hr />
84+
<BootstrapTable
85+
{ ...props.baseProps }
86+
filter={ filterFactory() }
87+
/>
88+
</div>
89+
)
90+
}
91+
</ToolkitProvider>
92+
<Code>{ sourceCode }</Code>
93+
</div>
94+
);

packages/react-bootstrap-table2-example/stories/index.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ import BasicColumnToggle from 'examples/column-toggle';
210210
import DefaultVisibility from 'examples/column-toggle/default-visibility';
211211
import StylingColumnToggle from 'examples/column-toggle/styling-toggle-list';
212212
import CustomToggleList from 'examples/column-toggle/custom-toggle-list';
213+
import ColumnToggleWithFilter from 'examples/column-toggle/column-toggle-with-filter';
213214

214215
// loading overlay
215216
import EmptyTableOverlay from 'examples/loading-overlay/empty-table-overlay';
@@ -451,7 +452,8 @@ storiesOf('Column Toggle', module)
451452
.add('Basic Column Toggle', () => <BasicColumnToggle />)
452453
.add('Default Visibility', () => <DefaultVisibility />)
453454
.add('Styling Column Toggle', () => <StylingColumnToggle />)
454-
.add('Custom Column Toggle', () => <CustomToggleList />);
455+
.add('Custom Column Toggle', () => <CustomToggleList />)
456+
.add('Column Toggle with Filter', () => <ColumnToggleWithFilter />);
455457

456458
storiesOf('Export CSV', module)
457459
.addDecorator(bootstrapStyle())

packages/react-bootstrap-table2-filter/src/components/date.js

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -83,14 +83,27 @@ class DateFilter extends Component {
8383
return optionTags;
8484
}
8585

86+
getDefaultComparator() {
87+
const { defaultValue, filterState } = this.props;
88+
if (filterState && filterState.filterVal) {
89+
return filterState.filterVal.comparator;
90+
}
91+
if (defaultValue && defaultValue.comparator) {
92+
return defaultValue.comparator;
93+
}
94+
return '';
95+
}
96+
8697
getDefaultDate() {
87-
let defaultDate = '';
88-
const { defaultValue } = this.props;
98+
// Set the appropriate format for the input type=date, i.e. "YYYY-MM-DD"
99+
const { defaultValue, filterState } = this.props;
100+
if (filterState && filterState.filterVal && filterState.filterVal.date) {
101+
return dateParser(filterState.filterVal.date);
102+
}
89103
if (defaultValue && defaultValue.date) {
90-
// Set the appropriate format for the input type=date, i.e. "YYYY-MM-DD"
91-
defaultDate = dateParser(new Date(defaultValue.date));
104+
return dateParser(new Date(defaultValue.date));
92105
}
93-
return defaultDate;
106+
return '';
94107
}
95108

96109
applyFilter(value, comparator, isInitial) {
@@ -122,8 +135,7 @@ class DateFilter extends Component {
122135
dateStyle,
123136
className,
124137
comparatorClassName,
125-
dateClassName,
126-
defaultValue
138+
dateClassName
127139
} = this.props;
128140

129141
return (
@@ -143,7 +155,7 @@ class DateFilter extends Component {
143155
style={ comparatorStyle }
144156
className={ `date-filter-comparator form-control ${comparatorClassName}` }
145157
onChange={ this.onChangeComparator }
146-
defaultValue={ defaultValue ? defaultValue.comparator : '' }
158+
defaultValue={ this.getDefaultComparator() }
147159
>
148160
{ this.getComparatorOptions() }
149161
</select>
@@ -169,6 +181,7 @@ class DateFilter extends Component {
169181
DateFilter.propTypes = {
170182
onFilter: PropTypes.func.isRequired,
171183
column: PropTypes.object.isRequired,
184+
filterState: PropTypes.object,
172185
delay: PropTypes.number,
173186
defaultValue: PropTypes.shape({
174187
date: PropTypes.oneOfType([PropTypes.object]),
@@ -210,6 +223,7 @@ DateFilter.defaultProps = {
210223
date: undefined,
211224
comparator: ''
212225
},
226+
filterState: {},
213227
withoutEmptyComparatorOption: false,
214228
comparators: legalComparators,
215229
placeholder: undefined,

packages/react-bootstrap-table2-filter/src/components/multiselect.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,14 @@ class MultiSelectFilter extends Component {
6969
}
7070
}
7171

72+
getDefaultValue() {
73+
const { filterState, defaultValue } = this.props;
74+
if (filterState && typeof filterState.filterVal !== 'undefined') {
75+
return filterState.filterVal;
76+
}
77+
return defaultValue;
78+
}
79+
7280
getOptions() {
7381
const optionTags = [];
7482
const { options, placeholder, column, withoutEmptyOption } = this.props;
@@ -106,6 +114,7 @@ class MultiSelectFilter extends Component {
106114
const {
107115
style,
108116
className,
117+
filterState,
109118
defaultValue,
110119
onFilter,
111120
column,
@@ -135,7 +144,7 @@ class MultiSelectFilter extends Component {
135144
className={ selectClass }
136145
onChange={ this.filter }
137146
onClick={ e => e.stopPropagation() }
138-
defaultValue={ defaultValue !== undefined ? defaultValue : '' }
147+
defaultValue={ this.getDefaultValue() }
139148
>
140149
{ this.getOptions() }
141150
</select>
@@ -148,6 +157,7 @@ MultiSelectFilter.propTypes = {
148157
onFilter: PropTypes.func.isRequired,
149158
column: PropTypes.object.isRequired,
150159
options: PropTypes.object.isRequired,
160+
filterState: PropTypes.object,
151161
comparator: PropTypes.oneOf([LIKE, EQ]),
152162
placeholder: PropTypes.string,
153163
style: PropTypes.object,
@@ -160,6 +170,7 @@ MultiSelectFilter.propTypes = {
160170

161171
MultiSelectFilter.defaultProps = {
162172
defaultValue: [],
173+
filterState: {},
163174
className: '',
164175
withoutEmptyOption: false,
165176
comparator: EQ,

packages/react-bootstrap-table2-filter/src/components/number.js

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,28 @@ class NumberFilter extends Component {
9494
onFilter(column, FILTER_TYPE.NUMBER)({ number: value, comparator });
9595
}
9696

97+
getDefaultComparator() {
98+
const { defaultValue, filterState } = this.props;
99+
if (filterState && filterState.filterVal) {
100+
return filterState.filterVal.comparator;
101+
}
102+
if (defaultValue && defaultValue.comparator) {
103+
return defaultValue.comparator;
104+
}
105+
return '';
106+
}
107+
108+
getDefaultValue() {
109+
const { defaultValue, filterState } = this.props;
110+
if (filterState && filterState.filterVal) {
111+
return filterState.filterVal.number;
112+
}
113+
if (defaultValue && defaultValue.number) {
114+
return defaultValue.number;
115+
}
116+
return '';
117+
}
118+
97119
getComparatorOptions() {
98120
const optionTags = [];
99121
const { withoutEmptyComparatorOption } = this.props;
@@ -148,7 +170,6 @@ class NumberFilter extends Component {
148170
render() {
149171
const { isSelected } = this.state;
150172
const {
151-
defaultValue,
152173
column,
153174
options,
154175
style,
@@ -184,7 +205,7 @@ class NumberFilter extends Component {
184205
id={ `number-filter-comparator-${column.text}` }
185206
className={ `number-filter-comparator form-control ${comparatorClassName}` }
186207
onChange={ this.onChangeComparator }
187-
defaultValue={ defaultValue ? defaultValue.comparator : '' }
208+
defaultValue={ this.getDefaultComparator() }
188209
>
189210
{ this.getComparatorOptions() }
190211
</select>
@@ -202,7 +223,7 @@ class NumberFilter extends Component {
202223
style={ numberStyle }
203224
className={ selectClass }
204225
onChange={ this.onChangeNumberSet }
205-
defaultValue={ defaultValue ? defaultValue.number : '' }
226+
defaultValue={ this.getDefaultValue() }
206227
>
207228
{ this.getNumberOptions() }
208229
</select>
@@ -217,7 +238,7 @@ class NumberFilter extends Component {
217238
className={ `number-filter-input form-control ${numberClassName}` }
218239
placeholder={ placeholder || `Enter ${column.text}...` }
219240
onChange={ this.onChangeNumber }
220-
defaultValue={ defaultValue ? defaultValue.number : '' }
241+
defaultValue={ this.getDefaultValue() }
221242
/>
222243
</label>
223244
}
@@ -229,6 +250,7 @@ class NumberFilter extends Component {
229250
NumberFilter.propTypes = {
230251
onFilter: PropTypes.func.isRequired,
231252
column: PropTypes.object.isRequired,
253+
filterState: PropTypes.object,
232254
options: PropTypes.arrayOf(PropTypes.number),
233255
defaultValue: PropTypes.shape({
234256
number: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
@@ -273,6 +295,7 @@ NumberFilter.defaultProps = {
273295
number: undefined,
274296
comparator: ''
275297
},
298+
filterState: {},
276299
withoutEmptyComparatorOption: false,
277300
withoutEmptyNumberOption: false,
278301
comparators: legalComparators,

packages/react-bootstrap-table2-filter/src/components/select.js

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class SelectFilter extends Component {
4444
constructor(props) {
4545
super(props);
4646
this.filter = this.filter.bind(this);
47-
const isSelected = getOptionValue(props.options, props.defaultValue) !== undefined;
47+
const isSelected = getOptionValue(props.options, this.getDefaultValue()) !== undefined;
4848
this.state = { isSelected };
4949
}
5050

@@ -82,6 +82,14 @@ class SelectFilter extends Component {
8282
}
8383
}
8484

85+
getDefaultValue() {
86+
const { filterState, defaultValue } = this.props;
87+
if (filterState && typeof filterState.filterVal !== 'undefined') {
88+
return filterState.filterVal;
89+
}
90+
return defaultValue;
91+
}
92+
8593
getOptions() {
8694
const optionTags = [];
8795
const { options, placeholder, column, withoutEmptyOption } = this.props;
@@ -132,6 +140,7 @@ class SelectFilter extends Component {
132140
withoutEmptyOption,
133141
caseSensitive,
134142
getFilter,
143+
filterState,
135144
...rest
136145
} = this.props;
137146

@@ -152,7 +161,7 @@ class SelectFilter extends Component {
152161
className={ selectClass }
153162
onChange={ this.filter }
154163
onClick={ e => e.stopPropagation() }
155-
defaultValue={ defaultValue !== undefined ? defaultValue : '' }
164+
defaultValue={ this.getDefaultValue() || '' }
156165
>
157166
{ this.getOptions() }
158167
</select>
@@ -164,6 +173,7 @@ class SelectFilter extends Component {
164173
SelectFilter.propTypes = {
165174
onFilter: PropTypes.func.isRequired,
166175
column: PropTypes.object.isRequired,
176+
filterState: PropTypes.object,
167177
options: PropTypes.oneOfType([PropTypes.object, PropTypes.array]).isRequired,
168178
comparator: PropTypes.oneOf([LIKE, EQ]),
169179
placeholder: PropTypes.string,
@@ -177,6 +187,7 @@ SelectFilter.propTypes = {
177187

178188
SelectFilter.defaultProps = {
179189
defaultValue: '',
190+
filterState: {},
180191
className: '',
181192
withoutEmptyOption: false,
182193
comparator: EQ,

0 commit comments

Comments
 (0)