ant-design/components/transfer/index.jsx

249 lines
7.3 KiB
React
Raw Normal View History

2015-11-25 23:17:06 +08:00
import React, { Component, PropTypes } from 'react';
2015-12-25 17:53:35 +08:00
import List from './list';
import Operation from './operation';
import Search from './search';
2015-12-24 17:44:54 +08:00
import classNames from 'classnames';
2015-11-25 23:17:06 +08:00
function noop() {
}
class Transfer extends Component {
constructor(props) {
super(props);
this.state = {
2015-11-26 16:07:11 +08:00
leftFilter: '',
rightFilter: '',
2015-12-21 15:29:02 +08:00
leftCheckedKeys: [],
2015-12-23 19:41:56 +08:00
rightCheckedKeys: [],
2015-11-25 23:17:06 +08:00
};
}
2015-12-21 15:29:02 +08:00
splitDataSource() {
const { targetKeys, dataSource } = this.props;
2015-11-26 11:18:37 +08:00
2015-12-21 15:29:02 +08:00
let leftDataSource = Object.assign([], dataSource);
let rightDataSource = [];
2015-12-17 16:08:16 +08:00
2015-12-21 15:29:02 +08:00
if ( targetKeys.length > 0 ) {
targetKeys.forEach((targetKey) => {
rightDataSource.push(leftDataSource.find((data, index) => {
if ( data.key === targetKey ) {
2015-12-21 15:29:02 +08:00
leftDataSource.splice(index, 1);
return true;
}
}));
2015-12-17 16:08:16 +08:00
});
}
2015-12-21 15:29:02 +08:00
return {
leftDataSource: leftDataSource,
rightDataSource: rightDataSource,
};
2015-12-16 23:02:49 +08:00
}
2015-11-25 23:17:06 +08:00
moveTo(direction) {
2015-12-21 15:29:02 +08:00
const { targetKeys } = this.props;
const { leftCheckedKeys, rightCheckedKeys } = this.state;
// move items to target box
const newTargetKeys = direction === 'right' ?
leftCheckedKeys.concat(targetKeys) :
targetKeys.filter((targetKey) => !rightCheckedKeys.some((checkedKey) => targetKey === checkedKey));
// empty checked keys
this.setState({
[ direction === 'right' ? 'leftCheckedKeys' : 'rightCheckedKeys' ]: [],
2015-12-21 15:29:02 +08:00
});
this.props.onChange(newTargetKeys);
2015-11-25 23:17:06 +08:00
}
2015-12-23 19:41:56 +08:00
getGlobalCheckStatus(direction) {
2015-12-21 15:29:02 +08:00
const { leftDataSource, rightDataSource } = this.splitDataSource();
2015-12-23 19:41:56 +08:00
const { leftFilter, rightFilter, leftCheckedKeys, rightCheckedKeys } = this.state;
2015-12-21 15:29:02 +08:00
const dataSource = direction === 'left' ? leftDataSource : rightDataSource;
2015-12-23 19:41:56 +08:00
const filter = direction === 'left' ? leftFilter : rightFilter;
const checkedKeys = direction === 'left' ? leftCheckedKeys : rightCheckedKeys;
const filteredDataSource = this.filterDataSource(dataSource, filter);
let globalCheckStatus;
if ( checkedKeys.length > 0 ) {
if ( checkedKeys.length < filteredDataSource.length ) {
globalCheckStatus = 'part';
} else {
globalCheckStatus = 'all';
}
} else {
globalCheckStatus = 'none';
}
return globalCheckStatus;
}
filterDataSource(dataSource, filter) {
return dataSource.filter(item => {
2015-12-24 17:44:54 +08:00
const itemText = this.props.render(item);
return this.matchFilter(itemText, filter);
2015-12-23 19:41:56 +08:00
});
}
matchFilter(text, filterText) {
const regex = new RegExp(filterText);
return text.match(regex);
}
handleSelectAll(direction) {
const { leftDataSource, rightDataSource } = this.splitDataSource();
const { leftFilter, rightFilter } = this.state;
const dataSource = direction === 'left' ? leftDataSource : rightDataSource;
const filter = direction === 'left' ? leftFilter : rightFilter;
const checkStatus = this.getGlobalCheckStatus(direction);
2015-12-21 15:29:02 +08:00
let holder = [];
2015-12-23 19:41:56 +08:00
if ( checkStatus === 'all' ) {
2015-12-21 15:29:02 +08:00
holder = [];
} else {
2015-12-23 19:41:56 +08:00
holder = this.filterDataSource(dataSource, filter).map(item => item.key);
2015-11-25 23:17:06 +08:00
}
this.setState({
2015-12-23 23:12:20 +08:00
[direction + 'CheckedKeys']: holder,
2015-11-25 23:17:06 +08:00
});
}
2015-11-26 16:07:11 +08:00
handleFilter(direction, e) {
2015-12-21 15:29:02 +08:00
this.setState({
2015-12-23 19:41:56 +08:00
// deselect all
2015-12-23 23:12:20 +08:00
[direction + 'CheckedKeys']: [],
2015-12-23 19:41:56 +08:00
// add filter
2015-12-23 23:12:20 +08:00
[direction + 'Filter']: e.target.value,
2015-12-21 15:29:02 +08:00
});
2015-11-26 16:07:11 +08:00
}
2015-12-17 16:08:16 +08:00
handleClear(direction) {
2015-12-21 15:29:02 +08:00
this.setState({
2015-12-23 23:12:20 +08:00
[direction + 'Filter']: '',
2015-11-25 23:17:06 +08:00
});
2015-12-21 15:29:02 +08:00
}
2015-11-25 23:17:06 +08:00
2015-12-21 15:29:02 +08:00
handleSelect(direction, selectedItem, checked) {
const { leftCheckedKeys, rightCheckedKeys } = this.state;
const holder = direction === 'left' ? leftCheckedKeys : rightCheckedKeys;
const index = holder.findIndex((key) => key === selectedItem.key);
if ( index > -1 ) {
holder.splice(index, 1);
}
if ( checked ) {
holder.push(selectedItem.key);
}
2015-11-25 23:17:06 +08:00
this.setState({
2015-12-23 23:12:20 +08:00
[direction + 'CheckedKeys']: holder,
2015-11-25 23:17:06 +08:00
});
}
render() {
2015-12-24 17:44:54 +08:00
const {
prefixCls, titles, operations, showSearch,
searchPlaceholder, body, footer, listStyle, className,
} = this.props;
2015-12-21 15:29:02 +08:00
const { leftFilter, rightFilter, leftCheckedKeys, rightCheckedKeys } = this.state;
2015-11-25 23:17:06 +08:00
2015-12-21 15:29:02 +08:00
const { leftDataSource, rightDataSource } = this.splitDataSource();
2015-12-23 19:41:56 +08:00
const leftActive = rightCheckedKeys.length > 0;
const rightActive = leftCheckedKeys.length > 0;
const leftCheckStatus = this.getGlobalCheckStatus('left');
const rightCheckStatus = this.getGlobalCheckStatus('right');
2015-11-25 23:17:06 +08:00
2015-12-24 17:44:54 +08:00
const cls = classNames({
[className]: !!className,
prefixCls: true,
});
return (
<div className={cls}>
<List titleText={titles[0]}
dataSource={leftDataSource}
filter={leftFilter}
style={listStyle}
checkedKeys={leftCheckedKeys}
checkStatus={leftCheckStatus}
handleFilter={this.handleFilter.bind(this, 'left')}
handleClear={this.handleClear.bind(this, 'left')}
handleSelect={this.handleSelect.bind(this, 'left')}
handleSelectAll={this.handleSelectAll.bind(this, 'left')}
position="left"
render={this.props.render}
showSearch={showSearch}
searchPlaceholder={searchPlaceholder}
body={body}
footer={footer}
prefixCls={prefixCls + '-list'}/>
<Operation rightActive={rightActive}
rightArrowText={operations[0]}
moveToRight={this.moveTo.bind(this, 'right')}
leftActive={leftActive}
leftArrowText={operations[1]}
moveToLeft={this.moveTo.bind(this, 'left')}
className={prefixCls + '-operation'}/>
<List titleText={titles[1]}
dataSource={rightDataSource}
filter={rightFilter}
style={listStyle}
checkedKeys={rightCheckedKeys}
checkStatus={rightCheckStatus}
handleFilter={this.handleFilter.bind(this, 'right')}
handleClear={this.handleClear.bind(this, 'right')}
handleSelect={this.handleSelect.bind(this, 'right')}
handleSelectAll={this.handleSelectAll.bind(this, 'right')}
position="right"
render={this.props.render}
showSearch={showSearch}
searchPlaceholder={searchPlaceholder}
body={body}
footer={footer}
prefixCls={prefixCls + '-list'}/>
</div>
);
2015-11-25 23:17:06 +08:00
}
}
Transfer.defaultProps = {
prefixCls: 'ant-transfer',
2015-11-26 11:18:37 +08:00
dataSource: [],
2015-12-21 15:29:02 +08:00
render: noop,
targetKeys: [],
2015-11-25 23:17:06 +08:00
onChange: noop,
2015-12-21 15:29:02 +08:00
titles: ['源列表', '目的列表'],
operations: [],
2015-11-25 23:17:06 +08:00
showSearch: false,
searchPlaceholder: '请输入搜索内容',
2015-12-15 17:08:34 +08:00
body: noop,
2015-12-21 15:29:02 +08:00
footer: noop,
2015-11-25 23:17:06 +08:00
};
Transfer.propTypes = {
prefixCls: PropTypes.string,
dataSource: PropTypes.array,
2015-12-21 15:29:02 +08:00
render: PropTypes.func,
targetKeys: PropTypes.array,
onChange: PropTypes.func,
2015-12-23 22:59:42 +08:00
height: PropTypes.number,
2015-12-24 17:44:54 +08:00
listStyle: PropTypes.object,
className: PropTypes.string,
2015-12-21 15:29:02 +08:00
titles: PropTypes.array,
operations: PropTypes.array,
2015-11-25 23:17:06 +08:00
showSearch: PropTypes.bool,
searchPlaceholder: PropTypes.string,
2015-12-21 15:29:02 +08:00
body: PropTypes.func,
footer: PropTypes.func,
2015-11-25 23:17:06 +08:00
};
2015-12-23 19:41:56 +08:00
Transfer.List = List;
Transfer.Operation = Operation;
Transfer.Search = Search;
2015-11-25 23:17:06 +08:00
export default Transfer;