implement select filter

This commit is contained in:
AllenFang
2018-01-30 23:20:47 +08:00
parent 280c423298
commit 3f2c6201d9
4 changed files with 144 additions and 3 deletions
+6
View File
@@ -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
});
@@ -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((
<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 !== '' }));
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 (
<select
{ ...rest }
ref={ n => this.selectInput = n }
style={ style }
className={ selectClass }
onChange={ this.filter }
defaultValue={ defaultValue !== undefined ? defaultValue : '' }
>
{ this.getOptions() }
</select>
);
}
}
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;
+2 -1
View File
@@ -1,5 +1,6 @@
export const FILTER_TYPE = {
TEXT: 'TEXT'
TEXT: 'TEXT',
SELECT: 'SELECT'
};
export const FILTER_DELAY = 500;
+4 -2
View File
@@ -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;