UNPKG

zarm-mobile

Version:
278 lines (238 loc) 7.55 kB
import React, { Component } from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; import { arrayTreeFilter, formatToInit, formatBackToObject } from './utils'; import ColumnGroup from './ColumnGroup'; import Cascader from './Cascader'; import { Popup } from '../../components'; // 阻止选择器区域的默认事件 function onContainerClick(e) { e.stopPropagation(); } class Picker extends Component { constructor(props) { super(props); let _data = null; let _value = null; if (Object.prototype.toString.call(props.dataSource[0]) !== '[object Array]' && !Object.prototype.hasOwnProperty.call(props.dataSource[0], 'children')) { _data = [props.dataSource]; _value = props.value.length ? [props.value] : props.value; } else { _data = props.dataSource; _value = props.value; } this.state = { visible: props.visible || false, value: _value, data: _data, cascade: Object.prototype.toString.call(props.dataSource[0]) !== '[object Array]' && Object.prototype.hasOwnProperty.call(props.dataSource[0], 'children'), }; this.tempValue = props.value; } componentWillReceiveProps(nextProps) { // console.log(nextProps); if ('value' in nextProps) { let _value = null; let _data = null; if (Object.prototype.toString.call(nextProps.dataSource[0]) !== '[object Array]' && !Object.prototype.hasOwnProperty.call(nextProps.dataSource[0], 'children')) { _value = nextProps.value.length ? [nextProps.value] : nextProps.value; _data = [nextProps.dataSource]; } else { _value = nextProps.value; _data = nextProps.dataSource; } this.setState({ value: _value, data: _data, cascade: Object.prototype.toString.call(nextProps.dataSource[0]) !== '[object Array]' && Object.prototype.hasOwnProperty.call(nextProps.dataSource[0], 'children'), }); } } onValueChange(value) { this.setState({ value, }); this.props.onChange(value); } onCancel() { const { onCancel } = this.props; this.toggle(); this.setState({ value: this.tempValue, }); onCancel && onCancel(); } onOk() { const { onOk, valueMember, cols } = this.props; const { data, cascade } = this.state; const value = this.getInitValue(); this.tempValue = value; this.toggle(); let _value = null; // _value = value.length === 1 ? value.toString() : value; _value = formatBackToObject(data, value, cascade, valueMember, cols); onOk && onOk(_value); } onMaskClick() { const { onMaskClick } = this.props; this.onCancel(); onMaskClick && onMaskClick(); } getInitValue() { const data = this.state.data; const { valueMember } = this.props; const { value } = this.state; if (!value || !value.length) { if (this.state.cascade) { return formatToInit(data[0], valueMember, this.props.cols); } return data.map(d => (d[0][valueMember])); } return value; } // 切换显示状态 toggle() { if (this.props.disabled) { return; } this.setState({ visible: !this.state.visible, }); } handleClick() { this.props.onClick(); !this.props.disabled && this.toggle(); } close(key) { this.setState({ [`${key}`]: false, }); } render() { const { prefixCls, format, disabled, className, cancelText, okText, title, placeholder, displayMember, valueMember } = this.props; const { data, value } = this.state; let PickerCol = null; const classes = classnames({ [`${prefixCls}-container`]: true, [className]: !!className, }); const inputCls = classnames({ [`${prefixCls}-input`]: true, [`${prefixCls}-placeholder`]: !value.join(format), [`${prefixCls}-disabled`]: !!disabled, }); const cols = data.map((d) => { return { props: { children: d } }; }); if (this.state.cascade) { PickerCol = ( <Cascader prefixCls={prefixCls} data={data} value={this.state.value} cols={this.props.cols} displayMember={displayMember} valueMember={valueMember} onChange={v => this.onValueChange(v)} /> ); } else { PickerCol = ( <ColumnGroup className={className} prefixCls={prefixCls} displayMember={displayMember} valueMember={valueMember} selectedValue={value} onValueChange={v => this.onValueChange(v)} > {cols} </ColumnGroup> ); } const display = () => { if (this.state.cascade) { if (value.length) { const treeChildren = arrayTreeFilter(this.props.dataSource, (item, level) => { return item[valueMember] === value[level]; }); return treeChildren.map((v) => { return v[displayMember]; }).join(format); } return value.join(format) || placeholder; } let treeChildren2 = this.props.dataSource.reduce((a, b) => { return a.concat(b); }, []); treeChildren2 = treeChildren2.filter((item) => { return ~value.indexOf(item.value); }); return treeChildren2.map((v) => { return v[displayMember]; }).join(format) || placeholder; // return value.join(format) || placeholder; }; return ( <div className={`${prefixCls}`} onClick={() => this.handleClick()}> <div className={inputCls}> <input type="hidden" value={this.state.value} /> {display()} </div> <div className={classes} onClick={e => onContainerClick(e)}> <Popup className="za-popup-inner" visible={this.state.visible} onMaskClick={() => this.close('visible')}> <div className={`${prefixCls}-wrapper`}> <div className={`${prefixCls}-header`}> <div className={`${prefixCls}-cancel`} onClick={() => this.onCancel()}>{cancelText}</div> <div className={`${prefixCls}-title`}>{title}</div> <div className={`${prefixCls}-submit`} onClick={() => this.onOk()}>{okText}</div> </div> <div className={`${prefixCls}-mask-top`}> <div className={`${prefixCls}-mask-bottom`}> {PickerCol} </div> </div> </div> </Popup> </div> </div> ); } } Picker.propTypes = { visible: PropTypes.bool, placeholder: PropTypes.string, title: PropTypes.string, cancelText: PropTypes.string, okText: PropTypes.string, format: PropTypes.string, disabled: PropTypes.bool, dataSource: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.object, PropTypes.array])).isRequired, cols: PropTypes.number, onOk: PropTypes.func.isRequired, onCancel: PropTypes.func, onMaskClick: PropTypes.func, prefixCls: PropTypes.string, displayMember: PropTypes.string, valueMember: PropTypes.string, }; Picker.defaultProps = { visible: false, placeholder: '请选择', title: '请选择', cancelText: '取消', okText: '确定', format: '', disabled: false, dataSource: [], value: [], onClick: () => {}, onChange: () => {}, onOk: () => {}, onCancel: () => {}, onMaskClick: () => {}, prefixCls: 'za-picker', displayMember: 'label', valueMember: 'value', }; export default Picker;