2015-12-29 11:46:13 +08:00
|
|
|
import React from 'react';
|
2016-03-21 21:16:38 +08:00
|
|
|
import RcCascader from 'rc-cascader';
|
2015-12-29 11:46:13 +08:00
|
|
|
import Input from '../input';
|
2015-12-29 21:18:27 +08:00
|
|
|
import Icon from '../icon';
|
2015-12-29 11:46:13 +08:00
|
|
|
import arrayTreeFilter from 'array-tree-filter';
|
2015-12-29 18:31:48 +08:00
|
|
|
import classNames from 'classnames';
|
2016-07-06 12:21:49 +08:00
|
|
|
import omit from 'object.omit';
|
2015-12-29 11:46:13 +08:00
|
|
|
|
2016-03-21 21:16:38 +08:00
|
|
|
export default class Cascader extends React.Component {
|
2016-03-29 14:01:10 +08:00
|
|
|
static defaultProps = {
|
|
|
|
prefixCls: 'ant-cascader',
|
2016-04-01 13:51:26 +08:00
|
|
|
placeholder: 'Please select',
|
2016-03-29 14:01:10 +08:00
|
|
|
transitionName: 'slide-up',
|
|
|
|
popupPlacement: 'bottomLeft',
|
|
|
|
onChange() {},
|
|
|
|
options: [],
|
2016-03-30 19:36:29 +08:00
|
|
|
displayRender: label => label.join(' / '),
|
2016-03-29 14:01:10 +08:00
|
|
|
disabled: false,
|
|
|
|
allowClear: true,
|
|
|
|
onPopupVisibleChange() {},
|
|
|
|
}
|
|
|
|
|
2015-12-29 11:46:13 +08:00
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
2016-05-09 11:59:30 +08:00
|
|
|
let value;
|
|
|
|
if ('value' in props) {
|
|
|
|
value = props.value;
|
|
|
|
} else if ('defaultValue' in props) {
|
|
|
|
value = props.defaultValue;
|
|
|
|
}
|
2015-12-29 11:46:13 +08:00
|
|
|
this.state = {
|
2016-05-09 11:59:30 +08:00
|
|
|
value: value || [],
|
2015-12-29 21:18:27 +08:00
|
|
|
popupVisible: false,
|
2015-12-29 11:46:13 +08:00
|
|
|
};
|
|
|
|
}
|
2016-03-29 14:01:10 +08:00
|
|
|
|
2015-12-29 21:18:27 +08:00
|
|
|
componentWillReceiveProps(nextProps) {
|
|
|
|
if ('value' in nextProps) {
|
2016-01-06 11:45:47 +08:00
|
|
|
this.setState({ value: nextProps.value || [] });
|
2015-12-29 21:18:27 +08:00
|
|
|
}
|
|
|
|
}
|
2016-03-29 14:01:10 +08:00
|
|
|
|
2016-03-23 19:50:44 +08:00
|
|
|
handleChange = (value, selectedOptions) => {
|
2015-12-29 21:18:27 +08:00
|
|
|
this.setValue(value, selectedOptions);
|
|
|
|
}
|
2016-03-29 14:01:10 +08:00
|
|
|
|
2016-03-23 19:50:44 +08:00
|
|
|
handlePopupVisibleChange = (popupVisible) => {
|
2015-12-29 21:18:27 +08:00
|
|
|
this.setState({ popupVisible });
|
|
|
|
this.props.onPopupVisibleChange(popupVisible);
|
|
|
|
}
|
2016-03-29 14:01:10 +08:00
|
|
|
|
2016-03-23 19:50:44 +08:00
|
|
|
setValue = (value, selectedOptions = []) => {
|
2015-12-29 21:18:27 +08:00
|
|
|
if (!('value' in this.props)) {
|
|
|
|
this.setState({ value });
|
|
|
|
}
|
2015-12-29 11:46:13 +08:00
|
|
|
this.props.onChange(value, selectedOptions);
|
|
|
|
}
|
2016-03-29 14:01:10 +08:00
|
|
|
|
2015-12-29 11:46:13 +08:00
|
|
|
getLabel() {
|
|
|
|
const { options, displayRender } = this.props;
|
2016-05-18 15:34:30 +08:00
|
|
|
const selectedOptions = arrayTreeFilter(options, (o, level) => o.value === this.state.value[level]);
|
|
|
|
const label = selectedOptions.map(o => o.label);
|
|
|
|
return displayRender(label, selectedOptions);
|
2015-12-29 11:46:13 +08:00
|
|
|
}
|
2016-03-29 14:01:10 +08:00
|
|
|
|
2016-03-23 19:50:44 +08:00
|
|
|
clearSelection = (e) => {
|
2015-12-29 21:18:27 +08:00
|
|
|
e.preventDefault();
|
2015-12-29 22:34:23 +08:00
|
|
|
e.stopPropagation();
|
2015-12-29 21:18:27 +08:00
|
|
|
this.setValue([]);
|
|
|
|
this.setState({ popupVisible: false });
|
|
|
|
}
|
2016-03-29 14:01:10 +08:00
|
|
|
|
2015-12-29 11:46:13 +08:00
|
|
|
render() {
|
2016-04-14 11:22:53 +08:00
|
|
|
const props = this.props;
|
2016-03-02 22:04:54 +08:00
|
|
|
const { prefixCls, children, placeholder, size, disabled,
|
2016-04-14 11:22:53 +08:00
|
|
|
className, style, allowClear, ...otherProps } = props;
|
2016-07-07 16:59:47 +08:00
|
|
|
|
2015-12-29 18:31:48 +08:00
|
|
|
const sizeCls = classNames({
|
|
|
|
'ant-input-lg': size === 'large',
|
|
|
|
'ant-input-sm': size === 'small',
|
|
|
|
});
|
2016-02-25 12:04:58 +08:00
|
|
|
const clearIcon = (allowClear && !disabled && this.state.value.length > 0) ?
|
2015-12-29 21:18:27 +08:00
|
|
|
<Icon type="cross-circle"
|
|
|
|
className={`${prefixCls}-picker-clear`}
|
2016-06-06 13:54:10 +08:00
|
|
|
onClick={this.clearSelection}
|
|
|
|
/> : null;
|
2015-12-29 22:34:23 +08:00
|
|
|
const arrowCls = classNames({
|
|
|
|
[`${prefixCls}-picker-arrow`]: true,
|
|
|
|
[`${prefixCls}-picker-arrow-expand`]: this.state.popupVisible,
|
|
|
|
});
|
2016-01-05 11:31:22 +08:00
|
|
|
const pickerCls = classNames({
|
2016-01-25 20:52:43 +08:00
|
|
|
[className]: !!className,
|
2016-01-05 11:31:22 +08:00
|
|
|
[`${prefixCls}-picker`]: true,
|
|
|
|
[`${prefixCls}-picker-disabled`]: disabled,
|
|
|
|
});
|
2016-03-03 14:57:26 +08:00
|
|
|
|
|
|
|
// Fix bug of https://github.com/facebook/react/pull/5004
|
2016-07-06 12:21:49 +08:00
|
|
|
// and https://fb.me/react-unknown-prop
|
|
|
|
const inputProps = omit(otherProps, [
|
|
|
|
'onChange',
|
|
|
|
'options',
|
|
|
|
'popupPlacement',
|
|
|
|
'transitionName',
|
|
|
|
'displayRender',
|
|
|
|
'onPopupVisibleChange',
|
|
|
|
'changeOnSelect',
|
|
|
|
'expandTrigger',
|
|
|
|
]);
|
2016-03-03 14:57:26 +08:00
|
|
|
|
2015-12-29 11:46:13 +08:00
|
|
|
return (
|
2016-04-14 11:22:53 +08:00
|
|
|
<RcCascader {...props}
|
2015-12-29 21:18:27 +08:00
|
|
|
value={this.state.value}
|
|
|
|
popupVisible={this.state.popupVisible}
|
|
|
|
onPopupVisibleChange={this.handlePopupVisibleChange}
|
2016-06-06 13:54:10 +08:00
|
|
|
onChange={this.handleChange}
|
|
|
|
>
|
2015-12-29 11:46:13 +08:00
|
|
|
{children ||
|
2016-01-04 19:23:19 +08:00
|
|
|
<span
|
2016-03-02 21:44:38 +08:00
|
|
|
style={style}
|
2016-06-06 13:54:10 +08:00
|
|
|
className={pickerCls}
|
|
|
|
>
|
2016-07-06 12:21:49 +08:00
|
|
|
<Input {...inputProps}
|
2016-05-18 15:34:30 +08:00
|
|
|
placeholder={this.state.value && this.state.value.length > 0 ? null : placeholder}
|
2015-12-29 21:18:27 +08:00
|
|
|
className={`${prefixCls}-input ant-input ${sizeCls}`}
|
2016-05-18 15:34:30 +08:00
|
|
|
value={null}
|
2016-01-05 11:31:22 +08:00
|
|
|
disabled={disabled}
|
2016-06-06 13:54:10 +08:00
|
|
|
readOnly
|
|
|
|
/>
|
2016-05-18 15:34:30 +08:00
|
|
|
<span className={`${prefixCls}-picker-label`}>{this.getLabel()}</span>
|
2015-12-29 21:18:27 +08:00
|
|
|
{clearIcon}
|
2015-12-29 22:34:23 +08:00
|
|
|
<Icon type="down" className={arrowCls} />
|
2015-12-29 21:18:27 +08:00
|
|
|
</span>
|
|
|
|
}
|
2016-03-21 21:16:38 +08:00
|
|
|
</RcCascader>
|
2015-12-29 11:46:13 +08:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|