ant-design/components/transfer/index.jsx

287 lines
8.7 KiB
React
Raw Normal View History

import React, { PropTypes } from 'react';
import List, { isRenderResultPlainObject } from './list';
2015-12-25 17:53:35 +08:00
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() {
}
export default class Transfer extends React.Component {
static List = List;
static Operation = Operation;
static Search = Search;
static defaultProps = {
prefixCls: 'ant-transfer',
dataSource: [],
render: noop,
targetKeys: [],
onChange: noop,
titles: ['源列表', '目的列表'],
operations: [],
showSearch: false,
body: noop,
footer: noop,
};
static propTypes = {
prefixCls: PropTypes.string,
dataSource: PropTypes.array,
render: PropTypes.func,
targetKeys: PropTypes.array,
onChange: PropTypes.func,
height: PropTypes.number,
listStyle: PropTypes.object,
className: PropTypes.string,
titles: PropTypes.array,
operations: PropTypes.array,
showSearch: PropTypes.bool,
searchPlaceholder: PropTypes.string,
notFoundContent: PropTypes.node,
body: PropTypes.func,
footer: PropTypes.func,
rowKey: PropTypes.func,
};
2015-11-25 23:17:06 +08:00
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
};
}
componentWillReceiveProps(nextProps) {
const { leftCheckedKeys, rightCheckedKeys } = this.state;
const { leftDataSource, rightDataSource } = this.splitDataSource(nextProps);
this.setState({
leftCheckedKeys: leftCheckedKeys.filter(data => leftDataSource.filter(leftData => leftData.key === data).length),
rightCheckedKeys: rightCheckedKeys.filter(data => rightDataSource.filter(rightData => rightData.key === data).length),
});
}
splitDataSource(props) {
const { targetKeys } = props;
let { dataSource } = props;
2015-11-26 11:18:37 +08:00
if (props.rowKey && typeof props.rowKey === 'function') {
dataSource = dataSource.map(record => {
record.key = props.rowKey(record);
return record;
});
}
2016-02-23 16:28:41 +08:00
let leftDataSource = [...dataSource];
2015-12-21 15:29:02 +08:00
let rightDataSource = [];
2015-12-17 16:08:16 +08:00
if (targetKeys.length > 0) {
2015-12-21 15:29:02 +08:00
targetKeys.forEach((targetKey) => {
rightDataSource.push(leftDataSource.filter((data, index) => {
if (data.key === targetKey) {
2015-12-21 15:29:02 +08:00
leftDataSource.splice(index, 1);
return true;
}
return false;
})[0]);
2015-12-17 16:08:16 +08:00
});
}
2015-12-21 15:29:02 +08:00
return {
leftDataSource,
rightDataSource,
2015-12-21 15:29:02 +08:00
};
2015-12-16 23:02:49 +08:00
}
moveTo = (direction) => {
2015-12-21 15:29:02 +08:00
const { targetKeys } = this.props;
const { leftCheckedKeys, rightCheckedKeys } = this.state;
2016-02-01 14:07:17 +08:00
const moveKeys = direction === 'right' ? leftCheckedKeys : rightCheckedKeys;
2015-12-21 15:29:02 +08:00
// move items to target box
2016-02-01 14:07:17 +08:00
const newTargetKeys = direction === 'right'
? moveKeys.concat(targetKeys)
: targetKeys.filter(targetKey => !moveKeys.some(checkedKey => targetKey === checkedKey));
2015-12-21 15:29:02 +08:00
// empty checked keys
this.setState({
[direction === 'right' ? 'leftCheckedKeys' : 'rightCheckedKeys']: [],
2015-12-21 15:29:02 +08:00
});
2016-02-01 14:07:17 +08:00
this.props.onChange(newTargetKeys, direction, moveKeys);
2015-11-25 23:17:06 +08:00
}
2016-03-30 17:06:19 +08:00
moveToLeft = () => this.moveTo('left')
moveToRight = () => this.moveTo('right')
2015-12-23 19:41:56 +08:00
getGlobalCheckStatus(direction) {
const { leftDataSource, rightDataSource } = this.splitDataSource(this.props);
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) {
2015-12-23 19:41:56 +08:00
globalCheckStatus = 'part';
} else {
globalCheckStatus = 'all';
}
} else {
globalCheckStatus = 'none';
}
return globalCheckStatus;
}
filterDataSource(dataSource, filter) {
return dataSource.filter(item => {
const renderResult = this.props.render(item);
let itemText;
if (isRenderResultPlainObject(renderResult)) {
itemText = renderResult.value;
} else {
itemText = renderResult;
}
2015-12-24 17:44:54 +08:00
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(this.props);
2015-12-23 19:41:56 +08:00
const { leftFilter, rightFilter } = this.state;
const dataSource = direction === 'left' ? leftDataSource : rightDataSource;
const filter = direction === 'left' ? leftFilter : rightFilter;
const checkStatus = this.getGlobalCheckStatus(direction);
2016-02-06 15:54:39 +08:00
const holder = (checkStatus === 'all') ? [] :
this.filterDataSource(dataSource, filter).map(item => item.key);
2015-11-25 23:17:06 +08:00
this.setState({
[`${direction}CheckedKeys`]: holder,
2015-11-25 23:17:06 +08:00
});
}
2016-03-30 17:06:19 +08:00
handleLeftSelectAll = () => this.handleSelectAll('left')
handleRightSelectAll = () => this.handleSelectAll('right')
handleFilter = (direction, e) => {
2015-12-21 15:29:02 +08:00
this.setState({
2015-12-23 19:41:56 +08:00
// deselect all
[`${direction}CheckedKeys`]: [],
2015-12-23 19:41:56 +08:00
// add filter
[`${direction}Filter`]: e.target.value,
2015-12-21 15:29:02 +08:00
});
2015-11-26 16:07:11 +08:00
}
2016-03-30 17:06:19 +08:00
handleLeftFilter = (e) => this.handleFilter('left', e)
handleRightFilter = (e) => this.handleFilter('right', e)
handleClear = (direction) => {
2015-12-21 15:29:02 +08:00
this.setState({
[`${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
2016-03-30 17:06:19 +08:00
handleLeftClear = () => this.handleClear('left')
handleRightClear = () => this.handleClear('right')
handleSelect = (direction, selectedItem, checked) => {
2015-12-21 15:29:02 +08:00
const { leftCheckedKeys, rightCheckedKeys } = this.state;
const holder = direction === 'left' ? leftCheckedKeys : rightCheckedKeys;
let index;
holder.forEach((key, i) => {
if (key === selectedItem.key) {
index = i;
}
});
if (index > -1) {
2015-12-21 15:29:02 +08:00
holder.splice(index, 1);
}
if (checked) {
2015-12-21 15:29:02 +08:00
holder.push(selectedItem.key);
}
2015-11-25 23:17:06 +08:00
this.setState({
[`${direction}CheckedKeys`]: holder,
2015-11-25 23:17:06 +08:00
});
}
2016-03-30 17:06:19 +08:00
handleLeftSelect = (selectedItem, checked) => this.handleSelect('left', selectedItem, checked);
handleRightSelect = (selectedItem, checked) => this.handleSelect('right', selectedItem, checked);
2015-11-25 23:17:06 +08:00
render() {
2015-12-24 17:44:54 +08:00
const {
prefixCls, titles, operations, showSearch, notFoundContent,
2015-12-24 17:44:54 +08:00
searchPlaceholder, body, footer, listStyle, className,
render,
2015-12-24 17:44:54 +08:00
} = 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
const { leftDataSource, rightDataSource } = this.splitDataSource(this.props);
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,
2016-03-29 17:19:31 +08:00
[prefixCls]: true,
2015-12-24 17:44:54 +08:00
});
return (
<div className={cls}>
<List titleText={titles[0]}
dataSource={leftDataSource}
filter={leftFilter}
style={listStyle}
checkedKeys={leftCheckedKeys}
checkStatus={leftCheckStatus}
2016-03-30 17:06:19 +08:00
handleFilter={this.handleLeftFilter}
handleClear={this.handleLeftClear}
handleSelect={this.handleLeftSelect}
handleSelectAll={this.handleLeftSelectAll}
position="left"
render={render}
showSearch={showSearch}
searchPlaceholder={searchPlaceholder}
notFoundContent={notFoundContent}
body={body}
footer={footer}
prefixCls={`${prefixCls}-list`} />
<Operation rightActive={rightActive}
rightArrowText={operations[0]}
2016-03-30 17:06:19 +08:00
moveToRight={this.moveToRight}
leftActive={leftActive}
leftArrowText={operations[1]}
2016-03-30 17:06:19 +08:00
moveToLeft={this.moveToLeft}
className={`${prefixCls}-operation`} />
<List titleText={titles[1]}
dataSource={rightDataSource}
filter={rightFilter}
style={listStyle}
checkedKeys={rightCheckedKeys}
checkStatus={rightCheckStatus}
2016-03-30 17:06:19 +08:00
handleFilter={this.handleRightFilter}
handleClear={this.handleRightClear}
handleSelect={this.handleRightSelect}
handleSelectAll={this.handleRightSelectAll}
position="right"
render={render}
showSearch={showSearch}
searchPlaceholder={searchPlaceholder}
notFoundContent={notFoundContent}
body={body}
footer={footer}
prefixCls={`${prefixCls}-list`} />
</div>
);
2015-11-25 23:17:06 +08:00
}
}