mirror of
https://github.com/gosticks/react-bootstrap-table2.git
synced 2026-06-29 13:40:07 +00:00
Compare commits
12 Commits
react-boot
...
react-boot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
258ea43225 | ||
|
|
7a7b708029 | ||
|
|
0cf89861af | ||
|
|
eb74625835 | ||
|
|
cbaec4c655 | ||
|
|
04c21cb63d | ||
|
|
7d72002b6e | ||
|
|
279cc25da0 | ||
|
|
1152bb8440 | ||
|
|
88befb8136 | ||
|
|
42c6bc0337 | ||
|
|
6e753bb955 |
@@ -82,7 +82,7 @@ Please see [available filter configuration](https://react-bootstrap-table.github
|
|||||||
- [x] Text Filter
|
- [x] Text Filter
|
||||||
- [x] Custom Text Filter
|
- [x] Custom Text Filter
|
||||||
- [x] Remote Filter
|
- [x] Remote Filter
|
||||||
- [ ] Custom Filter Component
|
- [x] Custom Filter Component
|
||||||
- [ ] Regex Filter
|
- [ ] Regex Filter
|
||||||
- [x] Select Filter
|
- [x] Select Filter
|
||||||
- [x] Custom Select Filter
|
- [x] Custom Select Filter
|
||||||
|
|||||||
184
packages/react-bootstrap-table2-example/examples/column-filter/advance-custom-filter.js
vendored
Normal file
184
packages/react-bootstrap-table2-example/examples/column-filter/advance-custom-filter.js
vendored
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
/* eslint no-return-assign: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import filterFactory, { textFilter, customFilter, Comparator, FILTER_TYPES } from 'react-bootstrap-table2-filter';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const products = productsGenerator(8);
|
||||||
|
|
||||||
|
class PriceFilter extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
column: PropTypes.object.isRequired,
|
||||||
|
onFilter: PropTypes.func.isRequired
|
||||||
|
}
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.filter = this.filter.bind(this);
|
||||||
|
this.getValue = this.getValue.bind(this);
|
||||||
|
this.onChange = this.onChange.bind(this);
|
||||||
|
this.state = { value: 2100 };
|
||||||
|
}
|
||||||
|
onChange(e) {
|
||||||
|
this.setState({ value: e.target.value });
|
||||||
|
}
|
||||||
|
getValue() {
|
||||||
|
return parseInt(this.range.value, 10);
|
||||||
|
}
|
||||||
|
filter() {
|
||||||
|
this.props.onFilter({
|
||||||
|
number: this.getValue(),
|
||||||
|
comparator: this.select.value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
return [
|
||||||
|
<input
|
||||||
|
key="range"
|
||||||
|
ref={ node => this.range = node }
|
||||||
|
type="range"
|
||||||
|
min="2100"
|
||||||
|
max="2110"
|
||||||
|
onChange={ this.onChange }
|
||||||
|
/>,
|
||||||
|
<p
|
||||||
|
key="show"
|
||||||
|
ref={ node => this.showValue = node }
|
||||||
|
style={ { textAlign: 'center' } }
|
||||||
|
>
|
||||||
|
{ this.state.value }
|
||||||
|
</p>,
|
||||||
|
<select
|
||||||
|
key="select"
|
||||||
|
ref={ node => this.select = node }
|
||||||
|
className="form-control"
|
||||||
|
>
|
||||||
|
<option value={ Comparator.GT }>></option>
|
||||||
|
<option value={ Comparator.EQ }>=</option>
|
||||||
|
<option value={ Comparator.LT }><</option>
|
||||||
|
</select>,
|
||||||
|
<button
|
||||||
|
key="submit"
|
||||||
|
className="btn btn-warning"
|
||||||
|
onClick={ this.filter }
|
||||||
|
>
|
||||||
|
{ `Filter ${this.props.column.text}` }
|
||||||
|
</button>
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
filter: textFilter()
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
filter: customFilter({
|
||||||
|
type: FILTER_TYPES.NUMBER // ask react-bootstrap-table to filter data as number
|
||||||
|
}),
|
||||||
|
filterRenderer: (onFilter, column) =>
|
||||||
|
<PriceFilter onFilter={ onFilter } column={ column } />
|
||||||
|
}];
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import filterFactory, { textFilter, customFilter, Comparator, FILTER_TYPES } from 'react-bootstrap-table2-filter';
|
||||||
|
|
||||||
|
class PriceFilter extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
column: PropTypes.object.isRequired,
|
||||||
|
onFilter: PropTypes.func.isRequired
|
||||||
|
}
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.filter = this.filter.bind(this);
|
||||||
|
this.getValue = this.getValue.bind(this);
|
||||||
|
this.onChange = this.onChange.bind(this);
|
||||||
|
this.state = { value: 2100 };
|
||||||
|
}
|
||||||
|
onChange(e) {
|
||||||
|
this.setState({ value: e.target.value });
|
||||||
|
}
|
||||||
|
getValue() {
|
||||||
|
return parseInt(this.range.value, 10);
|
||||||
|
}
|
||||||
|
filter() {
|
||||||
|
this.props.onFilter({
|
||||||
|
number: this.getValue(),
|
||||||
|
comparator: this.select.value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
return [
|
||||||
|
<input
|
||||||
|
key="range"
|
||||||
|
ref={ node => this.range = node }
|
||||||
|
type="range"
|
||||||
|
min="2100"
|
||||||
|
max="2110"
|
||||||
|
onChange={ this.onChange }
|
||||||
|
/>,
|
||||||
|
<p
|
||||||
|
key="show"
|
||||||
|
ref={ node => this.showValue = node }
|
||||||
|
style={ { textAlign: 'center' } }
|
||||||
|
>
|
||||||
|
{ this.state.value }
|
||||||
|
</p>,
|
||||||
|
<select
|
||||||
|
key="select"
|
||||||
|
ref={ node => this.select = node }
|
||||||
|
className="form-control"
|
||||||
|
>
|
||||||
|
<option value={ Comparator.GT }>></option>
|
||||||
|
<option value={ Comparator.EQ }>=</option>
|
||||||
|
<option value={ Comparator.LT }><</option>
|
||||||
|
</select>,
|
||||||
|
<button
|
||||||
|
key="submit"
|
||||||
|
className="btn btn-warning"
|
||||||
|
onClick={ this.filter }
|
||||||
|
>
|
||||||
|
{ \`Filter $\{this.props.column.text}\` }
|
||||||
|
</button>
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
filter: textFilter()
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
filter: customFilter({
|
||||||
|
type: FILTER_TYPES.NUMBER // ask react-bootstrap-table to filter data as number
|
||||||
|
}),
|
||||||
|
filterRenderer: (onFilter, column) =>
|
||||||
|
<PriceFilter onFilter={ onFilter } column={ column } />
|
||||||
|
}];
|
||||||
|
|
||||||
|
<BootstrapTable keyField='id' data={ products } columns={ columns } filter={ filterFactory() } />
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
filter={ filterFactory() }
|
||||||
|
/>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
128
packages/react-bootstrap-table2-example/examples/column-filter/custom-filter.js
vendored
Normal file
128
packages/react-bootstrap-table2-example/examples/column-filter/custom-filter.js
vendored
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
/* eslint no-return-assign: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import filterFactory, { textFilter, customFilter } from 'react-bootstrap-table2-filter';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const products = productsGenerator(8);
|
||||||
|
|
||||||
|
class PriceFilter extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
column: PropTypes.object.isRequired,
|
||||||
|
onFilter: PropTypes.func.isRequired
|
||||||
|
}
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.filter = this.filter.bind(this);
|
||||||
|
this.getValue = this.getValue.bind(this);
|
||||||
|
}
|
||||||
|
getValue() {
|
||||||
|
return this.input.value;
|
||||||
|
}
|
||||||
|
filter() {
|
||||||
|
this.props.onFilter(this.getValue());
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
return [
|
||||||
|
<input
|
||||||
|
key="input"
|
||||||
|
ref={ node => this.input = node }
|
||||||
|
type="text"
|
||||||
|
placeholder="Input price"
|
||||||
|
/>,
|
||||||
|
<button
|
||||||
|
key="submit"
|
||||||
|
className="btn btn-warning"
|
||||||
|
onClick={ this.filter }
|
||||||
|
>
|
||||||
|
{ `Find ${this.props.column.text}` }
|
||||||
|
</button>
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
filter: textFilter()
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
filter: customFilter(),
|
||||||
|
filterRenderer: (onFilter, column) =>
|
||||||
|
<PriceFilter onFilter={ onFilter } column={ column } />
|
||||||
|
}];
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import filterFactory, { textFilter, customFilter } from 'react-bootstrap-table2-filter';
|
||||||
|
|
||||||
|
class PriceFilter extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
column: PropTypes.object.isRequired,
|
||||||
|
onFilter: PropTypes.func.isRequired
|
||||||
|
}
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.filter = this.filter.bind(this);
|
||||||
|
this.getValue = this.getValue.bind(this);
|
||||||
|
}
|
||||||
|
getValue() {
|
||||||
|
return this.input.value;
|
||||||
|
}
|
||||||
|
filter() {
|
||||||
|
this.props.onFilter(this.getValue());
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
return [
|
||||||
|
<input
|
||||||
|
key="input"
|
||||||
|
ref={ node => this.input = node }
|
||||||
|
type="text"
|
||||||
|
placeholder="Input price"
|
||||||
|
/>,
|
||||||
|
<button
|
||||||
|
key="submit"
|
||||||
|
className="btn btn-warning"
|
||||||
|
onClick={ this.filter }
|
||||||
|
>
|
||||||
|
{ \`Filter $\{this.props.column.text}\` }
|
||||||
|
</button>
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
filter: textFilter()
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
filter: customFilter(),
|
||||||
|
filterRenderer: (onFilter, column) =>
|
||||||
|
<PriceFilter onFilter={ onFilter } column={ column } />
|
||||||
|
}];
|
||||||
|
|
||||||
|
<BootstrapTable keyField='id' data={ products } columns={ columns } filter={ filterFactory() } />
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
filter={ filterFactory() }
|
||||||
|
/>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "react-bootstrap-table2-example",
|
"name": "react-bootstrap-table2-example",
|
||||||
"version": "0.1.9",
|
"version": "0.1.10",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
|||||||
@@ -55,6 +55,8 @@ import ProgrammaticallyTextFilter from 'examples/column-filter/programmatically-
|
|||||||
import ProgrammaticallySelectFilter from 'examples/column-filter/programmatically-select-filter';
|
import ProgrammaticallySelectFilter from 'examples/column-filter/programmatically-select-filter';
|
||||||
import ProgrammaticallyNumberFilter from 'examples/column-filter/programmatically-number-filter';
|
import ProgrammaticallyNumberFilter from 'examples/column-filter/programmatically-number-filter';
|
||||||
import ProgrammaticallyDateFilter from 'examples/column-filter/programmatically-date-filter';
|
import ProgrammaticallyDateFilter from 'examples/column-filter/programmatically-date-filter';
|
||||||
|
import CustomFilter from 'examples/column-filter/custom-filter';
|
||||||
|
import AdvanceCustomFilter from 'examples/column-filter/advance-custom-filter';
|
||||||
|
|
||||||
// work on rows
|
// work on rows
|
||||||
import RowStyleTable from 'examples/rows/row-style';
|
import RowStyleTable from 'examples/rows/row-style';
|
||||||
@@ -186,7 +188,9 @@ storiesOf('Column Filter', module)
|
|||||||
.add('Programmatically Text Filter', () => <ProgrammaticallyTextFilter />)
|
.add('Programmatically Text Filter', () => <ProgrammaticallyTextFilter />)
|
||||||
.add('Programmatically Select Filter', () => <ProgrammaticallySelectFilter />)
|
.add('Programmatically Select Filter', () => <ProgrammaticallySelectFilter />)
|
||||||
.add('Programmatically Number Filter', () => <ProgrammaticallyNumberFilter />)
|
.add('Programmatically Number Filter', () => <ProgrammaticallyNumberFilter />)
|
||||||
.add('Programmatically Date Filter', () => <ProgrammaticallyDateFilter />);
|
.add('Programmatically Date Filter', () => <ProgrammaticallyDateFilter />)
|
||||||
|
.add('Custom Filter', () => <CustomFilter />)
|
||||||
|
.add('Advance Custom Filter', () => <AdvanceCustomFilter />);
|
||||||
|
|
||||||
storiesOf('Work on Rows', module)
|
storiesOf('Work on Rows', module)
|
||||||
.add('Customize Row Style', () => <RowStyleTable />)
|
.add('Customize Row Style', () => <RowStyleTable />)
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ You can get all types of filters via import and these filters are a factory func
|
|||||||
* SelectFilter
|
* SelectFilter
|
||||||
* NumberFilter
|
* NumberFilter
|
||||||
* DateFilter
|
* DateFilter
|
||||||
|
* CustomFilter
|
||||||
* **Coming soon!**
|
* **Coming soon!**
|
||||||
|
|
||||||
## Add CSS
|
## Add CSS
|
||||||
@@ -189,4 +190,54 @@ const dateFilter = dateFilter({
|
|||||||
})
|
})
|
||||||
|
|
||||||
// omit...
|
// omit...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Custom Filter
|
||||||
|
|
||||||
|
```js
|
||||||
|
import filterFactory, { customFilter } from 'react-bootstrap-table2-filter';
|
||||||
|
|
||||||
|
const columns = [..., {
|
||||||
|
dataField: 'date',
|
||||||
|
text: 'Product Name',
|
||||||
|
filter: customFilter(),
|
||||||
|
filterRenderer: (onFilter, column) => .....
|
||||||
|
}];
|
||||||
|
|
||||||
|
<BootstrapTable keyField='id' data={ products } columns={ columns } filter={ filterFactory() } />
|
||||||
|
```
|
||||||
|
|
||||||
|
In custom filter case, you are suppose to finish following two steps:
|
||||||
|
1. Call `customFilter` and pass to `column.filter`
|
||||||
|
2. Give `column.filterRenderer` as a callback function and return your custom filter element.
|
||||||
|
|
||||||
|
### column.filterRenderer
|
||||||
|
|
||||||
|
This function will pass two argument to you:
|
||||||
|
1. `onFilter`: call it to trigger filter when you need.
|
||||||
|
2. `column`: Just the column object!
|
||||||
|
|
||||||
|
In the end, please remember to return your custom filter element!
|
||||||
|
|
||||||
|
### customFilter
|
||||||
|
|
||||||
|
`customFilter` function just same as `textFilter`, `selectFilter` etc, it is for customization reason. However, in the custom filter case, there's only one props is valid: `type`
|
||||||
|
|
||||||
|
|
||||||
|
```js
|
||||||
|
import filterFactory, { FILTER_TYPES } from 'react-bootstrap-table2-filter';
|
||||||
|
|
||||||
|
const customFilter = customFilter({
|
||||||
|
type: FILTER_TYPES.NUMBER, // default is FILTER_TYPES.TEXT
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
`type` is a way to ask `react-bootstrap-table` to filter you data as number, select, date or normal text.
|
||||||
|
|
||||||
|
### FILTER_TYPES
|
||||||
|
|
||||||
|
Following properties is valid in `FILTER_TYPES`:
|
||||||
|
* TEXT
|
||||||
|
* SELECT
|
||||||
|
* NUMBER
|
||||||
|
* DATE
|
||||||
@@ -4,12 +4,15 @@ import NumberFilter from './src/components/number';
|
|||||||
import DateFilter from './src/components/date';
|
import DateFilter from './src/components/date';
|
||||||
import wrapperFactory from './src/wrapper';
|
import wrapperFactory from './src/wrapper';
|
||||||
import * as Comparison from './src/comparison';
|
import * as Comparison from './src/comparison';
|
||||||
|
import { FILTER_TYPE } from './src/const';
|
||||||
|
|
||||||
export default (options = {}) => ({
|
export default (options = {}) => ({
|
||||||
wrapperFactory,
|
wrapperFactory,
|
||||||
options
|
options
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const FILTER_TYPES = FILTER_TYPE;
|
||||||
|
|
||||||
export const Comparator = Comparison;
|
export const Comparator = Comparison;
|
||||||
|
|
||||||
export const textFilter = (props = {}) => ({
|
export const textFilter = (props = {}) => ({
|
||||||
@@ -31,3 +34,7 @@ export const dateFilter = (props = {}) => ({
|
|||||||
Filter: DateFilter,
|
Filter: DateFilter,
|
||||||
props
|
props
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const customFilter = (props = {}) => ({
|
||||||
|
props
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "react-bootstrap-table2-filter",
|
"name": "react-bootstrap-table2-filter",
|
||||||
"version": "0.2.0",
|
"version": "0.3.0",
|
||||||
"description": "it's a column filter addon for react-bootstrap-table2",
|
"description": "it's a column filter addon for react-bootstrap-table2",
|
||||||
"main": "./lib/index.js",
|
"main": "./lib/index.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
/* eslint react/require-default-props: 0 */
|
/* eslint react/require-default-props: 0 */
|
||||||
|
/* eslint jsx-a11y/no-static-element-interactions: 0 */
|
||||||
/* eslint no-return-assign: 0 */
|
/* eslint no-return-assign: 0 */
|
||||||
/* eslint prefer-template: 0 */
|
/* eslint prefer-template: 0 */
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
@@ -121,7 +122,11 @@ class DateFilter extends Component {
|
|||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={ `filter date-filter ${className}` } style={ style }>
|
<div
|
||||||
|
onClick={ e => e.stopPropagation() }
|
||||||
|
className={ `filter date-filter ${className}` }
|
||||||
|
style={ style }
|
||||||
|
>
|
||||||
<select
|
<select
|
||||||
ref={ n => this.dateFilterComparator = n }
|
ref={ n => this.dateFilterComparator = n }
|
||||||
style={ comparatorStyle }
|
style={ comparatorStyle }
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
/* eslint jsx-a11y/no-static-element-interactions: 0 */
|
||||||
/* eslint react/require-default-props: 0 */
|
/* eslint react/require-default-props: 0 */
|
||||||
/* eslint no-return-assign: 0 */
|
/* eslint no-return-assign: 0 */
|
||||||
|
|
||||||
@@ -167,7 +168,11 @@ class NumberFilter extends Component {
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={ `filter number-filter ${className}` } style={ style }>
|
<div
|
||||||
|
onClick={ e => e.stopPropagation() }
|
||||||
|
className={ `filter number-filter ${className}` }
|
||||||
|
style={ style }
|
||||||
|
>
|
||||||
<select
|
<select
|
||||||
ref={ n => this.numberFilterComparator = n }
|
ref={ n => this.numberFilterComparator = n }
|
||||||
style={ comparatorStyle }
|
style={ comparatorStyle }
|
||||||
|
|||||||
@@ -116,6 +116,7 @@ class SelectFilter extends Component {
|
|||||||
style={ style }
|
style={ style }
|
||||||
className={ selectClass }
|
className={ selectClass }
|
||||||
onChange={ this.filter }
|
onChange={ this.filter }
|
||||||
|
onClick={ e => e.stopPropagation() }
|
||||||
defaultValue={ defaultValue !== undefined ? defaultValue : '' }
|
defaultValue={ defaultValue !== undefined ? defaultValue : '' }
|
||||||
>
|
>
|
||||||
{ this.getOptions() }
|
{ this.getOptions() }
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ export default (Base, {
|
|||||||
super(props);
|
super(props);
|
||||||
this.state = { currFilters: {}, isDataChanged: props.isDataChanged || false };
|
this.state = { currFilters: {}, isDataChanged: props.isDataChanged || false };
|
||||||
this.onFilter = this.onFilter.bind(this);
|
this.onFilter = this.onFilter.bind(this);
|
||||||
|
this.onExternalFilter = this.onExternalFilter.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps({ isDataChanged, store, columns }) {
|
componentWillReceiveProps({ isDataChanged, store, columns }) {
|
||||||
@@ -78,12 +79,19 @@ export default (Base, {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onExternalFilter(column, filterType) {
|
||||||
|
return (value) => {
|
||||||
|
this.onFilter(column, filterType)(value);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Base
|
<Base
|
||||||
{ ...this.props }
|
{ ...this.props }
|
||||||
data={ this.props.store.data }
|
data={ this.props.store.data }
|
||||||
onFilter={ this.onFilter }
|
onFilter={ this.onFilter }
|
||||||
|
onExternalFilter={ this.onExternalFilter }
|
||||||
isDataChanged={ this.state.isDataChanged }
|
isDataChanged={ this.state.isDataChanged }
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "react-bootstrap-table2-paginator",
|
"name": "react-bootstrap-table2-paginator",
|
||||||
"version": "0.1.4",
|
"version": "0.1.5",
|
||||||
"description": "it's the pagination addon for react-bootstrap-table2",
|
"description": "it's the pagination addon for react-bootstrap-table2",
|
||||||
"main": "./lib/index.js",
|
"main": "./lib/index.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|||||||
@@ -54,11 +54,14 @@ export default (Base, {
|
|||||||
if (typeof page !== 'undefined' && currPage !== page) { // user defined page
|
if (typeof page !== 'undefined' && currPage !== page) { // user defined page
|
||||||
currPage = page;
|
currPage = page;
|
||||||
needNewState = true;
|
needNewState = true;
|
||||||
} else if (nextProps.isDataChanged) { // user didn't defined page but data change
|
} else if (nextProps.isDataChanged) {
|
||||||
currPage = typeof pageStartIndex !== 'undefined' ? pageStartIndex : Const.PAGE_START_INDEX;
|
|
||||||
needNewState = true;
|
needNewState = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeof currPage === 'undefined') {
|
||||||
|
currPage = typeof pageStartIndex !== 'undefined' ? pageStartIndex : Const.PAGE_START_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
if (typeof sizePerPage !== 'undefined') {
|
if (typeof sizePerPage !== 'undefined') {
|
||||||
currSizePerPage = sizePerPage;
|
currSizePerPage = sizePerPage;
|
||||||
needNewState = true;
|
needNewState = true;
|
||||||
|
|||||||
@@ -177,10 +177,11 @@ describe('Wrapper', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when nextProps.isDataChanged is true and options.pageStartIndex is existing', () => {
|
describe('when nextProps.isDataChanged is true, currPage is undefined and options.pageStartIndex exists', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
nextProps.isDataChanged = true;
|
nextProps.isDataChanged = true;
|
||||||
nextProps.pagination.options.pageStartIndex = 0;
|
nextProps.pagination.options.pageStartIndex = 0;
|
||||||
|
instance.state.currPage = undefined;
|
||||||
instance.componentWillReceiveProps(nextProps);
|
instance.componentWillReceiveProps(nextProps);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "react-bootstrap-table-next",
|
"name": "react-bootstrap-table-next",
|
||||||
"version": "0.1.13",
|
"version": "0.1.14",
|
||||||
"description": "Next generation of react-bootstrap-table",
|
"description": "Next generation of react-bootstrap-table",
|
||||||
"main": "./lib/index.js",
|
"main": "./lib/index.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|||||||
@@ -90,6 +90,7 @@ class BootstrapTable extends PropsBaseResolver(Component) {
|
|||||||
sortOrder={ store.sortOrder }
|
sortOrder={ store.sortOrder }
|
||||||
onSort={ this.props.onSort }
|
onSort={ this.props.onSort }
|
||||||
onFilter={ this.props.onFilter }
|
onFilter={ this.props.onFilter }
|
||||||
|
onExternalFilter={ this.props.onExternalFilter }
|
||||||
selectRow={ headerCellSelectionInfo }
|
selectRow={ headerCellSelectionInfo }
|
||||||
/>
|
/>
|
||||||
<Body
|
<Body
|
||||||
@@ -162,7 +163,8 @@ BootstrapTable.propTypes = {
|
|||||||
overlay: PropTypes.func,
|
overlay: PropTypes.func,
|
||||||
onTableChange: PropTypes.func,
|
onTableChange: PropTypes.func,
|
||||||
onSort: PropTypes.func,
|
onSort: PropTypes.func,
|
||||||
onFilter: PropTypes.func
|
onFilter: PropTypes.func,
|
||||||
|
onExternalFilter: PropTypes.func
|
||||||
};
|
};
|
||||||
|
|
||||||
BootstrapTable.defaultProps = {
|
BootstrapTable.defaultProps = {
|
||||||
|
|||||||
@@ -17,13 +17,15 @@ const HeaderCell = (props) => {
|
|||||||
sorting,
|
sorting,
|
||||||
sortOrder,
|
sortOrder,
|
||||||
isLastSorting,
|
isLastSorting,
|
||||||
onFilter
|
onFilter,
|
||||||
|
onExternalFilter
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
text,
|
text,
|
||||||
sort,
|
sort,
|
||||||
filter,
|
filter,
|
||||||
|
filterRenderer,
|
||||||
headerTitle,
|
headerTitle,
|
||||||
headerAlign,
|
headerAlign,
|
||||||
headerFormatter,
|
headerFormatter,
|
||||||
@@ -89,7 +91,11 @@ const HeaderCell = (props) => {
|
|||||||
|
|
||||||
if (cellClasses) cellAttrs.className = cs(cellAttrs.className, cellClasses);
|
if (cellClasses) cellAttrs.className = cs(cellAttrs.className, cellClasses);
|
||||||
if (!_.isEmptyObject(cellStyle)) cellAttrs.style = cellStyle;
|
if (!_.isEmptyObject(cellStyle)) cellAttrs.style = cellStyle;
|
||||||
if (filter) {
|
|
||||||
|
if (filterRenderer) {
|
||||||
|
const onCustomFilter = onExternalFilter(column, filter.props.type);
|
||||||
|
filterElm = filterRenderer(onCustomFilter, column);
|
||||||
|
} else if (filter) {
|
||||||
filterElm = <filter.Filter { ...filter.props } onFilter={ onFilter } column={ column } />;
|
filterElm = <filter.Filter { ...filter.props } onFilter={ onFilter } column={ column } />;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,6 +142,7 @@ HeaderCell.propTypes = {
|
|||||||
editorRenderer: PropTypes.func,
|
editorRenderer: PropTypes.func,
|
||||||
validator: PropTypes.func,
|
validator: PropTypes.func,
|
||||||
filter: PropTypes.object,
|
filter: PropTypes.object,
|
||||||
|
filterRenderer: PropTypes.func,
|
||||||
filterValue: PropTypes.func
|
filterValue: PropTypes.func
|
||||||
}).isRequired,
|
}).isRequired,
|
||||||
index: PropTypes.number.isRequired,
|
index: PropTypes.number.isRequired,
|
||||||
@@ -143,7 +150,8 @@ HeaderCell.propTypes = {
|
|||||||
sorting: PropTypes.bool,
|
sorting: PropTypes.bool,
|
||||||
sortOrder: PropTypes.oneOf([Const.SORT_ASC, Const.SORT_DESC]),
|
sortOrder: PropTypes.oneOf([Const.SORT_ASC, Const.SORT_DESC]),
|
||||||
isLastSorting: PropTypes.bool,
|
isLastSorting: PropTypes.bool,
|
||||||
onFilter: PropTypes.func
|
onFilter: PropTypes.func,
|
||||||
|
onExternalFilter: PropTypes.func
|
||||||
};
|
};
|
||||||
|
|
||||||
export default HeaderCell;
|
export default HeaderCell;
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ const Header = (props) => {
|
|||||||
onFilter,
|
onFilter,
|
||||||
sortField,
|
sortField,
|
||||||
sortOrder,
|
sortOrder,
|
||||||
selectRow
|
selectRow,
|
||||||
|
onExternalFilter
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -39,6 +40,7 @@ const Header = (props) => {
|
|||||||
onSort={ onSort }
|
onSort={ onSort }
|
||||||
sorting={ currSort }
|
sorting={ currSort }
|
||||||
onFilter={ onFilter }
|
onFilter={ onFilter }
|
||||||
|
onExternalFilter={ onExternalFilter }
|
||||||
sortOrder={ sortOrder }
|
sortOrder={ sortOrder }
|
||||||
isLastSorting={ isLastSorting }
|
isLastSorting={ isLastSorting }
|
||||||
/>);
|
/>);
|
||||||
@@ -57,7 +59,8 @@ Header.propTypes = {
|
|||||||
onFilter: PropTypes.func,
|
onFilter: PropTypes.func,
|
||||||
sortField: PropTypes.string,
|
sortField: PropTypes.string,
|
||||||
sortOrder: PropTypes.string,
|
sortOrder: PropTypes.string,
|
||||||
selectRow: PropTypes.object
|
selectRow: PropTypes.object,
|
||||||
|
onExternalFilter: PropTypes.func
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Header;
|
export default Header;
|
||||||
|
|||||||
@@ -669,4 +669,74 @@ describe('HeaderCell', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('when column.filter is defined', () => {
|
||||||
|
const onFilter = jest.fn();
|
||||||
|
const filterProps = { a: 123 };
|
||||||
|
const Filter = () => <div>test</div>;
|
||||||
|
let column;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
onFilter.mockClear();
|
||||||
|
column = {
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'ID',
|
||||||
|
filter: {
|
||||||
|
props: filterProps,
|
||||||
|
Filter
|
||||||
|
}
|
||||||
|
};
|
||||||
|
wrapper = shallow(<HeaderCell column={ column } index={ index } onFilter={ onFilter } />);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render successfully', () => {
|
||||||
|
expect(wrapper.length).toBe(1);
|
||||||
|
expect(wrapper.find('th').length).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render filter correctly', () => {
|
||||||
|
expect(wrapper.find(Filter).length).toBe(1);
|
||||||
|
expect(wrapper.find(Filter).props()).toEqual({
|
||||||
|
column,
|
||||||
|
onFilter,
|
||||||
|
...filterProps
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when column.filter and column.filterRenderer is defined', () => {
|
||||||
|
const onExternalFilter = jest.fn();
|
||||||
|
const filterProps = { a: 123 };
|
||||||
|
const Filter = () => <div>test</div>;
|
||||||
|
const filterRenderer = jest.fn().mockReturnValue(<Filter />);
|
||||||
|
let column;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
onExternalFilter.mockClear();
|
||||||
|
filterRenderer.mockClear();
|
||||||
|
column = {
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'ID',
|
||||||
|
filter: {
|
||||||
|
props: filterProps
|
||||||
|
},
|
||||||
|
filterRenderer
|
||||||
|
};
|
||||||
|
wrapper = shallow(
|
||||||
|
<HeaderCell column={ column } index={ index } onExternalFilter={ onExternalFilter } />);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render successfully', () => {
|
||||||
|
expect(wrapper.length).toBe(1);
|
||||||
|
expect(wrapper.find('th').length).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render filter correctly', () => {
|
||||||
|
expect(wrapper.find(Filter).length).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call filterRenderer function correctly', () => {
|
||||||
|
expect(filterRenderer).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user