Skip to content
This repository was archived by the owner on Jan 15, 2022. It is now read-only.

Commit eba3c42

Browse files
committed
Allow to filter by column: value
This Branch improves the way filterBy workes, by allowing it to be set with and hash like {'Column': 'search query'} programatically. Another improvement, that still needs to be touched is the ability to do the same from the search box in a form of 'Column: search query' that will be split by the ':' and use each side as column to filter, and value.
1 parent 0acc184 commit eba3c42

File tree

8 files changed

+620
-2514
lines changed

8 files changed

+620
-2514
lines changed

Gruntfile.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,4 +131,3 @@ module.exports = function(grunt) {
131131
grunt.registerTask('build', ['babel:common', 'buildBrowser']);
132132
grunt.registerTask('default', ['build', 'watch:build']);
133133
};
134-

build/reactable.js

Lines changed: 177 additions & 88 deletions
Large diffs are not rendered by default.

build/tests/reactable_test.js

Lines changed: 23 additions & 2336 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/reactable/filterer.js

Lines changed: 74 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use strict';
22

33
Object.defineProperty(exports, '__esModule', {
4-
value: true
4+
value: true
55
});
66

77
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
@@ -23,68 +23,91 @@ var _reactDom = require('react-dom');
2323
var _reactDom2 = _interopRequireDefault(_reactDom);
2424

2525
var FiltererInput = (function (_React$Component) {
26-
_inherits(FiltererInput, _React$Component);
27-
28-
function FiltererInput() {
29-
_classCallCheck(this, FiltererInput);
30-
31-
_get(Object.getPrototypeOf(FiltererInput.prototype), 'constructor', this).apply(this, arguments);
26+
_inherits(FiltererInput, _React$Component);
27+
28+
function FiltererInput() {
29+
_classCallCheck(this, FiltererInput);
30+
31+
_get(Object.getPrototypeOf(FiltererInput.prototype), 'constructor', this).apply(this, arguments);
32+
}
33+
34+
_createClass(FiltererInput, [{
35+
key: 'onChange',
36+
value: function onChange(e) {
37+
if (e && e.keyCode && e.keyCode == 13) {
38+
this.props.onFilter(_reactDom2['default'].findDOMNode(this).value, true);
39+
} else {
40+
this.props.onFilter(_reactDom2['default'].findDOMNode(this).value, false);
41+
}
3242
}
33-
34-
_createClass(FiltererInput, [{
35-
key: 'onChange',
36-
value: function onChange() {
37-
this.props.onFilter(_reactDom2['default'].findDOMNode(this).value);
43+
}, {
44+
key: 'render',
45+
value: function render() {
46+
var value = '';
47+
if (typeof this.props.value != 'string') {
48+
var should_slice = false;
49+
for (var key in this.props.value) {
50+
if (key && this.props.value[key]) {
51+
should_slice = true;
52+
value += ' ' + key + ': ' + this.props.value[key] + ',';
53+
} else {
54+
value += key + ': ';
55+
}
3856
}
39-
}, {
40-
key: 'render',
41-
value: function render() {
42-
return _react2['default'].createElement('input', { type: 'text',
43-
className: 'reactable-filter-input',
44-
placeholder: this.props.placeholder,
45-
value: this.props.value,
46-
onKeyUp: this.onChange.bind(this),
47-
onChange: this.onChange.bind(this) });
57+
if (value.slice(-1) == ',') {
58+
value = value.slice(0, -1);
4859
}
49-
}]);
60+
value = value.trimLeft();
61+
} else {
62+
value = this.props.value;
63+
}
64+
65+
return _react2['default'].createElement('input', { type: 'text',
66+
className: 'reactable-filter-input',
67+
placeholder: this.props.placeholder,
68+
value: value,
69+
onKeyUp: this.onChange.bind(this),
70+
onChange: this.onChange.bind(this) });
71+
}
72+
}]);
5073

51-
return FiltererInput;
74+
return FiltererInput;
5275
})(_react2['default'].Component);
5376

5477
exports.FiltererInput = FiltererInput;
5578
;
5679

5780
var Filterer = (function (_React$Component2) {
58-
_inherits(Filterer, _React$Component2);
59-
60-
function Filterer() {
61-
_classCallCheck(this, Filterer);
62-
63-
_get(Object.getPrototypeOf(Filterer.prototype), 'constructor', this).apply(this, arguments);
81+
_inherits(Filterer, _React$Component2);
82+
83+
function Filterer() {
84+
_classCallCheck(this, Filterer);
85+
86+
_get(Object.getPrototypeOf(Filterer.prototype), 'constructor', this).apply(this, arguments);
87+
}
88+
89+
_createClass(Filterer, [{
90+
key: 'render',
91+
value: function render() {
92+
if (typeof this.props.colSpan === 'undefined') {
93+
throw new TypeError('Must pass a colSpan argument to Filterer');
94+
}
95+
96+
return _react2['default'].createElement(
97+
'tr',
98+
{ className: 'reactable-filterer' },
99+
_react2['default'].createElement(
100+
'td',
101+
{ colSpan: this.props.colSpan },
102+
_react2['default'].createElement(FiltererInput, { onFilter: this.props.onFilter,
103+
value: this.props.value,
104+
placeholder: this.props.placeholder })
105+
)
106+
);
64107
}
108+
}]);
65109

66-
_createClass(Filterer, [{
67-
key: 'render',
68-
value: function render() {
69-
if (typeof this.props.colSpan === 'undefined') {
70-
throw new TypeError('Must pass a colSpan argument to Filterer');
71-
}
72-
73-
return _react2['default'].createElement(
74-
'tr',
75-
{ className: 'reactable-filterer' },
76-
_react2['default'].createElement(
77-
'td',
78-
{ colSpan: this.props.colSpan },
79-
_react2['default'].createElement(FiltererInput, { onFilter: this.props.onFilter,
80-
value: this.props.value,
81-
placeholder: this.props.placeholder })
82-
)
83-
);
84-
}
85-
}]);
86-
87-
return Filterer;
110+
return Filterer;
88111
})(_react2['default'].Component);
89112

90113
exports.Filterer = Filterer;

lib/reactable/table.js

Lines changed: 83 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -257,24 +257,92 @@ var Table = (function (_React$Component) {
257257
}, {
258258
key: 'applyFilter',
259259
value: function applyFilter(filter, children) {
260-
// Helper function to apply filter text to a list of table rows
261-
filter = filter.toLowerCase();
262-
var matchedChildren = [];
260+
if (typeof filter === 'string') {
261+
// Helper function to apply filter text to a list of table rows
262+
filter = filter.toLowerCase();
263+
var matchedChildren = [];
263264

264-
for (var i = 0; i < children.length; i++) {
265-
var data = children[i].props.data;
265+
for (var i = 0; i < children.length; i++) {
266+
var data = children[i].props.data;
266267

267-
for (var j = 0; j < this.props.filterable.length; j++) {
268-
var filterColumn = this.props.filterable[j];
268+
for (var j = 0; j < this.props.filterable.length; j++) {
269+
var filterColumn = this.props.filterable[j];
269270

270-
if (typeof data[filterColumn] !== 'undefined' && (0, _libExtract_data_from.extractDataFrom)(data, filterColumn).toString().toLowerCase().indexOf(filter) > -1) {
271-
matchedChildren.push(children[i]);
272-
break;
271+
if (typeof data[filterColumn] !== 'undefined' && (0, _libExtract_data_from.extractDataFrom)(data, filterColumn).toString().toLowerCase().indexOf(filter) > -1) {
272+
matchedChildren.push(children[i]);
273+
break;
274+
}
273275
}
274276
}
277+
278+
return matchedChildren;
279+
} else {
280+
var _ret = (function () {
281+
282+
var filterCount = Object.keys(filter).length;
283+
var matchedChildren = [];
284+
285+
for (var filterColumn in filter) {
286+
var val = filter[filterColumn].toLowerCase();
287+
for (var i = 0; i < children.length; i++) {
288+
var data = children[i].props.data;
289+
if (typeof data[filterColumn] !== 'undefined' && (0, _libExtract_data_from.extractDataFrom)(data, filterColumn).toString().toLowerCase().indexOf(val) > -1) {
290+
matchedChildren.push(children[i]);
291+
}
292+
}
293+
}
294+
295+
if (filterCount > 1) {
296+
var result = [];
297+
return {
298+
v: matchedChildren.map(function (children) {
299+
var occurrences = matchedChildren.filter(function (value) {
300+
return value.key === children.key;
301+
}).length;
302+
if (occurrences == filterCount) {
303+
return children;
304+
}
305+
})
306+
};
307+
} else {
308+
return {
309+
v: matchedChildren
310+
};
311+
}
312+
})();
313+
314+
if (typeof _ret === 'object') return _ret.v;
275315
}
316+
}
317+
}, {
318+
key: 'onFilter',
319+
value: function onFilter(filters, enterKey) {
320+
var _this = this;
276321

277-
return matchedChildren;
322+
var input = undefined;
323+
var filterObj = {};
324+
if (typeof filters === 'string' && filters.indexOf(':') != -1 && enterKey) {
325+
(function () {
326+
input = filters.trim();
327+
var col = undefined,
328+
val = undefined;
329+
var splitFilters = input.split(',');
330+
splitFilters.forEach(function (f) {
331+
var filter = f.split(':');
332+
333+
if (filter[0]) {
334+
col = filter[0].trim();
335+
}
336+
if (filter[1]) {
337+
val = filter[1].trim();
338+
}
339+
filterObj[col] = val;
340+
});
341+
_this.setState({ filter: filterObj });
342+
})();
343+
} else {
344+
this.setState({ filter: filters });
345+
}
278346
}
279347
}, {
280348
key: 'sortByCurrentSort',
@@ -337,14 +405,14 @@ var Table = (function (_React$Component) {
337405
this.setState({ currentSort: currentSort });
338406
this.sortByCurrentSort();
339407

340-
if (this.props.onSort) {
408+
if (typeof this.props.onSort === 'function') {
341409
this.props.onSort(currentSort);
342410
}
343411
}
344412
}, {
345413
key: 'render',
346414
value: function render() {
347-
var _this = this;
415+
var _this2 = this;
348416

349417
var children = [];
350418
var columns = undefined;
@@ -463,9 +531,7 @@ var Table = (function (_React$Component) {
463531
props,
464532
columns && columns.length > 0 ? _react2['default'].createElement(_thead.Thead, { columns: columns,
465533
filtering: filtering,
466-
onFilter: function (filter) {
467-
_this.setState({ filter: filter });
468-
},
534+
onFilter: this.onFilter.bind(this),
469535
filterPlaceholder: this.props.filterPlaceholder,
470536
currentFilter: this.state.filter,
471537
sort: this.state.currentSort,
@@ -482,7 +548,7 @@ var Table = (function (_React$Component) {
482548
numPages: numPages,
483549
currentPage: currentPage,
484550
onPageChange: function (page) {
485-
_this.setState({ currentPage: page });
551+
_this2.setState({ currentPage: page });
486552
},
487553
key: 'paginator' }) : null,
488554
this.tfoot

src/reactable/filterer.jsx

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,40 @@ import React from 'react';
22
import ReactDOM from 'react-dom';
33

44
export class FiltererInput extends React.Component {
5-
onChange() {
6-
this.props.onFilter(ReactDOM.findDOMNode(this).value);
5+
6+
onChange(e) {
7+
if ( e && e.keyCode && e.keyCode == 13 ) {
8+
this.props.onFilter(ReactDOM.findDOMNode(this).value, true)
9+
} else{
10+
this.props.onFilter(ReactDOM.findDOMNode(this).value, false)
11+
}
712
}
813

914
render() {
15+
let value = ''
16+
if (typeof(this.props.value) != 'string') {
17+
let should_slice = false
18+
for(let key in this.props.value) {
19+
if(key && this.props.value[key]) {
20+
should_slice = true
21+
value += ' ' + key + ': ' + this.props.value[key] + ','
22+
} else {
23+
value += key + ': '
24+
}
25+
}
26+
if (value.slice(-1) == ',') {
27+
value = value.slice(0, -1)
28+
}
29+
value = value.trimLeft()
30+
} else {
31+
value = this.props.value
32+
}
33+
1034
return (
1135
<input type="text"
1236
className="reactable-filter-input"
1337
placeholder={this.props.placeholder}
14-
value={this.props.value}
38+
value={value}
1539
onKeyUp={this.onChange.bind(this)}
1640
onChange={this.onChange.bind(this)} />
1741
);
@@ -35,4 +59,3 @@ export class Filterer extends React.Component {
3559
);
3660
}
3761
};
38-

0 commit comments

Comments
 (0)