Transfer
Double column transfer choice box.
When To Use#
Transfer the elements between two columns in an intuitive and efficient way.
One or more elements can be selected from either column, one click on the proper direction
button, and the transfer is done. The left column is considered the source
and the right column is considered the target
. As you can see in the API description, these names are reflected in.
Examples
- content1
- content2
- content4
- content5
- content7
- content8
- content10
- content11
- content13
- content14
- content16
- content17
- content19
- content20
- content3
- content6
- content9
- content12
- content15
- content18
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: i % 3 < 1,
});
}
const targetKeys = mockData
.filter(item => +item.key % 3 > 1)
.map(item => item.key);
class App extends React.Component {
state = {
targetKeys,
selectedKeys: [],
}
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);
}
handleScroll = (direction, e) => {
console.log('direction:', direction);
console.log('target:', e.target);
}
render() {
const state = this.state;
return (
<Transfer
dataSource={mockData}
titles={['Source', 'Target']}
targetKeys={state.targetKeys}
selectedKeys={state.selectedKeys}
onChange={this.handleChange}
onSelectChange={this.handleSelectChange}
onScroll={this.handleScroll}
render={item => item.title}
/>
);
}
}
ReactDOM.render(<App />, mountNode);
- content1
- content3
- content5
- content9
- content10
- content11
- content17
- content18
- content2
- content4
- content6
- content7
- content8
- content12
- content13
- content14
- content15
- content16
- content19
- content20
import { Transfer } from 'antd';
class App extends React.Component {
state = {
mockData: [],
targetKeys: [],
}
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,
};
if (data.chosen) {
targetKeys.push(data.key);
}
mockData.push(data);
}
this.setState({ mockData, targetKeys });
}
filterOption = (inputValue, option) => {
return option.description.indexOf(inputValue) > -1;
}
handleChange = (targetKeys) => {
this.setState({ targetKeys });
}
render() {
return (
<Transfer
dataSource={this.state.mockData}
showSearch
filterOption={this.filterOption}
targetKeys={this.state.targetKeys}
onChange={this.handleChange}
render={item => item.title}
/>
);
}
}
ReactDOM.render(<App />, mountNode);
import { Transfer, Button } from 'antd';
class App extends React.Component {
state = {
mockData: [],
targetKeys: [],
}
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,
};
if (data.chosen) {
targetKeys.push(data.key);
}
mockData.push(data);
}
this.setState({ mockData, targetKeys });
}
handleChange = (targetKeys) => {
this.setState({ targetKeys });
}
renderFooter = () => {
return (
<Button
size="small"
style={{ float: 'right', margin: 5 }}
onClick={this.getMock}
>
reload
</Button>
);
}
render() {
return (
<Transfer
dataSource={this.state.mockData}
showSearch
listStyle={{
width: 250,
height: 300,
}}
operations={['to right', 'to left']}
targetKeys={this.state.targetKeys}
onChange={this.handleChange}
render={item => `${item.title}-${item.description}`}
footer={this.renderFooter}
/>
);
}
}
ReactDOM.render(<App />, mountNode);
- content1 - description of content1
- content2 - description of content2
- content3 - description of content3
- content8 - description of content8
- content10 - description of content10
- content13 - description of content13
- content14 - description of content14
- content15 - description of content15
- content16 - description of content16
- content19 - description of content19
- content20 - description of content20
- content4 - description of content4
- content5 - description of content5
- content6 - description of content6
- content7 - description of content7
- content9 - description of content9
- content11 - description of content11
- content12 - description of content12
- content17 - description of content17
- content18 - description of content18
import { Transfer } from 'antd';
class App extends React.Component {
state = {
mockData: [],
targetKeys: [],
}
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,
};
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 });
}
renderItem = (item) => {
const customLabel = (
<span className="custom-item">
{item.title} - {item.description}
</span>
);
return {
label: customLabel, // for displayed item
value: item.title, // for title and filter matching
};
}
render() {
return (
<Transfer
dataSource={this.state.mockData}
listStyle={{
width: 300,
height: 300,
}}
targetKeys={this.state.targetKeys}
onChange={this.handleChange}
render={this.renderItem}
/>
);
}
}
ReactDOM.render(<App />, mountNode);
API#
Property | Description | Type | Default |
---|---|---|---|
className | A custom CSS class. | string | '', '' |
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. | TransferItem[] | [] |
filterOption | A function to determine whether an item should show in search result list | (inputValue, option): boolean | |
footer | A function used for rendering the footer. | (props): ReactNode | |
lazy | property of react-lazy-load for lazy rendering items. Turn off it by set to false . | object|boolean | { height: 32, offset: 32 } |
listStyle | A custom CSS style used for rendering the transfer columns. | object | |
notFoundContent | Text to display when a column is empty. | string|ReactNode | 'The list is empty' |
operations | A set of operations that are sorted from bottom to top. | string[] | '>', '<' |
operationStyle | A custom CSS style used for rendering the operations column. | object | |
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. Also, it can return a plain object with value and label , label is a React element and value is for title | Function(record) | |
searchPlaceholder | The hint text of the search box. | string | 'Search here' |
selectedKeys | A set of keys of selected items. | string[] | [] |
showSearch | If included, a search box is shown on each column. | boolean | false |
style | A custom CSS style used for rendering wrapper element. | object | |
targetKeys | A set of keys of elements that are listed on the right column. | string[] | [] |
titles | A set of titles that are sorted from left to right. | string[] | - |
onChange | A callback function that is executed when the transfer between columns is complete. | (targetKeys, direction, moveKeys): void | |
onScroll | A callback function which is executed when scroll options list | (direction, event): void | |
onSearchChange | A callback function which is executed when search field are changed | (direction: 'left'|'right', event: Event): void | - |
onSelectChange | A callback function which is executed when selected items are changed. | (sourceSelectedKeys, targetSelectedKeys): void |
Warning#
According the standard of React, the key should always be supplied directly to the elements in the array. In Transfer, the keys should be set on the elements included in dataSource
array. By default, key
property is used as an unique identifier.
If there's no key
in your data, you should use rowKey
to specify the key that will be used for uniquely identify each element.
// eg. your primary key is `uid`
return <Transfer rowKey={record => record.uid} />;