From 3f2c6201d95f738b35b3d11987c7a0394cd2857c Mon Sep 17 00:00:00 2001 From: AllenFang Date: Sun, 28 Jan 2018 23:12:54 +0800 Subject: [PATCH] implement select filter --- .../react-bootstrap-table2-filter/index.js | 6 + .../src/components/select.js | 132 ++++++++++++++++++ .../src/const.js | 3 +- .../src/wrapper.js | 6 +- 4 files changed, 144 insertions(+), 3 deletions(-) create mode 100644 packages/react-bootstrap-table2-filter/src/components/select.js diff --git a/packages/react-bootstrap-table2-filter/index.js b/packages/react-bootstrap-table2-filter/index.js index f6335a8..068b508 100644 --- a/packages/react-bootstrap-table2-filter/index.js +++ b/packages/react-bootstrap-table2-filter/index.js @@ -1,4 +1,5 @@ import TextFilter from './src/components/text'; +import SelectFilter from './src/components/select'; import wrapperFactory from './src/wrapper'; import * as Comparison from './src/comparison'; @@ -13,3 +14,8 @@ export const textFilter = (props = {}) => ({ Filter: TextFilter, props }); + +export const selectFilter = (props = {}) => ({ + Filter: SelectFilter, + props +}); diff --git a/packages/react-bootstrap-table2-filter/src/components/select.js b/packages/react-bootstrap-table2-filter/src/components/select.js new file mode 100644 index 0000000..0374280 --- /dev/null +++ b/packages/react-bootstrap-table2-filter/src/components/select.js @@ -0,0 +1,132 @@ +/* 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; +} + +class SelectFilter extends Component { + constructor(props) { + super(props); + this.filter = this.filter.bind(this); + const isSelected = props.options[props.defaultValue] !== undefined; + this.state = { isSelected }; + } + + componentDidMount() { + const value = this.selectInput.value; + if (value && value !== '') { + this.props.onFilter(this.props.column, value, FILTER_TYPE.SELECT); + } + } + + 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, value, FILTER_TYPE.SELECT); + } + } + } + + getOptions() { + const optionTags = []; + const { options, placeholder, column, withoutEmptyOption } = this.props; + if (!withoutEmptyOption) { + optionTags.push(( + + )); + } + Object.keys(options).forEach(key => + optionTags.push() + ); + return optionTags; + } + + cleanFiltered() { + const value = (this.props.defaultValue !== undefined) ? this.props.defaultValue : ''; + this.setState(() => ({ isSelected: value !== '' })); + this.selectInput.value = value; + this.props.onFilter(this.props.column, value, FILTER_TYPE.SELECT); + } + + applyFilter(value) { + this.selectInput.value = value; + this.setState(() => ({ isSelected: value !== '' })); + this.props.onFilter(this.props.column, value, FILTER_TYPE.SELECT); + } + + filter(e) { + const { value } = e.target; + this.setState(() => ({ isSelected: value !== '' })); + this.props.onFilter(this.props.column, value, FILTER_TYPE.SELECT); + } + + render() { + const { + style, + className, + defaultValue, + onFilter, + column, + options, + comparator, + withoutEmptyOption, + ...rest + } = this.props; + + const selectClass = + `filter select-filter form-control ${className} ${this.state.isSelected ? '' : 'placeholder-selected'}`; + + return ( + + ); + } +} + +SelectFilter.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.any +}; + +SelectFilter.defaultProps = { + defaultValue: '', + className: '', + withoutEmptyOption: false, + comparator: EQ +}; + +export default SelectFilter; diff --git a/packages/react-bootstrap-table2-filter/src/const.js b/packages/react-bootstrap-table2-filter/src/const.js index 25faae0..64e8361 100644 --- a/packages/react-bootstrap-table2-filter/src/const.js +++ b/packages/react-bootstrap-table2-filter/src/const.js @@ -1,5 +1,6 @@ export const FILTER_TYPE = { - TEXT: 'TEXT' + TEXT: 'TEXT', + SELECT: 'SELECT' }; export const FILTER_DELAY = 500; diff --git a/packages/react-bootstrap-table2-filter/src/wrapper.js b/packages/react-bootstrap-table2-filter/src/wrapper.js index 7e197fa..3e6822a 100644 --- a/packages/react-bootstrap-table2-filter/src/wrapper.js +++ b/packages/react-bootstrap-table2-filter/src/wrapper.js @@ -3,7 +3,8 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { filters } from './filter'; -import { LIKE } from './comparison'; +import { LIKE, EQ } from './comparison'; +import { FILTER_TYPE } from './const'; export default (Base, { _, @@ -47,7 +48,8 @@ export default (Base, { if (!_.isDefined(filterVal) || filterVal === '') { delete currFilters[dataField]; } else { - const { comparator = LIKE } = filter.props; + // select default comparator is EQ, others are LIKE + const { comparator = (filterType === FILTER_TYPE.SELECT ? EQ : LIKE) } = filter.props; currFilters[dataField] = { filterVal, filterType, comparator }; } store.filters = currFilters;