Skip to content

Commit 30cad00

Browse files
committed
Merge branch 'feature#1031'
2 parents dd0f04f + dde877a commit 30cad00

File tree

8 files changed

+206
-49
lines changed

8 files changed

+206
-49
lines changed

dist/react-bootstrap-table.js

Lines changed: 84 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,7 @@ return /******/ (function(modules) { // webpackBootstrap
400400
keyField: keyField,
401401
colInfos: this.colInfos,
402402
multiColumnSearch: props.multiColumnSearch,
403+
strictSearch: props.strictSearch,
403404
multiColumnSort: props.multiColumnSort,
404405
remote: this.props.remote
405406
});
@@ -748,6 +749,7 @@ return /******/ (function(modules) { // webpackBootstrap
748749
withoutNoDataText: this.props.options.withoutNoDataText,
749750
expanding: this.state.expanding,
750751
onExpand: this.handleExpandRow,
752+
onlyOneExpanding: this.props.options.onlyOneExpanding,
751753
beforeShowError: this.props.options.beforeShowError,
752754
keyBoardNav: this.props.keyBoardNav,
753755
onNavigateCell: this.handleNavigateCell,
@@ -1452,6 +1454,7 @@ return /******/ (function(modules) { // webpackBootstrap
14521454
field: props.dataField,
14531455
hiddenOnInsert: props.hiddenOnInsert,
14541456
keyValidator: props.keyValidator,
1457+
customInsertEditor: props.customInsertEditor,
14551458
// when you want same auto generate value and not allow edit, example ID field
14561459
autoValue: props.autoValue || false,
14571460
// for create editor, no params for column.editable() indicate that editor for new row
@@ -1466,6 +1469,7 @@ return /******/ (function(modules) { // webpackBootstrap
14661469
name: children.props.headerText || children.props.children,
14671470
field: children.props.dataField,
14681471
editable: children.props.editable,
1472+
customInsertEditor: children.props.customInsertEditor,
14691473
hiddenOnInsert: children.props.hiddenOnInsert,
14701474
keyValidator: children.props.keyValidator
14711475
}];
@@ -1706,6 +1710,8 @@ return /******/ (function(modules) { // webpackBootstrap
17061710
insertRow: _react.PropTypes.bool,
17071711
deleteRow: _react.PropTypes.bool,
17081712
search: _react.PropTypes.bool,
1713+
multiColumnSearch: _react.PropTypes.bool,
1714+
strictSearch: _react.PropTypes.bool,
17091715
columnFilter: _react.PropTypes.bool,
17101716
trClassName: _react.PropTypes.any,
17111717
tableStyle: _react.PropTypes.object,
@@ -1789,6 +1795,7 @@ return /******/ (function(modules) { // webpackBootstrap
17891795
expandRowBgColor: _react.PropTypes.string,
17901796
expandBy: _react.PropTypes.string,
17911797
expanding: _react.PropTypes.array,
1798+
onlyOneExpanding: _react.PropTypes.bool,
17921799
beforeShowError: _react.PropTypes.func,
17931800
printToolBar: _react.PropTypes.bool
17941801
}),
@@ -1851,6 +1858,7 @@ return /******/ (function(modules) { // webpackBootstrap
18511858
deleteRow: false,
18521859
search: false,
18531860
multiColumnSearch: false,
1861+
strictSearch: undefined,
18541862
multiColumnSort: 1,
18551863
columnFilter: false,
18561864
trClassName: '',
@@ -1932,6 +1940,7 @@ return /******/ (function(modules) { // webpackBootstrap
19321940
expandRowBgColor: undefined,
19331941
expandBy: _Const2.default.EXPAND_BY_ROW,
19341942
expanding: [],
1943+
onlyOneExpanding: false,
19351944
beforeShowError: undefined,
19361945
printToolBar: true
19371946
},
@@ -2870,7 +2879,8 @@ return /******/ (function(modules) { // webpackBootstrap
28702879
keyField = _props4.keyField,
28712880
expandBy = _props4.expandBy,
28722881
expandableRow = _props4.expandableRow,
2873-
clickToExpand = _props4.selectRow.clickToExpand;
2882+
clickToExpand = _props4.selectRow.clickToExpand,
2883+
onlyOneExpanding = _props4.onlyOneExpanding;
28742884

28752885
var selectRowAndExpand = this._isSelectRowDefined() && !clickToExpand ? false : true;
28762886
columnIndex = this._isSelectRowDefined() ? columnIndex - 1 : columnIndex;
@@ -2887,7 +2897,7 @@ return /******/ (function(modules) { // webpackBootstrap
28872897
return k !== rowKey;
28882898
});
28892899
} else {
2890-
expanding.push(rowKey);
2900+
if (onlyOneExpanding) expanding = [rowKey];else expanding.push(rowKey);
28912901
}
28922902
_this2.props.onExpand(expanding);
28932903
})();
@@ -3083,6 +3093,7 @@ return /******/ (function(modules) { // webpackBootstrap
30833093
expandBy: _react.PropTypes.string,
30843094
expanding: _react.PropTypes.array,
30853095
onExpand: _react.PropTypes.func,
3096+
onlyOneExpanding: _react.PropTypes.bool,
30863097
beforeShowError: _react.PropTypes.func,
30873098
keyBoardNav: _react.PropTypes.oneOfType([_react.PropTypes.bool, _react.PropTypes.object]),
30883099
x: _react.PropTypes.number,
@@ -13571,6 +13582,8 @@ return /******/ (function(modules) { // webpackBootstrap
1357113582
if (column.editable && column.editable.type === 'checkbox') {
1357213583
var values = inputVal.split(':');
1357313584
inputVal = dom.checked ? values[0] : values[1];
13585+
} else if (column.customInsertEditor) {
13586+
inputVal = inputVal || dom.getFieldValue();
1357413587
}
1357513588
}
1357613589
newRow[column.field] = inputVal;
@@ -13594,12 +13607,22 @@ return /******/ (function(modules) { // webpackBootstrap
1359413607
field = column.field,
1359513608
name = column.name,
1359613609
autoValue = column.autoValue,
13597-
hiddenOnInsert = column.hiddenOnInsert;
13610+
hiddenOnInsert = column.hiddenOnInsert,
13611+
customInsertEditor = column.customInsertEditor;
1359813612

1359913613
var attr = {
1360013614
ref: field + i,
1360113615
placeholder: editable.placeholder ? editable.placeholder : name
1360213616
};
13617+
var fieldElement = void 0;
13618+
13619+
if (customInsertEditor) {
13620+
var getElement = customInsertEditor.getElement;
13621+
13622+
fieldElement = getElement(column, attr, 'form-control', ignoreEditable);
13623+
} else {
13624+
fieldElement = (0, _Editor2.default)(editable, attr, format, '', undefined, ignoreEditable);
13625+
}
1360313626

1360413627
if (autoValue || hiddenOnInsert || !column.field) {
1360513628
// when you want same auto generate value
@@ -13619,7 +13642,7 @@ return /******/ (function(modules) { // webpackBootstrap
1361913642
null,
1362013643
name
1362113644
),
13622-
(0, _Editor2.default)(editable, attr, format, '', undefined, ignoreEditable),
13645+
fieldElement,
1362313646
error
1362413647
);
1362513648
})
@@ -14491,18 +14514,14 @@ return /******/ (function(modules) { // webpackBootstrap
1449114514
};
1449214515

1449314516
this.data = data;
14494-
this.colInfos = null;
1449514517
this.filteredData = null;
1449614518
this.isOnFilter = false;
1449714519
this.filterObj = null;
1449814520
this.searchText = null;
1449914521
this.sortList = [];
1450014522
this.pageObj = {};
1450114523
this.selected = [];
14502-
this.multiColumnSearch = false;
14503-
this.multiColumnSort = 1;
1450414524
this.showOnlySelected = false;
14505-
this.remote = false; // remote data
1450614525
}
1450714526

1450814527
_createClass(TableDataStore, [{
@@ -14513,6 +14532,8 @@ return /******/ (function(modules) { // webpackBootstrap
1451314532
this.colInfos = props.colInfos;
1451414533
this.remote = props.remote;
1451514534
this.multiColumnSearch = props.multiColumnSearch;
14535+
// default behaviour if strictSearch prop is not provided: !multiColumnSearch
14536+
this.strictSearch = typeof props.strictSearch === 'undefined' ? !props.multiColumnSearch : props.strictSearch;
1451614537
this.multiColumnSort = props.multiColumnSort;
1451714538
}
1451814539
}, {
@@ -15077,57 +15098,82 @@ return /******/ (function(modules) { // webpackBootstrap
1507715098
});
1507815099
this.isOnFilter = true;
1507915100
}
15101+
15102+
/*
15103+
* Four different sort modes, all case insensitive:
15104+
* (1) strictSearch && !multiColumnSearch
15105+
* search text must be contained as provided in a single column
15106+
* (2) strictSearch && multiColumnSearch
15107+
* conjunction (AND combination) of whitespace separated terms over multiple columns
15108+
* (3) !strictSearch && !multiColumnSearch
15109+
* conjunction (AND combination) of whitespace separated terms in a single column
15110+
* (4) !strictSearch && multiColumnSearch
15111+
* any of the whitespace separated terms must be contained in any column
15112+
*/
15113+
1508015114
}, {
1508115115
key: '_search',
1508215116
value: function _search(source) {
1508315117
var _this7 = this;
1508415118

15085-
var searchTextArray = [];
15086-
15087-
if (this.multiColumnSearch) {
15088-
searchTextArray = this.searchText.split(' ');
15119+
var searchTextArray = void 0;
15120+
if (this.multiColumnSearch || !this.strictSearch) {
15121+
// ignore leading and trailing whitespaces
15122+
searchTextArray = this.searchText.trim().toLowerCase().split(/\s+/);
1508915123
} else {
15090-
searchTextArray.push(this.searchText);
15124+
searchTextArray = [this.searchText.toLowerCase()];
1509115125
}
15126+
var searchTermCount = searchTextArray.length;
15127+
var multipleTerms = searchTermCount > 1;
15128+
var nonStrictMultiCol = multipleTerms && !this.strictSearch && this.multiColumnSearch;
15129+
var nonStrictSingleCol = multipleTerms && !this.strictSearch && !this.multiColumnSearch;
1509215130
this.filteredData = source.filter(function (row, r) {
1509315131
var keys = Object.keys(row);
15094-
var valid = false;
15132+
// only clone array if necessary
15133+
var searchTerms = multipleTerms ? searchTextArray.slice() : searchTextArray;
1509515134
// for loops are ugly, but performance matters here.
1509615135
// And you cant break from a forEach.
1509715136
// http://jsperf.com/for-vs-foreach/66
1509815137
for (var i = 0, keysLength = keys.length; i < keysLength; i++) {
1509915138
var key = keys[i];
15100-
// fixed data filter when misunderstand 0 is false
15101-
var filterSpecialNum = false;
15102-
if (!isNaN(row[key]) && parseInt(row[key], 10) === 0) {
15103-
filterSpecialNum = true;
15104-
}
15105-
if (_this7.colInfos[key] && (row[key] || filterSpecialNum)) {
15106-
var _colInfos$key = _this7.colInfos[key],
15107-
format = _colInfos$key.format,
15108-
filterFormatted = _colInfos$key.filterFormatted,
15109-
filterValue = _colInfos$key.filterValue,
15110-
formatExtraData = _colInfos$key.formatExtraData,
15111-
searchable = _colInfos$key.searchable;
15112-
15113-
var targetVal = row[key];
15114-
if (searchable) {
15115-
if (filterFormatted && format) {
15116-
targetVal = format(targetVal, row, formatExtraData, r);
15117-
} else if (filterValue) {
15118-
targetVal = filterValue(targetVal, row);
15139+
var colInfo = _this7.colInfos[key];
15140+
if (colInfo && colInfo.searchable) {
15141+
var format = colInfo.format,
15142+
filterFormatted = colInfo.filterFormatted,
15143+
filterValue = colInfo.filterValue,
15144+
formatExtraData = colInfo.formatExtraData;
15145+
15146+
var targetVal = void 0;
15147+
if (filterFormatted && format) {
15148+
targetVal = format(row[key], row, formatExtraData, r);
15149+
} else if (filterValue) {
15150+
targetVal = filterValue(row[key], row);
15151+
} else {
15152+
targetVal = row[key];
15153+
}
15154+
if (targetVal !== null && typeof targetVal !== 'undefined') {
15155+
targetVal = targetVal.toString().toLowerCase();
15156+
if (nonStrictSingleCol && searchTermCount > searchTerms.length) {
15157+
// reset search terms for single column search
15158+
searchTerms = searchTextArray.slice();
1511915159
}
15120-
for (var j = 0, textLength = searchTextArray.length; j < textLength; j++) {
15121-
var filterVal = searchTextArray[j].toLowerCase();
15122-
if (targetVal.toString().toLowerCase().indexOf(filterVal) !== -1) {
15123-
valid = true;
15160+
for (var j = searchTerms.length - 1; j > -1; j--) {
15161+
if (targetVal.indexOf(searchTerms[j]) !== -1) {
15162+
if (nonStrictMultiCol || searchTerms.length === 1) {
15163+
// match found: the last or only one
15164+
return true;
15165+
}
15166+
// match found: but there are more search terms to check for
15167+
searchTerms.splice(j, 1);
15168+
} else if (!_this7.multiColumnSearch) {
15169+
// one of the search terms was not found in this column
1512415170
break;
1512515171
}
1512615172
}
1512715173
}
1512815174
}
1512915175
}
15130-
return valid;
15176+
return false;
1513115177
});
1513215178
this.isOnFilter = true;
1513315179
}

dist/react-bootstrap-table.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/react-bootstrap-table.min.js

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

examples/js/custom/demo.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import FullyCustomInsertModalHeaderTable from './insert-modal/fully-custom-inser
77
import DefaultCustomInsertModalFooterTable from './insert-modal/default-custom-insert-modal-footer';
88
import FullyCustomInsertModalFooterTable from './insert-modal/fully-custom-insert-modal-footer';
99
import CustomInsertModalBodyTable from './insert-modal/custom-insert-modal-body';
10+
import CustomInsertModalFieldTable from './insert-modal/custom-insert-modal-field';
1011
import CustomInsertModalTable from './insert-modal/custom-insert-modal';
1112
import DefaultCustomInsertButtonTable from './insert-button/default-custom-insert-button';
1213
import FullyCustomInsertButtonTable from './insert-button/fully-custom-insert-button';
@@ -55,6 +56,10 @@ class Demo extends React.Component {
5556
{ renderLinks('custom/insert-modal/custom-insert-modal-body.js') }
5657
<CustomInsertModalBodyTable/>
5758
</Panel>
59+
<Panel header={ 'Custom for Insert Modal Field Demo' }>
60+
{ renderLinks('custom/insert-modal/custom-insert-modal-field.js') }
61+
<CustomInsertModalFieldTable/>
62+
</Panel>
5863
<Panel header={ 'Custom for Insert Modal Demo' }>
5964
{ renderLinks('custom/insert-modal/custom-insert-modal.js') }
6065
<CustomInsertModalTable/>
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/* eslint max-len: 0 */
2+
/* eslint no-unused-vars: 0 */
3+
/* eslint no-alert: 0 */
4+
import React from 'react';
5+
import ReactDOM from 'react-dom';
6+
import { BootstrapTable, TableHeaderColumn } from 'react-bootstrap-table';
7+
8+
9+
const products = [];
10+
const fruits = [ 'banana', 'apple', 'orange', 'tomato', 'strawberries' ];
11+
function addProducts(quantity) {
12+
const startId = products.length;
13+
for (let i = 0; i < quantity; i++) {
14+
const id = startId + i;
15+
products.push({
16+
id: id,
17+
name: fruits[i],
18+
sales: i % 2 ? 'Yes' : 'No',
19+
price: 100 + i
20+
});
21+
}
22+
}
23+
24+
addProducts(5);
25+
26+
class SalesRadioField extends React.Component {
27+
28+
getFieldValue = () => {
29+
return this.refs.yes.checked ? 'Yes' : 'No';
30+
}
31+
32+
render() {
33+
return (
34+
<div>
35+
<label className='radio-inline'>
36+
<input ref='yes' type='radio' name='optradio' value='Yes'/>Yes
37+
</label>
38+
<label className='radio-inline'>
39+
<input ref='no' type='radio' name='optradio' value='No'/>No
40+
</label>
41+
</div>
42+
);
43+
}
44+
}
45+
46+
export default class CustomInsertModalFieldTable extends React.Component {
47+
48+
customKeyField = (column, attr, editorClass, ignoreEditable) => {
49+
const seqId = this.refs.table.state.data.length;
50+
return (
51+
<input type='text' { ...attr } disabled value={ seqId } className={ `${editorClass}` }/>
52+
);
53+
}
54+
55+
customNameField = (column, attr, editorClass, ignoreEditable) => {
56+
return (
57+
<select className={ `${editorClass}` } { ...attr }>
58+
{
59+
fruits.map(name => (<option key={ name } value={ name }>{ name }</option>))
60+
}
61+
</select>
62+
);
63+
}
64+
65+
customSaleField = (column, attr, editorClass, ignoreEditable) => {
66+
/*
67+
Sometime, your field is not only a HTML element, like radio, checkbox etc.
68+
In this case, you are suppose to be prodived a specific method name for
69+
react-bootstrap-table to get the value for this field.
70+
71+
Notes:
72+
1. You are suppose to be added ref to your custom React class
73+
2. You are suppose to be implement getFieldValue function and return the value that user input
74+
*/
75+
return (
76+
<SalesRadioField ref={ attr.ref } editorClass={ editorClass } ignoreEditable={ ignoreEditable }/>
77+
);
78+
}
79+
80+
render() {
81+
const options = {
82+
insertModalField: this.createCustomModalField
83+
};
84+
return (
85+
<BootstrapTable ref='table' data={ products } options={ options } insertRow>
86+
<TableHeaderColumn dataField='id' isKey={ true } customInsertEditor={ { getElement: this.customKeyField } }>Product ID</TableHeaderColumn>
87+
<TableHeaderColumn dataField='name' customInsertEditor={ { getElement: this.customNameField } }>Product Name</TableHeaderColumn>
88+
<TableHeaderColumn dataField='sales' customInsertEditor={ { getElement: this.customSaleField } }>On Sales?</TableHeaderColumn>
89+
<TableHeaderColumn dataField='price'>Product Price</TableHeaderColumn>
90+
</BootstrapTable>
91+
);
92+
}
93+
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-bootstrap-table",
3-
"version": "3.1.8",
3+
"version": "3.2.0",
44
"description": "It's a react table for bootstrap",
55
"main": "./lib/index.js",
66
"repository": {

0 commit comments

Comments
 (0)