mirror of
https://github.com/ant-design/ant-design.git
synced 2025-01-19 14:53:16 +08:00
Merge branch 'master' of github.com:ant-design/ant-design
This commit is contained in:
commit
64899c5da2
@ -1,12 +1,12 @@
|
||||
import React from 'react';
|
||||
import { PropTypes } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import createDOMForm from 'rc-form/lib/createDOMForm';
|
||||
import PureRenderMixin from 'rc-util/lib/PureRenderMixin';
|
||||
import omit from 'omit.js';
|
||||
import warning from 'warning';
|
||||
import assign from 'object-assign';
|
||||
import warning from '../_util/warning';
|
||||
import FormItem from './FormItem';
|
||||
import createDOMForm from 'rc-form/lib/createDOMForm';
|
||||
import { FIELD_META_PROP } from './constants';
|
||||
|
||||
export interface FormCreateOption {
|
||||
@ -121,14 +121,14 @@ export default class Form extends React.Component<FormProps, any> {
|
||||
};
|
||||
},
|
||||
componentWillMount() {
|
||||
this.getFieldProps = this.deprecatedGetFieldProps;
|
||||
this.__getFieldProps = this.props.form.getFieldProps;
|
||||
},
|
||||
deprecatedGetFieldProps(name, option) {
|
||||
warning(
|
||||
false,
|
||||
'`getFieldProps` is not recommended, please use `getFieldDecorator` instead'
|
||||
);
|
||||
return this.getFieldProps(name, option);
|
||||
return this.__getFieldProps(name, option);
|
||||
},
|
||||
render() {
|
||||
this.props.form.getFieldProps = this.deprecatedGetFieldProps;
|
||||
|
@ -16,47 +16,47 @@ The most basic usage of `Transfer` involves providing the source data and target
|
||||
````jsx
|
||||
import { Transfer } from 'antd';
|
||||
|
||||
const mockData = [];
|
||||
for (let i = 0; i < 20; i++) {
|
||||
mockData.push({
|
||||
key: i.toString(),
|
||||
title: `content${i + 1}`,
|
||||
description: `description of content${i + 1}`,
|
||||
disabled: Math.random() * 3 < 1,
|
||||
});
|
||||
}
|
||||
|
||||
const targetKeys = mockData
|
||||
.filter(() => Math.random() * 2 > 1)
|
||||
.map(item => item.key);
|
||||
|
||||
const App = React.createClass({
|
||||
getInitialState() {
|
||||
return {
|
||||
mockData: [],
|
||||
targetKeys: [],
|
||||
targetKeys,
|
||||
selectedKeys: [],
|
||||
};
|
||||
},
|
||||
componentDidMount() {
|
||||
this.getMock();
|
||||
},
|
||||
getMock() {
|
||||
const targetKeys = [];
|
||||
const mockData = [];
|
||||
for (let i = 0; i < 20; i++) {
|
||||
const data = {
|
||||
key: i.toString(),
|
||||
title: `content${i + 1}`,
|
||||
description: `description of content${i + 1}`,
|
||||
chosen: Math.random() * 2 > 1,
|
||||
disabled: Math.random() * 3 < 1,
|
||||
};
|
||||
if (data.chosen) {
|
||||
targetKeys.push(data.key);
|
||||
}
|
||||
mockData.push(data);
|
||||
}
|
||||
this.setState({ mockData, targetKeys });
|
||||
},
|
||||
handleChange(targetKeys, direction, moveKeys) {
|
||||
console.log(targetKeys, direction, moveKeys);
|
||||
this.setState({ targetKeys });
|
||||
handleChange(nextTargetKeys, direction, moveKeys) {
|
||||
this.setState({ targetKeys: nextTargetKeys });
|
||||
|
||||
console.log('targetKeys: ', targetKeys);
|
||||
console.log('direction: ', direction);
|
||||
console.log('moveKeys: ', moveKeys);
|
||||
},
|
||||
handleSelectChange(sourceSelectedKeys, targetSelectedKeys) {
|
||||
this.setState({ selectedKeys: [...sourceSelectedKeys, ...targetSelectedKeys] });
|
||||
|
||||
console.log('sourceSelectedKeys: ', sourceSelectedKeys);
|
||||
console.log('targetSelectedKeys: ', targetSelectedKeys);
|
||||
},
|
||||
render() {
|
||||
const state = this.state;
|
||||
return (
|
||||
<Transfer
|
||||
dataSource={this.state.mockData}
|
||||
targetKeys={this.state.targetKeys}
|
||||
dataSource={mockData}
|
||||
targetKeys={state.targetKeys}
|
||||
selectedKeys={state.selectedKeys}
|
||||
onChange={this.handleChange}
|
||||
onSelectChange={this.handleSelectChange}
|
||||
render={item => item.title}
|
||||
|
@ -19,17 +19,19 @@ To transfer the elements between two columns in an intuitive and efficient way.
|
||||
|-----------|------------------------------------------|------------|--------|
|
||||
| dataSource | Used for setting the source data. The elements that are part of this array will be present the left column. Except the elements whose keys are included in `targetKeys` prop. | Array | [] |
|
||||
| render | The function to generate the item shown on a column. Based on an record (element of the dataSource array), this function should return a React element which is generated from that record. | Function(record) | |
|
||||
| targetKeys | A set of keys of elements that are listed on the right column. | Array | [] |
|
||||
| onChange | A callback function that is executed when the transfer between columns is complete. | Function(targetKeys, direction, moveKeys) | |
|
||||
| onSelectChange | A callback function which is executed when selected items are changed. | Function(sourceSelectedKeys, targetSelectedKeys) | |
|
||||
| targetKeys | A set of keys of elements that are listed on the right column. | string[] | [] |
|
||||
| selectedKeys | A set of keys of selected items. | string[] | [] |
|
||||
| onChange | A callback function that is executed when the transfer between columns is complete. | (targetKeys, direction, moveKeys): void | |
|
||||
| onSelectChange | A callback function which is executed when selected items are changed. | (sourceSelectedKeys, targetSelectedKeys): void | |
|
||||
| listStyle | A custom CSS style used for rendering the transfer columns. | Object | |
|
||||
| className | A custom CSS class. | String | |
|
||||
| titles | A set of titles that are sorted from left to right. | Array | ['Source, 'Target] |
|
||||
| operations | A set of operations that are sorted from top to bottom. | Array | [] |
|
||||
| showSearch | If included, a search box is shown on each column. | Boolean | false |
|
||||
| filterOption | A function to determine whether an item should show in search result list | (inputValue, option): boolean | |
|
||||
| searchPlaceholder | The hint text of the search box. | String | 'Search here' |
|
||||
| notFoundContent | Text to display when a column is empty. | React.node | 'The list is empty' |
|
||||
| footer | A function used for rendering the footer. | Function(props) | |
|
||||
| notFoundContent | Text to display when a column is empty. | React.ReactNode | 'The list is empty' |
|
||||
| footer | A function used for rendering the footer. | (props): React.ReactNode | |
|
||||
| lazy | property of [react-lazy-load](https://github.com/loktar00/react-lazy-load) for lazy rendering items | Object | `{ height: 32, offset: 32 }` |
|
||||
|
||||
## Warning
|
||||
|
@ -19,18 +19,19 @@ export interface TransferItem {
|
||||
export interface TransferProps {
|
||||
dataSource: TransferItem[];
|
||||
targetKeys: string[];
|
||||
render?: (record: TransferItem) => any;
|
||||
onChange?: (targetKeys: TransferItem[], direction: string, moveKeys: any) => void;
|
||||
selectedKeys?: string[];
|
||||
render?: (record: TransferItem) => React.ReactNode;
|
||||
onChange?: (targetKeys: string[], direction: string, moveKeys: any) => void;
|
||||
onSelectChange?: (sourceSelectedKeys: string[], targetSelectedKeys: string[]) => void;
|
||||
listStyle?: React.CSSProperties;
|
||||
className?: string;
|
||||
prefixCls?: string;
|
||||
className?: string;
|
||||
titles?: string[];
|
||||
operations?: string[];
|
||||
showSearch?: boolean;
|
||||
searchPlaceholder?: string;
|
||||
notFoundContent?: React.ReactNode;
|
||||
footer?: (props: any) => any;
|
||||
footer?: (props: any) => React.ReactNode;
|
||||
style?: React.CSSProperties;
|
||||
filterOption: (inputValue: any, item: any) => boolean;
|
||||
body?: (props: any) => any;
|
||||
@ -46,6 +47,7 @@ export interface TransferContext {
|
||||
|
||||
const defaultTitles = ['源列表', '目的列表'];
|
||||
export default class Transfer extends React.Component<TransferProps, any> {
|
||||
// For high-level customized Transfer @dqaria
|
||||
static List = List;
|
||||
static Operation = Operation;
|
||||
static Search = Search;
|
||||
@ -84,18 +86,20 @@ export default class Transfer extends React.Component<TransferProps, any> {
|
||||
context: TransferContext;
|
||||
splitedDataSource: any;
|
||||
|
||||
constructor(props) {
|
||||
constructor(props: TransferProps) {
|
||||
super(props);
|
||||
|
||||
const { selectedKeys = [], targetKeys = [] } = props;
|
||||
this.state = {
|
||||
leftFilter: '',
|
||||
rightFilter: '',
|
||||
leftCheckedKeys: [],
|
||||
rightCheckedKeys: [],
|
||||
sourceSelectedKeys: selectedKeys.filter(key => targetKeys.indexOf(key) === -1),
|
||||
targetSelectedKeys: selectedKeys.filter(key => targetKeys.indexOf(key) > -1),
|
||||
};
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const { leftCheckedKeys, rightCheckedKeys } = this.state;
|
||||
componentWillReceiveProps(nextProps: TransferProps) {
|
||||
const { sourceSelectedKeys, targetSelectedKeys } = this.state;
|
||||
if (nextProps.targetKeys !== this.props.targetKeys ||
|
||||
nextProps.dataSource !== this.props.dataSource) {
|
||||
// clear cached splited dataSource
|
||||
@ -108,12 +112,19 @@ export default class Transfer extends React.Component<TransferProps, any> {
|
||||
// clear key nolonger existed
|
||||
// clear checkedKeys according to targetKeys
|
||||
this.setState({
|
||||
leftCheckedKeys: leftCheckedKeys.filter(existInDateSourcekey)
|
||||
sourceSelectedKeys: sourceSelectedKeys.filter(existInDateSourcekey)
|
||||
.filter(data => targetKeys.filter(key => key === data).length === 0),
|
||||
rightCheckedKeys: rightCheckedKeys.filter(existInDateSourcekey)
|
||||
targetSelectedKeys: targetSelectedKeys.filter(existInDateSourcekey)
|
||||
.filter(data => targetKeys.filter(key => key === data).length > 0),
|
||||
});
|
||||
}
|
||||
if (nextProps.selectedKeys) {
|
||||
const targetKeys = nextProps.targetKeys;
|
||||
this.setState({
|
||||
sourceSelectedKeys: nextProps.selectedKeys.filter(key => targetKeys.indexOf(key) === -1),
|
||||
targetSelectedKeys: nextProps.selectedKeys.filter(key => targetKeys.indexOf(key) > -1),
|
||||
});
|
||||
}
|
||||
}
|
||||
splitDataSource(props: TransferProps) {
|
||||
if (this.splitedDataSource) {
|
||||
@ -146,8 +157,8 @@ export default class Transfer extends React.Component<TransferProps, any> {
|
||||
|
||||
moveTo = (direction) => {
|
||||
const { targetKeys = [], onChange } = this.props;
|
||||
const { leftCheckedKeys, rightCheckedKeys } = this.state;
|
||||
const moveKeys = direction === 'right' ? leftCheckedKeys : rightCheckedKeys;
|
||||
const { sourceSelectedKeys, targetSelectedKeys } = this.state;
|
||||
const moveKeys = direction === 'right' ? sourceSelectedKeys : targetSelectedKeys;
|
||||
// move items to target box
|
||||
const newTargetKeys = direction === 'right'
|
||||
? moveKeys.concat(targetKeys)
|
||||
@ -156,7 +167,7 @@ export default class Transfer extends React.Component<TransferProps, any> {
|
||||
// empty checked keys
|
||||
const oppositeDirection = direction === 'right' ? 'left' : 'right';
|
||||
this.setState({
|
||||
[`${oppositeDirection}CheckedKeys`]: [],
|
||||
[this.getSelectedKeysName(oppositeDirection)]: [],
|
||||
});
|
||||
this.handleSelectChange(oppositeDirection, []);
|
||||
|
||||
@ -169,25 +180,28 @@ export default class Transfer extends React.Component<TransferProps, any> {
|
||||
moveToRight = () => this.moveTo('right')
|
||||
|
||||
handleSelectChange(direction: string, holder: string[]) {
|
||||
const { leftCheckedKeys, rightCheckedKeys } = this.state;
|
||||
const { sourceSelectedKeys, targetSelectedKeys } = this.state;
|
||||
const onSelectChange = this.props.onSelectChange;
|
||||
if (!onSelectChange) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (direction === 'left') {
|
||||
onSelectChange(holder, rightCheckedKeys);
|
||||
onSelectChange(holder, targetSelectedKeys);
|
||||
} else {
|
||||
onSelectChange(leftCheckedKeys, holder);
|
||||
onSelectChange(sourceSelectedKeys, holder);
|
||||
}
|
||||
}
|
||||
|
||||
handleSelectAll = (direction, filteredDataSource, checkAll) => {
|
||||
const holder = checkAll ? [] : filteredDataSource.map(item => item.key);
|
||||
this.setState({
|
||||
[`${direction}CheckedKeys`]: holder,
|
||||
});
|
||||
this.handleSelectChange(direction, holder);
|
||||
|
||||
if (!this.props.selectedKeys) {
|
||||
this.setState({
|
||||
[this.getSelectedKeysName(direction)]: holder,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
handleLeftSelectAll = (filteredDataSource, checkAll) => (
|
||||
@ -217,8 +231,8 @@ export default class Transfer extends React.Component<TransferProps, any> {
|
||||
handleRightClear = () => this.handleClear('right')
|
||||
|
||||
handleSelect = (direction, selectedItem, checked) => {
|
||||
const { leftCheckedKeys, rightCheckedKeys } = this.state;
|
||||
const holder = direction === 'left' ? [...leftCheckedKeys] : [...rightCheckedKeys];
|
||||
const { sourceSelectedKeys, targetSelectedKeys } = this.state;
|
||||
const holder = direction === 'left' ? [...sourceSelectedKeys] : [...targetSelectedKeys];
|
||||
let index;
|
||||
holder.forEach((key, i) => {
|
||||
if (key === selectedItem.key) {
|
||||
@ -231,10 +245,13 @@ export default class Transfer extends React.Component<TransferProps, any> {
|
||||
if (checked) {
|
||||
holder.push(selectedItem.key);
|
||||
}
|
||||
this.setState({
|
||||
[`${direction}CheckedKeys`]: holder,
|
||||
});
|
||||
this.handleSelectChange(direction, holder);
|
||||
|
||||
if (!this.props.selectedKeys) {
|
||||
this.setState({
|
||||
[this.getSelectedKeysName(direction)]: holder,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
handleLeftSelect = (selectedItem, checked) => this.handleSelect('left', selectedItem, checked);
|
||||
@ -253,17 +270,21 @@ export default class Transfer extends React.Component<TransferProps, any> {
|
||||
return defaultTitles;
|
||||
}
|
||||
|
||||
getSelectedKeysName(direction) {
|
||||
return direction === 'left' ? 'sourceSelectedKeys' : 'targetSelectedKeys';
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
prefixCls = 'ant-transfer', operations = [], showSearch, notFoundContent,
|
||||
searchPlaceholder, body, footer, listStyle, className = '',
|
||||
filterOption, render, lazy,
|
||||
} = this.props;
|
||||
const { leftFilter, rightFilter, leftCheckedKeys, rightCheckedKeys } = this.state;
|
||||
const { leftFilter, rightFilter, sourceSelectedKeys, targetSelectedKeys } = this.state;
|
||||
|
||||
const { leftDataSource, rightDataSource } = this.splitDataSource(this.props);
|
||||
const leftActive = rightCheckedKeys.length > 0;
|
||||
const rightActive = leftCheckedKeys.length > 0;
|
||||
const leftActive = targetSelectedKeys.length > 0;
|
||||
const rightActive = sourceSelectedKeys.length > 0;
|
||||
|
||||
const cls = classNames({
|
||||
[className]: !!className,
|
||||
@ -279,7 +300,7 @@ export default class Transfer extends React.Component<TransferProps, any> {
|
||||
filter={leftFilter}
|
||||
filterOption={filterOption}
|
||||
style={listStyle}
|
||||
checkedKeys={leftCheckedKeys}
|
||||
checkedKeys={sourceSelectedKeys}
|
||||
handleFilter={this.handleLeftFilter}
|
||||
handleClear={this.handleLeftClear}
|
||||
handleSelect={this.handleLeftSelect}
|
||||
@ -308,7 +329,7 @@ export default class Transfer extends React.Component<TransferProps, any> {
|
||||
filter={rightFilter}
|
||||
filterOption={filterOption}
|
||||
style={listStyle}
|
||||
checkedKeys={rightCheckedKeys}
|
||||
checkedKeys={targetSelectedKeys}
|
||||
handleFilter={this.handleRightFilter}
|
||||
handleClear={this.handleRightClear}
|
||||
handleSelect={this.handleRightSelect}
|
||||
|
@ -20,18 +20,19 @@ title: Transfer
|
||||
|-----------|------------------------------------------|------------|--------|
|
||||
| dataSource | 数据源,其中的数据将会被渲染到左边一栏中,`targetKeys` 中指定的除外。 | Array | [] |
|
||||
| render | 每行数据渲染函数,该函数的入参为 `dataSource` 中的项,返回值为 React element | Function(record) | |
|
||||
| targetKeys | 显示在右侧框数据的key集合 | Array | [] |
|
||||
| onChange | 选项在两栏之间转移时的回调函数 | Function(targetKeys, direction, moveKeys) | |
|
||||
| onSelectChange | 选中项发生改变时的回调函数 | Function(sourceSelectedKeys, targetSelectedKeys) | |
|
||||
| targetKeys | 显示在右侧框数据的key集合 | string[] | [] |
|
||||
| selectedKeys | 设置哪些项应该被选中 | string[] | [] |
|
||||
| onChange | 选项在两栏之间转移时的回调函数 | (targetKeys, direction, moveKeys): void | |
|
||||
| onSelectChange | 选中项发生改变时的回调函数 | (sourceSelectedKeys, targetSelectedKeys): void | |
|
||||
| listStyle | 两个穿梭框的自定义样式 | Object | |
|
||||
| className | 自定义类 | String | |
|
||||
| titles | 标题集合,顺序从左至右 | Array | ['源列表', '目的列表'] |
|
||||
| operations | 操作文案集合,顺序从上至下 | Array | [] |
|
||||
| showSearch | 是否显示搜索框 | Boolean | false |
|
||||
| filterOption | 接收 `inputValue` `option` 两个参数,当 `option` 符合筛选条件时,应返回 `true`,反之则返回 `false`。| Function(inputValue, option) | |
|
||||
| searchPlaceholder | 搜索框的默认值 | String | '请输入搜索内容' |
|
||||
| notFoundContent | 当列表为空时显示的内容 | React.node | '列表为空' |
|
||||
| footer | 底部渲染函数 | Function(props) | |
|
||||
| filterOption | 接收 `inputValue` `option` 两个参数,当 `option` 符合筛选条件时,应返回 `true`,反之则返回 `false`。| (inputValue, option): boolean | |
|
||||
| searchPlaceholder | 搜索框的默认值 | string | '请输入搜索内容' |
|
||||
| notFoundContent | 当列表为空时显示的内容 | React.ReactNode | '列表为空' |
|
||||
| footer | 底部渲染函数 | (props): React.ReactNode | |
|
||||
| lazy | Transfer 使用了 [react-lazy-load](https://github.com/loktar00/react-lazy-load) 优化性能,这里可以设置相关参数 | Object | `{ height: 32, offset: 32 }` |
|
||||
|
||||
## 注意
|
||||
|
Loading…
Reference in New Issue
Block a user