mirror of
https://github.com/gosticks/react-bootstrap-table2.git
synced 2026-06-28 21:20:04 +00:00
Added multiselect filter (mostly copied from default select one)
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import TextFilter from './src/components/text';
|
||||
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';
|
||||
@@ -25,6 +26,11 @@ export const selectFilter = (props = {}) => ({
|
||||
props
|
||||
});
|
||||
|
||||
export const multiSelectFilter = (props = {}) => ({
|
||||
Filter: MultiSelectFilter,
|
||||
props
|
||||
});
|
||||
|
||||
export const numberFilter = (props = {}) => ({
|
||||
Filter: NumberFilter,
|
||||
props
|
||||
|
||||
155
packages/react-bootstrap-table2-filter/src/components/multiselect.js
vendored
Normal file
155
packages/react-bootstrap-table2-filter/src/components/multiselect.js
vendored
Normal file
@@ -0,0 +1,155 @@
|
||||
/* eslint react/require-default-props: 0 */
|
||||
/* eslint no-return-assign: 0 */
|
||||
/* eslint react/no-unused-prop-types: 0 */
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { LIKE, EQ } from '../comparison';
|
||||
import { FILTER_TYPE } from '../const';
|
||||
|
||||
|
||||
function optionsEquals(currOpts, prevOpts) {
|
||||
const keys = Object.keys(currOpts);
|
||||
for (let i = 0; i < keys.length; i += 1) {
|
||||
if (currOpts[keys[i]] !== prevOpts[keys[i]]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return Object.keys(currOpts).length === Object.keys(prevOpts).length;
|
||||
}
|
||||
|
||||
const getSelections = container =>
|
||||
Array.from(container.selectedOptions).map(item => item.value);
|
||||
|
||||
class MultiSelectFilter extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.filter = this.filter.bind(this);
|
||||
const isSelected = props.defaultValue.map(item => props.options[item]).length > 0;
|
||||
this.state = { isSelected };
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { column, onFilter, getFilter } = this.props;
|
||||
|
||||
const value = getSelections(this.selectInput);
|
||||
if (value && value.length > 0) {
|
||||
onFilter(column, FILTER_TYPE.MULTISELECT)(value);
|
||||
}
|
||||
|
||||
// export onFilter function to allow users to access
|
||||
if (getFilter) {
|
||||
getFilter((filterVal) => {
|
||||
this.setState(() => ({ isSelected: filterVal.length > 0 }));
|
||||
this.selectInput.value = filterVal;
|
||||
|
||||
onFilter(column, FILTER_TYPE.MULTISELECT)(filterVal);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
let needFilter = false;
|
||||
if (this.props.defaultValue !== prevProps.defaultValue) {
|
||||
needFilter = true;
|
||||
} else if (!optionsEquals(this.props.options, prevProps.options)) {
|
||||
needFilter = true;
|
||||
}
|
||||
if (needFilter) {
|
||||
const value = this.selectInput.value;
|
||||
if (value) {
|
||||
this.props.onFilter(this.props.column, FILTER_TYPE.MULTISELECT)(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getOptions() {
|
||||
const optionTags = [];
|
||||
const { options, placeholder, column, withoutEmptyOption } = this.props;
|
||||
if (!withoutEmptyOption) {
|
||||
optionTags.push((
|
||||
<option key="-1" value="">{ placeholder || `Select ${column.text}...` }</option>
|
||||
));
|
||||
}
|
||||
Object.keys(options).forEach(key =>
|
||||
optionTags.push(<option key={ key } value={ key }>{ options[key] }</option>)
|
||||
);
|
||||
return optionTags;
|
||||
}
|
||||
|
||||
cleanFiltered() {
|
||||
const value = (this.props.defaultValue !== undefined) ? this.props.defaultValue : [];
|
||||
this.setState(() => ({ isSelected: value.length > 0 }));
|
||||
this.selectInput.value = value;
|
||||
this.props.onFilter(this.props.column, FILTER_TYPE.MULTISELECT)(value);
|
||||
}
|
||||
|
||||
applyFilter(value) {
|
||||
this.selectInput.value = value;
|
||||
this.setState(() => ({ isSelected: value.length > 0 }));
|
||||
this.props.onFilter(this.props.column, FILTER_TYPE.MULTISELECT)(value);
|
||||
}
|
||||
|
||||
filter(e) {
|
||||
const value = getSelections(e.target);
|
||||
this.setState(() => ({ isSelected: value.length > 0 }));
|
||||
this.props.onFilter(this.props.column, FILTER_TYPE.MULTISELECT)(value);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
style,
|
||||
className,
|
||||
defaultValue,
|
||||
onFilter,
|
||||
column,
|
||||
options,
|
||||
comparator,
|
||||
withoutEmptyOption,
|
||||
caseSensitive,
|
||||
getFilter,
|
||||
...rest
|
||||
} = this.props;
|
||||
|
||||
const selectClass =
|
||||
`filter select-filter form-control ${className} ${this.state.isSelected ? '' : 'placeholder-selected'}`;
|
||||
|
||||
return (
|
||||
<select
|
||||
{ ...rest }
|
||||
ref={ n => this.selectInput = n }
|
||||
style={ style }
|
||||
multiple
|
||||
className={ selectClass }
|
||||
onChange={ this.filter }
|
||||
onClick={ e => e.stopPropagation() }
|
||||
defaultValue={ defaultValue !== undefined ? defaultValue : '' }
|
||||
>
|
||||
{ this.getOptions() }
|
||||
</select>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
MultiSelectFilter.propTypes = {
|
||||
onFilter: PropTypes.func.isRequired,
|
||||
column: PropTypes.object.isRequired,
|
||||
options: PropTypes.object.isRequired,
|
||||
comparator: PropTypes.oneOf([LIKE, EQ]),
|
||||
placeholder: PropTypes.string,
|
||||
style: PropTypes.object,
|
||||
className: PropTypes.string,
|
||||
withoutEmptyOption: PropTypes.bool,
|
||||
defaultValue: PropTypes.array,
|
||||
caseSensitive: PropTypes.bool,
|
||||
getFilter: PropTypes.func
|
||||
};
|
||||
|
||||
MultiSelectFilter.defaultProps = {
|
||||
defaultValue: [],
|
||||
className: '',
|
||||
withoutEmptyOption: false,
|
||||
comparator: EQ,
|
||||
caseSensitive: true
|
||||
};
|
||||
|
||||
export default MultiSelectFilter;
|
||||
@@ -1,6 +1,7 @@
|
||||
export const FILTER_TYPE = {
|
||||
TEXT: 'TEXT',
|
||||
SELECT: 'SELECT',
|
||||
MULTISELECT: 'MULTISELECT',
|
||||
NUMBER: 'NUMBER',
|
||||
DATE: 'DATE'
|
||||
};
|
||||
|
||||
@@ -187,6 +187,22 @@ export const filterByDate = _ => (
|
||||
});
|
||||
};
|
||||
|
||||
export const filterByArray = _ => (
|
||||
data,
|
||||
dataField,
|
||||
{ filterVal, comparator }
|
||||
) => (
|
||||
data.filter((row) => {
|
||||
const cell = _.get(row, dataField);
|
||||
let cellStr = _.isDefined(cell) ? cell.toString() : '';
|
||||
if (comparator === EQ) {
|
||||
return filterVal.indexOf(cellStr) !== -1;
|
||||
}
|
||||
cellStr = cellStr.toLocaleUpperCase();
|
||||
return filterVal.some(item => cellStr.indexOf(item.toLocaleUpperCase()) !== -1);
|
||||
})
|
||||
);
|
||||
|
||||
export const filterFactory = _ => (filterType) => {
|
||||
let filterFn;
|
||||
switch (filterType) {
|
||||
@@ -194,6 +210,9 @@ export const filterFactory = _ => (filterType) => {
|
||||
case FILTER_TYPE.SELECT:
|
||||
filterFn = filterByText(_);
|
||||
break;
|
||||
case FILTER_TYPE.MULTISELECT:
|
||||
filterFn = filterByArray(_);
|
||||
break;
|
||||
case FILTER_TYPE.NUMBER:
|
||||
filterFn = filterByNumber(_);
|
||||
break;
|
||||
|
||||
@@ -53,12 +53,18 @@ export default (Base, {
|
||||
const currFilters = Object.assign({}, store.filters);
|
||||
const { dataField, filter } = column;
|
||||
|
||||
if (!_.isDefined(filterVal) || filterVal === '') {
|
||||
const needClearFilters = !_.isDefined(filterVal) || filterVal === '' ||
|
||||
filterVal.length === 0; // || (filterVal.length === 1 && filterVal[0] === '');
|
||||
|
||||
if (needClearFilters) {
|
||||
delete currFilters[dataField];
|
||||
} else {
|
||||
// select default comparator is EQ, others are LIKE
|
||||
const {
|
||||
comparator = (filterType === FILTER_TYPE.SELECT ? EQ : LIKE),
|
||||
comparator = (
|
||||
(filterType === FILTER_TYPE.SELECT) || (
|
||||
filterType === FILTER_TYPE.MULTISELECT) ? EQ : LIKE
|
||||
),
|
||||
caseSensitive = false
|
||||
} = filter.props;
|
||||
currFilters[dataField] = { filterVal, filterType, comparator, caseSensitive };
|
||||
|
||||
Reference in New Issue
Block a user