mirror of
https://github.com/ant-design/ant-design.git
synced 2024-11-24 11:10:01 +08:00
change api
This commit is contained in:
parent
0e82e14030
commit
765ce7bb67
@ -2,7 +2,7 @@
|
||||
|
||||
- order: 2
|
||||
|
||||
高级用法
|
||||
穿梭框高级用法
|
||||
|
||||
---
|
||||
|
||||
@ -13,7 +13,8 @@ const container = document.getElementById('components-transfer-demo-advanced');
|
||||
const App = React.createClass({
|
||||
getInitialState() {
|
||||
return {
|
||||
mockData: []
|
||||
mockData: [],
|
||||
targetKeys: [],
|
||||
};
|
||||
},
|
||||
|
||||
@ -22,23 +23,47 @@ const App = React.createClass({
|
||||
},
|
||||
|
||||
getMock() {
|
||||
let targetKeys = [];
|
||||
let mockData = [];
|
||||
for (let i = 0; i < 20; i++) {
|
||||
mockData.push({
|
||||
const data = {
|
||||
key: i,
|
||||
title: '内容' + (i + 1),
|
||||
value: (i + 1),
|
||||
description: '内容' + (i + 1) + '的描述',
|
||||
chosen: Math.random() * 2 > 1
|
||||
});
|
||||
};
|
||||
if (data.chosen) {
|
||||
targetKeys.push(data.key);
|
||||
}
|
||||
mockData.push(data);
|
||||
}
|
||||
this.setState({
|
||||
mockData: mockData
|
||||
mockData: mockData,
|
||||
targetKeys: targetKeys,
|
||||
});
|
||||
},
|
||||
|
||||
handleChange(targetKeys) {
|
||||
this.setState({
|
||||
targetKeys: targetKeys,
|
||||
});
|
||||
},
|
||||
|
||||
renderFooter(props) {
|
||||
return <Button type="primary" size="small" style={{ float: 'right', margin: '5' }}
|
||||
onClick={this.getMock}>刷新</Button>;
|
||||
},
|
||||
|
||||
render() {
|
||||
return <div>
|
||||
<Transfer defaultDataSource={this.state.mockData} />
|
||||
<Button onClick={this.getMock}>刷新数据</Button>
|
||||
<Transfer
|
||||
dataSource={this.state.mockData}
|
||||
showSearch
|
||||
operations={['hello', 'world']}
|
||||
targetKeys={this.state.targetKeys}
|
||||
onChange={this.handleChange}
|
||||
render={(item) => { return item.title + item.description; }}
|
||||
footer={this.renderFooter}/>
|
||||
</div>;
|
||||
}
|
||||
});
|
||||
|
@ -13,7 +13,8 @@ const container = document.getElementById('components-transfer-demo-basic');
|
||||
const App = React.createClass({
|
||||
getInitialState() {
|
||||
return {
|
||||
mockData: []
|
||||
mockData: [],
|
||||
targetKeys: [],
|
||||
};
|
||||
},
|
||||
|
||||
@ -22,23 +23,44 @@ const App = React.createClass({
|
||||
},
|
||||
|
||||
getMock() {
|
||||
let targetKeys = [];
|
||||
let mockData = [];
|
||||
for (let i = 0; i < 20; i++) {
|
||||
mockData.push({
|
||||
const data = {
|
||||
key: i,
|
||||
title: '内容' + (i + 1),
|
||||
value: (i + 1),
|
||||
description: '内容' + (i + 1) + '的描述',
|
||||
chosen: Math.random() * 2 > 1
|
||||
});
|
||||
};
|
||||
if (data.chosen) {
|
||||
targetKeys.push(data.key);
|
||||
}
|
||||
mockData.push(data);
|
||||
}
|
||||
this.setState({
|
||||
mockData: mockData
|
||||
mockData: mockData,
|
||||
targetKeys: targetKeys,
|
||||
});
|
||||
},
|
||||
|
||||
handleChange(targetKeys) {
|
||||
this.setState({
|
||||
targetKeys: targetKeys,
|
||||
});
|
||||
},
|
||||
|
||||
renderFooter(props) {
|
||||
return <Button type="primary" size="small" style={{ float: 'right', margin: '5' }}
|
||||
onClick={this.getMock}>刷新</Button>;
|
||||
},
|
||||
|
||||
render() {
|
||||
return <div>
|
||||
<Transfer dataSource={this.state.mockData} />
|
||||
<Button onClick={this.getMock}>刷新数据</Button>
|
||||
<Transfer
|
||||
dataSource={this.state.mockData}
|
||||
targetKeys={this.state.targetKeys}
|
||||
onChange={this.handleChange}
|
||||
render={(item) => { return item.title + item.description; }} />
|
||||
</div>;
|
||||
}
|
||||
});
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
- order: 1
|
||||
|
||||
带搜索的穿梭框
|
||||
带搜索框的 穿梭框
|
||||
|
||||
---
|
||||
|
||||
@ -10,5 +10,56 @@
|
||||
import { Transfer } from 'antd';
|
||||
const container = document.getElementById('components-transfer-demo-search');
|
||||
|
||||
ReactDOM.render(<Transfer />, container);
|
||||
const App = React.createClass({
|
||||
getInitialState() {
|
||||
return {
|
||||
mockData: [],
|
||||
targetKeys: [],
|
||||
};
|
||||
},
|
||||
|
||||
componentDidMount() {
|
||||
this.getMock();
|
||||
},
|
||||
|
||||
getMock() {
|
||||
let targetKeys = [];
|
||||
let mockData = [];
|
||||
for (let i = 0; i < 20; i++) {
|
||||
const data = {
|
||||
key: i,
|
||||
title: '内容' + (i + 1),
|
||||
description: '内容' + (i + 1) + '的描述',
|
||||
chosen: Math.random() * 2 > 1
|
||||
};
|
||||
if (data.chosen) {
|
||||
targetKeys.push(data.key);
|
||||
}
|
||||
mockData.push(data);
|
||||
}
|
||||
this.setState({
|
||||
mockData: mockData,
|
||||
targetKeys: targetKeys,
|
||||
});
|
||||
},
|
||||
|
||||
handleChange(targetKeys) {
|
||||
this.setState({
|
||||
targetKeys: targetKeys,
|
||||
});
|
||||
},
|
||||
|
||||
render() {
|
||||
return <div>
|
||||
<Transfer
|
||||
dataSource={this.state.mockData}
|
||||
showSearch
|
||||
targetKeys={this.state.targetKeys}
|
||||
onChange={this.handleChange}
|
||||
render={(item) => { return item.title + item.description;}} />
|
||||
</div>;
|
||||
}
|
||||
});
|
||||
|
||||
ReactDOM.render(<App />, container);
|
||||
````
|
||||
|
@ -11,194 +11,133 @@ class Transfer extends Component {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
dataSource: props.dataSource,
|
||||
leftFilter: '',
|
||||
rightFilter: '',
|
||||
leftCheckedKeys: [],
|
||||
rightCheckedKeys: []
|
||||
};
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
this.setState({
|
||||
dataSource: nextProps.dataSource,
|
||||
});
|
||||
}
|
||||
splitDataSource() {
|
||||
const { targetKeys, dataSource } = this.props;
|
||||
|
||||
checkDirection(direction) {
|
||||
const { filterKey } = this.props;
|
||||
let { dataSource } = this.state;
|
||||
let leftDataSource = Object.assign([], dataSource);
|
||||
let rightDataSource = [];
|
||||
|
||||
let result = false;
|
||||
|
||||
if ( direction === 'right' ) {
|
||||
dataSource.forEach((data) => {
|
||||
if ( !data[filterKey] && data.checked ) {
|
||||
result = true;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
dataSource.forEach((data) => {
|
||||
if ( data[filterKey] && data.checked ) {
|
||||
result = true;
|
||||
}
|
||||
if ( targetKeys.length > 0 ) {
|
||||
targetKeys.forEach((targetKey) => {
|
||||
rightDataSource.push(leftDataSource.find((data, index) => {
|
||||
if( data.key === targetKey ) {
|
||||
leftDataSource.splice(index, 1);
|
||||
return true;
|
||||
}
|
||||
}));
|
||||
});
|
||||
}
|
||||
return result;
|
||||
|
||||
return {
|
||||
leftDataSource: leftDataSource,
|
||||
rightDataSource: rightDataSource,
|
||||
};
|
||||
}
|
||||
|
||||
moveTo(direction) {
|
||||
const { filterKey } = this.props;
|
||||
let { dataSource } = this.state;
|
||||
// TODO: 验证是否可点
|
||||
if ( direction === 'right' ) {
|
||||
dataSource.forEach((data) => {
|
||||
// 左边向右移动
|
||||
if ( !data[filterKey] && data.checked ) {
|
||||
data[filterKey] = true;
|
||||
data.checked = false;
|
||||
}
|
||||
});
|
||||
this.setState({
|
||||
leftFilter: '',
|
||||
dataSource: dataSource,
|
||||
});
|
||||
} else {
|
||||
dataSource.forEach((data) => {
|
||||
if ( data[filterKey] && data.checked ) {
|
||||
data[filterKey] = false;
|
||||
data.checked = false;
|
||||
}
|
||||
});
|
||||
this.setState({
|
||||
rightFilter: '',
|
||||
dataSource: dataSource,
|
||||
});
|
||||
}
|
||||
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']: [],
|
||||
});
|
||||
|
||||
this.props.onChange(newTargetKeys);
|
||||
}
|
||||
|
||||
handleSelectAll(direction, globalCheckStatus) {
|
||||
const { filterKey } = this.props;
|
||||
const { dataSource, leftFilter, rightFilter } = this.state;
|
||||
switch ( globalCheckStatus ) {
|
||||
// 选中部分,则全选
|
||||
case 'part':
|
||||
case 'none':
|
||||
dataSource.forEach((data)=> {
|
||||
// data[filterKey] true 时,在右侧
|
||||
if ( direction === 'right' && data[filterKey] && this.matchFilter(data.title, rightFilter)
|
||||
|| direction === 'left' && !data[filterKey] && this.matchFilter(data.title, leftFilter)) {
|
||||
data.checked = true;
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 'all':
|
||||
dataSource.forEach((data)=> {
|
||||
if ( direction === 'right' && data[filterKey] && this.matchFilter(data.title, rightFilter)
|
||||
|| direction === 'left' && !data[filterKey] && this.matchFilter(data.title, leftFilter)) {
|
||||
data.checked = false;
|
||||
}
|
||||
});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
const { leftDataSource, rightDataSource } = this.splitDataSource();
|
||||
const dataSource = direction === 'left' ? leftDataSource : rightDataSource;
|
||||
let holder = [];
|
||||
|
||||
if ( globalCheckStatus === 'all' ) {
|
||||
holder = [];
|
||||
} else {
|
||||
holder = dataSource.map((data) => data.key);
|
||||
}
|
||||
|
||||
this.setState({
|
||||
dataSource: dataSource,
|
||||
[direction === 'left' ? 'leftCheckedKeys' : 'rightCheckedKeys']: holder,
|
||||
});
|
||||
}
|
||||
|
||||
handleFilter(direction, e) {
|
||||
const filterText = e.target.value;
|
||||
if ( direction === 'left') {
|
||||
this.setState({
|
||||
'leftFilter': filterText,
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
'rightFilter': filterText,
|
||||
});
|
||||
}
|
||||
this.setState({
|
||||
[direction === 'left' ? 'leftFilter' : 'rightFilter']: e.target.value,
|
||||
});
|
||||
}
|
||||
|
||||
handleClear(direction) {
|
||||
if ( direction === 'left') {
|
||||
this.setState({
|
||||
'leftFilter': '',
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
'rightFilter': '',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
matchFilter(text, filterText) {
|
||||
const regex = new RegExp(filterText);
|
||||
return text.match(regex);
|
||||
}
|
||||
|
||||
handleSelect(selectedItem, checked) {
|
||||
const { dataSource } = this.state;
|
||||
dataSource.forEach((data)=> {
|
||||
if ( data.value === selectedItem.value ) {
|
||||
data.checked = checked;
|
||||
}
|
||||
});
|
||||
|
||||
this.setState({
|
||||
dataSource: dataSource,
|
||||
[direction === 'left' ? 'leftFilter' : 'rightFilter']: '',
|
||||
});
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
this.setState({
|
||||
[direction === 'left' ? 'leftCheckedKeys' : 'rightCheckedKeys']: holder,
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { prefixCls, leftConfig, rightConfig, filterKey, showSearch, header, body, footer } = this.props;
|
||||
const { dataSource, leftFilter, rightFilter } = this.state;
|
||||
const { prefixCls, titles, operations, showSearch, searchPlaceholder, body, footer } = this.props;
|
||||
const { leftFilter, rightFilter, leftCheckedKeys, rightCheckedKeys } = this.state;
|
||||
|
||||
let leftDataSource = [];
|
||||
let rightDataSource = [];
|
||||
|
||||
let leftActive = this.checkDirection('left');
|
||||
let rightActive = this.checkDirection('right');
|
||||
|
||||
dataSource.map((item)=> {
|
||||
// filter item
|
||||
if ( item[filterKey] ) {
|
||||
if ( this.matchFilter(item.title, rightFilter) ) {
|
||||
rightDataSource.push(item);
|
||||
}
|
||||
} else {
|
||||
if ( this.matchFilter(item.title, leftFilter) ) {
|
||||
leftDataSource.push(item);
|
||||
}
|
||||
}
|
||||
});
|
||||
const { leftDataSource, rightDataSource } = this.splitDataSource();
|
||||
let leftActive = rightCheckedKeys.length > 0;
|
||||
let rightActive = leftCheckedKeys.length > 0;
|
||||
|
||||
return <div className={prefixCls}>
|
||||
<List config={leftConfig}
|
||||
<List title={titles[0]}
|
||||
dataSource={leftDataSource}
|
||||
filter={leftFilter}
|
||||
checkedKeys={leftCheckedKeys}
|
||||
handleFilter={this.handleFilter.bind(this, 'left')}
|
||||
handleClear={this.handleClear.bind(this, 'left')}
|
||||
handleSelect={this.handleSelect.bind(this)}
|
||||
handleSelect={this.handleSelect.bind(this, 'left')}
|
||||
handleSelectAll={this.handleSelectAll.bind(this, 'left')}
|
||||
position="left"
|
||||
render={this.props.render}
|
||||
showSearch={showSearch}
|
||||
header={header}
|
||||
searchPlaceholder={searchPlaceholder}
|
||||
body={body}
|
||||
footer={footer}
|
||||
/>
|
||||
<Operation rightActive={rightActive} rightArrowText={leftConfig.operationText} moveToRight={this.moveTo.bind(this, 'right')}
|
||||
leftActive={leftActive} leftArrowText={rightConfig.operationText} moveToLeft={this.moveTo.bind(this, 'left')} />
|
||||
<List config={rightConfig}
|
||||
<Operation rightActive={rightActive} rightArrowText={operations[0]} moveToRight={this.moveTo.bind(this, 'right')}
|
||||
leftActive={leftActive} leftArrowText={operations[1]} moveToLeft={this.moveTo.bind(this, 'left')} />
|
||||
<List title={titles[1]}
|
||||
dataSource={rightDataSource}
|
||||
filter={rightFilter}
|
||||
checkedKeys={rightCheckedKeys}
|
||||
handleFilter={this.handleFilter.bind(this, 'right')}
|
||||
handleClear={this.handleClear.bind(this, 'right')}
|
||||
handleSelect={this.handleSelect.bind(this)}
|
||||
handleSelect={this.handleSelect.bind(this, 'right')}
|
||||
handleSelectAll={this.handleSelectAll.bind(this, 'right')}
|
||||
position="right"
|
||||
render={this.props.render}
|
||||
showSearch={showSearch}
|
||||
header={header}
|
||||
searchPlaceholder={searchPlaceholder}
|
||||
body={body}
|
||||
footer={footer}
|
||||
/>
|
||||
@ -206,41 +145,32 @@ class Transfer extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
// onChange-> do operation
|
||||
// onSelect-> select action row
|
||||
|
||||
Transfer.defaultProps = {
|
||||
prefixCls: 'ant-transfer',
|
||||
dataSource: [],
|
||||
dataIndex: 'title',
|
||||
filterKey: 'chosen',
|
||||
render: noop,
|
||||
targetKeys: [],
|
||||
onChange: noop,
|
||||
onSelect: noop,
|
||||
leftConfig: {
|
||||
title: '源列表',
|
||||
operationText: '审核入库',
|
||||
},
|
||||
rightConfig: {
|
||||
title: '目的列表',
|
||||
operationText: '审核出库',
|
||||
},
|
||||
titles: ['源列表', '目的列表'],
|
||||
operations: [],
|
||||
showSearch: false,
|
||||
searchPlaceholder: '请输入搜索内容',
|
||||
header: noop,
|
||||
footer: noop,
|
||||
body: noop,
|
||||
footer: noop,
|
||||
};
|
||||
|
||||
Transfer.propTypes = {
|
||||
prefixCls: PropTypes.string,
|
||||
dataSource: PropTypes.array,
|
||||
render: PropTypes.func,
|
||||
targetKeys: PropTypes.array,
|
||||
onChange: PropTypes.func,
|
||||
titles: PropTypes.array,
|
||||
operations: PropTypes.array,
|
||||
showSearch: PropTypes.bool,
|
||||
searchPlaceholder: PropTypes.string,
|
||||
operationText: PropTypes.string,
|
||||
leftTitle: PropTypes.string,
|
||||
rightTitle: PropTypes.string,
|
||||
onChange: PropTypes.func,
|
||||
extraRender: PropTypes.func,
|
||||
body: PropTypes.func,
|
||||
footer: PropTypes.func,
|
||||
};
|
||||
|
||||
export default Transfer;
|
||||
|
@ -11,15 +11,18 @@
|
||||
|
||||
## 何时使用
|
||||
|
||||
- 需要表示开关状态/两种状态之间的切换时;
|
||||
- 和 `switch`的区别是,切换 `switch` 会直接触发状态改变,而 `checkbox` 一般用于状态标记,需要和提交操作配合。
|
||||
|
||||
## API
|
||||
|
||||
### Checkbox
|
||||
### Transfer
|
||||
|
||||
| 参数 | 说明 | 类型 | 可选值 |默认值 |
|
||||
|-----------|------------------------------------------|------------|-------|--------|
|
||||
| dataSource | 指定当前是否选中 | boolean | | false |
|
||||
| defaultChecked | 初始是否选中 | boolean | | false |
|
||||
| onChange | 变化时回调函数 | Function(e:Event) | | | |
|
||||
| dataSource | 数据源 | Array | | [] |
|
||||
| render | 渲染每行数据 | Function(record) | | false |
|
||||
| targetKeys | 显示在右侧框的数据 | Array | | |
|
||||
| onChange | 变化时回调函数 | Function(e:Event) | | |
|
||||
| titles | 标题集合,顺序从左至右 | Array | | [] |
|
||||
| operations | 集合,顺序从左至右 | Array | | [] |
|
||||
| showSearch | 是否显示搜索框 | Boolean | | false |
|
||||
| searchPlaceholder | 搜索框的默认值 | String | | |
|
||||
|
@ -2,7 +2,6 @@ import React, { Component, PropTypes } from 'react';
|
||||
import Checkbox from '../checkbox';
|
||||
import Search from './search.jsx';
|
||||
import {classSet} from 'rc-util';
|
||||
|
||||
function noop() {
|
||||
}
|
||||
|
||||
@ -13,11 +12,13 @@ class TransferList extends Component {
|
||||
}
|
||||
|
||||
handleSelectALl() {
|
||||
this.props.handleSelectAll(this.getGlobalCheckStatus());
|
||||
this.props.handleSelectAll(this.getGlobalCheckStatus(), this.filter);
|
||||
}
|
||||
|
||||
handleSelect(selectedItem) {
|
||||
this.props.handleSelect(selectedItem, !selectedItem.checked);
|
||||
const { checkedKeys } = this.props;
|
||||
const result = checkedKeys.some((key) => key === selectedItem.key);
|
||||
this.props.handleSelect(selectedItem, !result);
|
||||
}
|
||||
|
||||
handleFilter(e) {
|
||||
@ -29,18 +30,12 @@ class TransferList extends Component {
|
||||
}
|
||||
|
||||
getGlobalCheckStatus() {
|
||||
let { dataSource } = this.props;
|
||||
const { dataSource, checkedKeys } = this.props;
|
||||
|
||||
let globalCheckStatus;
|
||||
let selectedRowLength = 0;
|
||||
dataSource.forEach((data)=> {
|
||||
if ( data.checked ) {
|
||||
selectedRowLength++;
|
||||
}
|
||||
});
|
||||
|
||||
if ( selectedRowLength > 0 ) {
|
||||
if ( selectedRowLength < dataSource.length ) {
|
||||
if ( checkedKeys.length > 0 ) {
|
||||
if ( checkedKeys.length < dataSource.length ) {
|
||||
globalCheckStatus = 'part';
|
||||
} else {
|
||||
globalCheckStatus = 'all';
|
||||
@ -72,38 +67,53 @@ class TransferList extends Component {
|
||||
return (<span ref="checkbox" className={classSet(checkboxCls)} onClick={this.handleSelectALl.bind(this)}>{customEle}</span>);
|
||||
}
|
||||
|
||||
matchFilter(text, filterText) {
|
||||
const regex = new RegExp(filterText);
|
||||
return text.match(regex);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { prefixCls, config, header, footer, dataSource, filter, body } = this.props;
|
||||
let self = this;
|
||||
const { prefixCls, dataSource, title, filter, checkedKeys, body, footer, showSearch } = this.props;
|
||||
|
||||
let globalCheckStatus = this.getGlobalCheckStatus();
|
||||
|
||||
// Custom Layout
|
||||
const headerDom = header({...this.props, globalCheckStatus});
|
||||
const footerDom = footer({...this.props, globalCheckStatus});
|
||||
const bodyDom = body({...this.props, globalCheckStatus});
|
||||
|
||||
return (<div className={prefixCls} {...this.props}>
|
||||
{ headerDom ? <div className={`${prefixCls}-header`}>
|
||||
{ headerDom }
|
||||
</div> : <div className={`${prefixCls}-header`}>
|
||||
<div className={`${prefixCls}-header`}>
|
||||
{this.renderCheckbox({
|
||||
prefixCls: 'ant-tree',
|
||||
checked: globalCheckStatus === 'all',
|
||||
checkPart: globalCheckStatus === 'part',
|
||||
checkable: <span className={`ant-tree-checkbox-inner`}></span>
|
||||
})} {dataSource.length} 条
|
||||
<span className={`${prefixCls}-header-title`}>{config.title}</span>
|
||||
</div> }
|
||||
{ bodyDom ? bodyDom : <div className={`${prefixCls}-body`}>
|
||||
<div className={`${prefixCls}-body-search-wrapper`}>
|
||||
})} { (checkedKeys.length > 0 ? checkedKeys.length + '/' : '') + dataSource.length} 条
|
||||
<span className={`${prefixCls}-header-title`}>{title}</span>
|
||||
</div>
|
||||
{ bodyDom ? bodyDom :
|
||||
<div className={ showSearch ? `${prefixCls}-body ${prefixCls}-body-with-search` : `${prefixCls}-body`}>
|
||||
{ showSearch ? <div className={`${prefixCls}-body-search-wrapper`}>
|
||||
<Search className={`${prefixCls}-body-search-bar`} onChange={this.handleFilter.bind(this)} handleClear={this.handleClear.bind(this)} value={filter} />
|
||||
</div>
|
||||
<ul className="">
|
||||
{dataSource.map((item)=> {
|
||||
return <li onClick={this.handleSelect.bind(this, item)}>
|
||||
<Checkbox checked={item.checked} />
|
||||
{ item.title }
|
||||
</li>;})}
|
||||
</div> : null }
|
||||
<ul>
|
||||
{ dataSource.length > 0 ?
|
||||
dataSource.map((item)=> {
|
||||
// apply filter
|
||||
const itemText = self.props.render(item);
|
||||
const filterResult = self.matchFilter(itemText, filter);
|
||||
|
||||
if ( filterResult ) {
|
||||
return <li onClick={this.handleSelect.bind(this, item)}>
|
||||
<Checkbox checked={checkedKeys.some((key) => key === item.key)} />
|
||||
{ self.props.render(item) }
|
||||
</li>;
|
||||
}
|
||||
}) : <div className={`${prefixCls}-body-not-found`}>
|
||||
Not Found
|
||||
</div>
|
||||
}
|
||||
</ul>
|
||||
</div>}
|
||||
{ footerDom ? <div className={`${prefixCls}-footer`}>
|
||||
@ -116,12 +126,13 @@ class TransferList extends Component {
|
||||
TransferList.defaultProps = {
|
||||
prefixCls: 'ant-transfer-list',
|
||||
dataSource: [],
|
||||
defaultDataSource: [],
|
||||
showSearch: false,
|
||||
searchPlaceholder: '',
|
||||
handleFilter: noop,
|
||||
handleSelect: noop,
|
||||
onChange: noop,
|
||||
handleSelectAll: noop,
|
||||
render: noop,
|
||||
//advanced
|
||||
header: noop,
|
||||
footer: noop,
|
||||
body: noop,
|
||||
};
|
||||
@ -129,12 +140,12 @@ TransferList.defaultProps = {
|
||||
TransferList.propTypes = {
|
||||
prefixCls: PropTypes.string,
|
||||
dataSource: PropTypes.array,
|
||||
footer: PropTypes.func,
|
||||
searchPlaceholder: PropTypes.string,
|
||||
handleFilter: PropTypes.func,
|
||||
handleSelect: PropTypes.func,
|
||||
handleSelectAll: PropTypes.func,
|
||||
config: PropTypes.object,
|
||||
body: PropTypes.func,
|
||||
footer: PropTypes.func,
|
||||
};
|
||||
|
||||
export default TransferList;
|
||||
|
@ -1,5 +1,6 @@
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import Button from '../button';
|
||||
import Icon from '../icon';
|
||||
|
||||
function noop() {
|
||||
}
|
||||
@ -9,8 +10,10 @@ class TransferOperation extends Component {
|
||||
const { moveToLeft, moveToRight, leftArrowText, rightArrowText, leftActive, rightActive, prefixCls } = this.props;
|
||||
|
||||
return <div className={`${prefixCls}`}>
|
||||
<Button style={{ 'margin-bottom': '4px' }} disabled={ !rightActive ? 'disabled' : false } onClick={moveToRight}>{rightArrowText + '>'}</Button>
|
||||
<Button disabled={ !leftActive ? 'disabled' : false } onClick={moveToLeft}>{'<' + leftArrowText}</Button>
|
||||
{ rightArrowText ? <Button type="primary" style={{ 'margin-bottom': '4px' }} disabled={ !rightActive ? 'disabled' : false } onClick={moveToRight}>{rightArrowText}<Icon type="right" /></Button> :
|
||||
<Button type="primary" style={{ 'margin-bottom': '4px' }} disabled={ !rightActive ? 'disabled' : false } onClick={moveToRight}><Icon type="right" /></Button>}
|
||||
{leftArrowText ? <Button type="primary" disabled={ !leftActive ? 'disabled' : false } onClick={moveToLeft}><Icon type="left" />{leftArrowText}</Button> :
|
||||
<Button type="primary" disabled={ !leftActive ? 'disabled' : false } onClick={moveToLeft}><Icon type="left" /></Button>}
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
|
@ -15,9 +15,11 @@ class Search extends Component {
|
||||
render() {
|
||||
const {placeholder, value, prefixCls} = this.props;
|
||||
return <div>
|
||||
<input placeholder={placeholder} className={ prefixCls + ' ant-input' } value={ value } ref="input" onChange={this.handleChange.bind(this)}/>
|
||||
<input placeholder={placeholder} className={ prefixCls + ' ant-input' } value={ value } ref="input"
|
||||
onChange={this.handleChange.bind(this)}/>
|
||||
{ value && value.length > 0 ?
|
||||
<a href="javascirpt:;" className={ prefixCls + '-action' } onClick={this.props.handleClear}><i className="anticon anticon-cross-circle"></i></a>
|
||||
<a href="javascirpt:;" className={ prefixCls + '-action' } onClick={this.props.handleClear}><i
|
||||
className="anticon anticon-cross-circle"></i></a>
|
||||
: <span className={ prefixCls + '-action' }><i className="anticon anticon-search"></i></span>
|
||||
}
|
||||
</div>;
|
||||
|
@ -8,7 +8,6 @@
|
||||
display: inline-block;
|
||||
border-radius: 6px;
|
||||
width: 160px;
|
||||
height: 191px;
|
||||
|
||||
&-search {
|
||||
&-action {
|
||||
@ -40,7 +39,6 @@
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
position: relative;
|
||||
padding-top: 30px;
|
||||
height: 150px;
|
||||
|
||||
&-search-wrapper {
|
||||
@ -50,7 +48,12 @@
|
||||
height: 28px;
|
||||
padding: 4px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&-not-found {
|
||||
margin-top: 24px;
|
||||
color: #ccc;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
ul {
|
||||
@ -66,10 +69,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
&-body-with-search {
|
||||
padding-top: 34px;
|
||||
}
|
||||
|
||||
&-footer {
|
||||
border-top: 1px solid #e9e9e9;
|
||||
padding: 8px 20px 16px 10px;
|
||||
text-align: right;
|
||||
border-radius: 0 0 5px 5px;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user