mirror of
https://github.com/ant-design/ant-design.git
synced 2024-11-24 11:10:01 +08:00
add search and operation funcation
This commit is contained in:
parent
38b51372e6
commit
779d904f53
@ -7,9 +7,23 @@
|
||||
---
|
||||
|
||||
````jsx
|
||||
import { Transfer, Button } from 'antd';
|
||||
import { Transfer, Button, Menu, Dropdown, Icon } from 'antd';
|
||||
const container = document.getElementById('components-transfer-demo-basic');
|
||||
|
||||
const menu = <Menu>
|
||||
<Menu.Item>
|
||||
<a target="_blank" href="http://www.alipay.com/">编辑</a>
|
||||
</Menu.Item>
|
||||
</Menu>;
|
||||
|
||||
function makeDropdown(item) {
|
||||
return <Dropdown overlay={menu}>
|
||||
<Button type="small">
|
||||
{item.title} <Icon type="down" />
|
||||
</Button>
|
||||
</Dropdown>;
|
||||
}
|
||||
|
||||
const App = React.createClass({
|
||||
getInitialState() {
|
||||
return {
|
||||
@ -17,6 +31,10 @@ const App = React.createClass({
|
||||
};
|
||||
},
|
||||
|
||||
componentDidMount() {
|
||||
this.getMock();
|
||||
},
|
||||
|
||||
getMock() {
|
||||
let mockData = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
@ -33,7 +51,7 @@ const App = React.createClass({
|
||||
},
|
||||
render() {
|
||||
return <div>
|
||||
<Transfer dataSource={this.state.mockData} />
|
||||
<Transfer dataSource={this.state.mockData} extraRender={makeDropdown} />
|
||||
<Button onClick={this.getMock}>刷新数据</Button>
|
||||
</div>;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import List from './list.jsx';
|
||||
import Button from '../button';
|
||||
import Operation from './operation.jsx';
|
||||
|
||||
function noop() {
|
||||
}
|
||||
@ -12,6 +12,8 @@ class Transfer extends Component {
|
||||
|
||||
this.state = {
|
||||
dataSource: props.dataSource,
|
||||
leftFilter: '',
|
||||
rightFilter: '',
|
||||
};
|
||||
}
|
||||
|
||||
@ -22,7 +24,7 @@ class Transfer extends Component {
|
||||
}
|
||||
|
||||
moveTo(direction) {
|
||||
// TODO: 讨论是否要将新移动的元素置顶
|
||||
// TODO: 将新移动的元素置顶: 存index至state中
|
||||
const { filterKey } = this.props;
|
||||
let { dataSource } = this.state;
|
||||
if ( direction === 'right' ) {
|
||||
@ -33,6 +35,10 @@ class Transfer extends Component {
|
||||
data.checked = false;
|
||||
}
|
||||
});
|
||||
this.setState({
|
||||
leftFilter: '',
|
||||
dataSource: dataSource,
|
||||
});
|
||||
} else {
|
||||
dataSource.forEach((data) => {
|
||||
if ( data[filterKey] && data.checked ) {
|
||||
@ -40,32 +46,32 @@ class Transfer extends Component {
|
||||
data.checked = false;
|
||||
}
|
||||
});
|
||||
this.setState({
|
||||
rightFilter: '',
|
||||
dataSource: dataSource,
|
||||
});
|
||||
}
|
||||
|
||||
this.setState({
|
||||
dataSource: dataSource,
|
||||
});
|
||||
}
|
||||
|
||||
handleSelectAll(direction, globalCheckStatus) {
|
||||
const { filterKey } = this.props;
|
||||
const { dataSource } = this.state;
|
||||
const { dataSource, leftFilter, rightFilter } = this.state;
|
||||
switch ( globalCheckStatus ) {
|
||||
// 选中部分,则全选
|
||||
case 'part':
|
||||
case 'none':
|
||||
dataSource.forEach((data)=> {
|
||||
// data[filterKey] true 时,在右侧
|
||||
if ( direction === 'right' && data[filterKey]
|
||||
|| direction === 'left' && !data[filterKey] ) {
|
||||
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]
|
||||
|| direction === 'left' && !data[filterKey] ) {
|
||||
if ( direction === 'right' && data[filterKey] && this.matchFilter(data.title, rightFilter)
|
||||
|| direction === 'left' && !data[filterKey] && this.matchFilter(data.title, leftFilter)) {
|
||||
data.checked = false;
|
||||
}
|
||||
});
|
||||
@ -79,6 +85,24 @@ class Transfer extends Component {
|
||||
});
|
||||
}
|
||||
|
||||
handleFilter(direction, e) {
|
||||
const filterText = e.target.value;
|
||||
if ( direction === 'left') {
|
||||
this.setState({
|
||||
'leftFilter': filterText
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
'rightFilter': filterText
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
matchFilter(text, filterText) {
|
||||
const regex = new RegExp(filterText);
|
||||
return text.match(regex);
|
||||
}
|
||||
|
||||
handleSelect(selectedItem, checked) {
|
||||
const { dataSource } = this.state;
|
||||
dataSource.forEach((data)=> {
|
||||
@ -93,29 +117,40 @@ class Transfer extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { prefixCls, leftConfig, rightConfig, filterKey } = this.props;
|
||||
const { dataSource } = this.state;
|
||||
const { prefixCls, leftConfig, rightConfig, filterKey, extraRender } = this.props;
|
||||
const { dataSource, leftFilter, rightFilter } = this.state;
|
||||
|
||||
let leftDataSource = [];
|
||||
let rightDataSource = [];
|
||||
|
||||
dataSource.map((item)=> {
|
||||
// filter item
|
||||
if ( item[filterKey] ) {
|
||||
rightDataSource.push(item);
|
||||
if ( this.matchFilter(item.title, rightFilter) ) {
|
||||
rightDataSource.push(item);
|
||||
}
|
||||
} else {
|
||||
leftDataSource.push(item);
|
||||
if ( this.matchFilter(item.title, leftFilter) ) {
|
||||
leftDataSource.push(item);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return <div className={prefixCls}>
|
||||
<List style={{ width: '45%', display: 'inline-block'}} config={leftConfig} dataSource={leftDataSource}
|
||||
handleSelect={this.handleSelect.bind(this)} handleSelectAll={this.handleSelectAll.bind(this, 'left')}/>
|
||||
<div style={{ width: '10%', display: 'inline-block'}}>
|
||||
<Button shape="circle" onClick={this.moveTo.bind(this, 'right')}>{">"}</Button>
|
||||
<Button shape="circle" onClick={this.moveTo.bind(this, 'left')}>{"<"}</Button>
|
||||
</div>
|
||||
<List style={{ width: '45%', display: 'inline-block'}} config={rightConfig} dataSource={rightDataSource}
|
||||
handleSelect={this.handleSelect.bind(this)} handleSelectAll={this.handleSelectAll.bind(this, 'right')}/>
|
||||
<List style={{ width: '40%', display: 'inline-block'}} config={leftConfig} dataSource={leftDataSource}
|
||||
filter={leftFilter}
|
||||
handleFilter={this.handleFilter.bind(this, 'left')}
|
||||
handleSelect={this.handleSelect.bind(this)}
|
||||
handleSelectAll={this.handleSelectAll.bind(this, 'left')}
|
||||
extraRender={extraRender}/>
|
||||
<Operation rightArrowText={leftConfig.operationText} moveToRight={this.moveTo.bind(this, 'right')}
|
||||
leftArrowText={rightConfig.operationText} moveToLeft={this.moveTo.bind(this, 'left')} />
|
||||
<List style={{ width: '40%', display: 'inline-block'}} config={rightConfig} dataSource={rightDataSource}
|
||||
filter={rightFilter}
|
||||
handleFilter={this.handleFilter.bind(this, 'right')}
|
||||
handleSelect={this.handleSelect.bind(this)}
|
||||
handleSelectAll={this.handleSelectAll.bind(this, 'right')}
|
||||
extraRender={extraRender} />
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
@ -141,7 +176,8 @@ Transfer.defaultProps = {
|
||||
showSearch: false,
|
||||
searchPlaceholder: '请输入搜索内容',
|
||||
extraRender: noop,
|
||||
footer: noop,
|
||||
footer: ()=> {
|
||||
},
|
||||
};
|
||||
|
||||
Transfer.propTypes = {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import Checkbox from '../checkbox';
|
||||
import Button from '../button';
|
||||
import Search from './search.jsx';
|
||||
import {classSet} from 'rc-util';
|
||||
|
||||
function noop() {
|
||||
@ -20,6 +20,10 @@ class TransferList extends Component {
|
||||
this.props.handleSelect(selectedItem, e.target.checked);
|
||||
}
|
||||
|
||||
handleFilter(e) {
|
||||
this.props.handleFilter(e);
|
||||
}
|
||||
|
||||
getGlobalCheckStatus() {
|
||||
let { dataSource } = this.props;
|
||||
|
||||
@ -65,20 +69,7 @@ class TransferList extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { prefixCls, config, footer, extraRender, dataSource } = this.props;
|
||||
|
||||
let defaultFooter = [
|
||||
<Button key="reload"
|
||||
type="primary"
|
||||
onClick={this.handleCancel}>
|
||||
刷新
|
||||
</Button>,
|
||||
<Button key="ignore"
|
||||
type="ghost"
|
||||
onClick={this.handleOk}>
|
||||
忽略所选
|
||||
</Button>
|
||||
];
|
||||
const { prefixCls, config, footer, extraRender, dataSource, filter } = this.props;
|
||||
|
||||
let globalCheckStatus = this.getGlobalCheckStatus();
|
||||
|
||||
@ -92,6 +83,7 @@ class TransferList extends Component {
|
||||
})} {dataSource.length} 条{config.title}
|
||||
</div>
|
||||
<div className={`${prefixCls}-body`}>
|
||||
<Search onChange={this.handleFilter.bind(this)} value={filter} />
|
||||
<ul>
|
||||
{dataSource.map((item)=> {
|
||||
return <li>
|
||||
@ -99,13 +91,15 @@ class TransferList extends Component {
|
||||
<Checkbox checked={item.checked} onChange={this.handleSelect.bind(this, item)} />
|
||||
{ item.title }
|
||||
</label>
|
||||
{extraRender(item)}
|
||||
<div className="extra-holder">
|
||||
{extraRender(item)}
|
||||
</div>
|
||||
</li>;})}
|
||||
</ul>
|
||||
</div>
|
||||
<div className={`${prefixCls}-footer`}>
|
||||
{ defaultFooter || footer }
|
||||
</div>
|
||||
{ footer ? <div className={`${prefixCls}-footer`}>
|
||||
{ footer }
|
||||
</div> : null }
|
||||
</div>);
|
||||
}
|
||||
}
|
||||
@ -114,6 +108,7 @@ TransferList.defaultProps = {
|
||||
prefixCls: 'ant-transfer-list',
|
||||
dataSource: [],
|
||||
onChange: noop,
|
||||
footer: [],
|
||||
extraRender: noop,
|
||||
};
|
||||
|
||||
@ -122,6 +117,7 @@ TransferList.propTypes = {
|
||||
dataSource: PropTypes.array,
|
||||
footer: PropTypes.array,
|
||||
searchPlaceholder: PropTypes.string,
|
||||
handleFilter: PropTypes.func,
|
||||
handleSelect: PropTypes.func,
|
||||
handleSelectAll: PropTypes.func,
|
||||
config: PropTypes.object,
|
||||
|
@ -0,0 +1,34 @@
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import Button from '../button';
|
||||
|
||||
function noop() {
|
||||
}
|
||||
|
||||
class TransferOperation extends Component {
|
||||
render() {
|
||||
const { moveToLeft, moveToRight, leftArrowText, rightArrowText } = this.props;
|
||||
|
||||
return <div style={{ width: '20%', display: 'inline-block'}}>
|
||||
<Button onClick={moveToRight}>{rightArrowText + '>'}</Button>
|
||||
<Button onClick={moveToLeft}>{'<' + leftArrowText}</Button>
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
|
||||
TransferOperation.defaultProps = {
|
||||
prefixCls: 'ant-transfer-operation',
|
||||
leftArrowText: '',
|
||||
rightArrowText: '',
|
||||
moveToLeft: noop,
|
||||
moveToRight: noop,
|
||||
};
|
||||
|
||||
TransferOperation.propTypes = {
|
||||
prefixCls: PropTypes.string,
|
||||
leftArrowText: PropTypes.string,
|
||||
rightArrowText: PropTypes.string,
|
||||
moveToLeft: PropTypes.func,
|
||||
moveToRight: PropTypes.func,
|
||||
};
|
||||
|
||||
export default TransferOperation;
|
@ -1,28 +1,34 @@
|
||||
import { Component, PropTypes } from 'react';
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
|
||||
function noop() {
|
||||
}
|
||||
|
||||
class TransferSearch extends Component {
|
||||
render() {
|
||||
class Search extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
handleChange(e) {
|
||||
this.props.onChange(e);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {placeholder, value} = this.props;
|
||||
return <input placeholder={placeholder} className="ant-input" value={ value } ref="input" onChange={this.handleChange.bind(this)}/>;
|
||||
}
|
||||
}
|
||||
|
||||
TransferSearch.defaultProps = {
|
||||
Search.defaultProps = {
|
||||
prefixCls: 'ant-transfer-search',
|
||||
value: PropTypes.string,
|
||||
defaultValue: PropTypes.string,
|
||||
placeholder: '请输入搜索内容',
|
||||
onChange: noop,
|
||||
onDelete: noop,
|
||||
};
|
||||
|
||||
TransferSearch.propTypes = {
|
||||
Search.propTypes = {
|
||||
prefixCls: PropTypes.string,
|
||||
value: PropTypes.string,
|
||||
defaultValue: PropTypes.string,
|
||||
onChange: PropTypes.func,
|
||||
onDelete: PropTypes.func,
|
||||
placeholder: PropTypes.string,
|
||||
onChange: PropTypes.func
|
||||
};
|
||||
|
||||
export default TransferSearch;
|
||||
export default Search;
|
||||
|
@ -25,9 +25,18 @@
|
||||
li {
|
||||
padding: 7px 16px;
|
||||
|
||||
.extra-holder {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
background-color: #EEF9FE;
|
||||
|
||||
.extra-holder {
|
||||
float: right;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user