mirror of
https://github.com/ant-design/ant-design.git
synced 2025-01-18 06:03:38 +08:00
* feat: support disabled item for Transfer, close: #3038 * refactor: Transfer
This commit is contained in:
parent
41266f6374
commit
31615c9793
@ -35,6 +35,7 @@ const App = React.createClass({
|
||||
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);
|
||||
|
@ -12,24 +12,24 @@ export interface TransferItem {
|
||||
key: number | string;
|
||||
title: string;
|
||||
description?: string;
|
||||
chosen: boolean;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
// Transfer
|
||||
export interface TransferProps {
|
||||
dataSource: Array<TransferItem>;
|
||||
render?: (record: TransferItem) => any;
|
||||
dataSource: TransferItem[];
|
||||
targetKeys: string[];
|
||||
onChange?: (targetKeys: Array<TransferItem>, direction: string, moveKeys: any) => void;
|
||||
render?: (record: TransferItem) => any;
|
||||
onChange?: (targetKeys: TransferItem[], direction: string, moveKeys: any) => void;
|
||||
onSelectChange?: (sourceSelectedKeys: string[], targetSelectedKeys: string[]) => void;
|
||||
listStyle?: React.CSSProperties;
|
||||
className?: string;
|
||||
prefixCls?: string;
|
||||
titles?: Array<string>;
|
||||
operations?: Array<string>;
|
||||
titles?: string[];
|
||||
operations?: string[];
|
||||
showSearch?: boolean;
|
||||
searchPlaceholder?: string;
|
||||
notFoundContent?: React.ReactNode | string;
|
||||
notFoundContent?: React.ReactNode;
|
||||
footer?: (props: any) => any;
|
||||
style?: React.CSSProperties;
|
||||
filterOption: (inputValue: any, item: any) => boolean;
|
||||
@ -112,29 +112,16 @@ export default class Transfer extends React.Component<TransferProps, any> {
|
||||
if (this.splitedDataSource) {
|
||||
return this.splitedDataSource;
|
||||
}
|
||||
const { targetKeys } = props;
|
||||
let { dataSource } = props;
|
||||
|
||||
const { dataSource, targetKeys } = props;
|
||||
if (props.rowKey) {
|
||||
dataSource = dataSource.map(record => {
|
||||
dataSource.forEach(record => {
|
||||
record.key = props.rowKey(record);
|
||||
return record;
|
||||
});
|
||||
}
|
||||
let leftDataSource = [...dataSource];
|
||||
let rightDataSource = [];
|
||||
|
||||
if (targetKeys.length > 0) {
|
||||
targetKeys.forEach((targetKey) => {
|
||||
rightDataSource.push(leftDataSource.filter((data, index) => {
|
||||
if (data.key === targetKey) {
|
||||
leftDataSource.splice(index, 1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
})[0]);
|
||||
});
|
||||
}
|
||||
const leftDataSource = dataSource.filter(({ key }) => targetKeys.indexOf(key) === -1);
|
||||
const rightDataSource = dataSource.filter(({ key }) => targetKeys.indexOf(key) >= 0);
|
||||
|
||||
this.splitedDataSource = {
|
||||
leftDataSource,
|
||||
@ -151,7 +138,7 @@ export default class Transfer extends React.Component<TransferProps, any> {
|
||||
// move items to target box
|
||||
const newTargetKeys = direction === 'right'
|
||||
? moveKeys.concat(targetKeys)
|
||||
: targetKeys.filter(targetKey => !moveKeys.some(checkedKey => targetKey === checkedKey));
|
||||
: targetKeys.filter(targetKey => moveKeys.indexOf(targetKey) === -1);
|
||||
|
||||
// empty checked keys
|
||||
const oppositeDirection = direction === 'right' ? 'left' : 'right';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import * as React from 'react';
|
||||
import React from 'react';
|
||||
import { PropTypes } from 'react';
|
||||
import Checkbox from '../checkbox';
|
||||
import Search from './search';
|
||||
@ -18,7 +18,7 @@ export function isRenderResultPlainObject(result) {
|
||||
|
||||
export interface TransferListProps {
|
||||
prefixCls?: string;
|
||||
dataSource: Array<TransferItem>;
|
||||
dataSource: TransferItem[];
|
||||
filter?: string;
|
||||
showSearch?: boolean;
|
||||
searchPlaceholder?: string;
|
||||
@ -176,43 +176,52 @@ export default class TransferList extends React.Component<TransferListProps, any
|
||||
|
||||
const filteredDataSource = [];
|
||||
|
||||
const showItems = dataSource.map(item => {
|
||||
const showItems = dataSource.map((item) => {
|
||||
const renderResult = render(item);
|
||||
let renderedText;
|
||||
let renderedEl;
|
||||
|
||||
if (isRenderResultPlainObject(renderResult)) {
|
||||
renderedText = renderResult.value;
|
||||
renderedEl = renderResult.label;
|
||||
} else {
|
||||
renderedText = renderResult;
|
||||
renderedEl = renderResult;
|
||||
return {
|
||||
item: item,
|
||||
renderedText: renderResult.value,
|
||||
renderedEl: renderResult.label,
|
||||
};
|
||||
}
|
||||
return {
|
||||
item: item,
|
||||
renderedText: renderResult,
|
||||
renderedEl: renderResult,
|
||||
};
|
||||
}).filter(({ item, renderedText }) => {
|
||||
return !(filter && filter.trim() && !this.matchFilter(filter, item, renderedText));
|
||||
}).map(({ item, renderedText, renderedEl }) => {
|
||||
if (!item.disabled) {
|
||||
filteredDataSource.push(item);
|
||||
}
|
||||
|
||||
if (filter && filter.trim() && !this.matchFilter(filter, item, renderedText)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
filteredDataSource.push(item);
|
||||
|
||||
const className = classNames({
|
||||
[`${prefixCls}-content-item`]: true,
|
||||
[`${prefixCls}-content-item-disabled`]: item.disabled,
|
||||
});
|
||||
return (
|
||||
<li onClick={() => this.handleSelect(item)} key={item.key} title={renderedText}>
|
||||
<Checkbox checked={checkedKeys.some(key => key === item.key)} />
|
||||
<li
|
||||
key={item.key}
|
||||
className={className}
|
||||
title={renderedText}
|
||||
onClick={item.disabled ? null : () => this.handleSelect(item)}
|
||||
>
|
||||
<Checkbox checked={checkedKeys.some(key => key === item.key)} disabled={item.disabled} />
|
||||
<span>{renderedEl}</span>
|
||||
</li>
|
||||
);
|
||||
}).filter(item => !!item);
|
||||
});
|
||||
|
||||
let unit = '条';
|
||||
if (this.context.antLocale &&
|
||||
this.context.antLocale.Transfer) {
|
||||
unit = dataSource.length > 1
|
||||
? this.context.antLocale.Transfer.itemsUnit
|
||||
: this.context.antLocale.Transfer.itemUnit;
|
||||
searchPlaceholder = searchPlaceholder
|
||||
|| this.context.antLocale.Transfer.searchPlaceholder;
|
||||
notFoundContent = notFoundContent
|
||||
|| this.context.antLocale.Transfer.notFoundContent;
|
||||
const antLocale = this.context.antLocale;
|
||||
if (antLocale && antLocale.Transfer) {
|
||||
const transferLocale = antLocale.Transfer;
|
||||
unit = dataSource.length > 1 ? transferLocale.itemsUnit : transferLocale.itemUnit;
|
||||
searchPlaceholder = searchPlaceholder || transferLocale.searchPlaceholder;
|
||||
notFoundContent = notFoundContent || transferLocale.notFoundContent;
|
||||
}
|
||||
|
||||
const checkStatus = this.getCheckStatus(filteredDataSource);
|
||||
@ -248,8 +257,10 @@ export default class TransferList extends React.Component<TransferListProps, any
|
||||
value={filter}
|
||||
/>
|
||||
</div> : null}
|
||||
<Animate component="ul"
|
||||
transitionName={this.state.mounted ? `${prefixCls}-highlight` : ''}
|
||||
<Animate
|
||||
component="ul"
|
||||
className={`${prefixCls}-content`}
|
||||
transitionName={this.state.mounted ? `${prefixCls}-content-item-highlight` : ''}
|
||||
transitionLeave={false}
|
||||
>
|
||||
{showItems.length > 0
|
||||
|
@ -1,4 +1,4 @@
|
||||
import * as React from 'react';
|
||||
import React from 'react';
|
||||
import Button from '../button';
|
||||
import Icon from '../icon';
|
||||
|
||||
|
@ -83,33 +83,39 @@
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
ul {
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
li {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
padding: 7px 16px;
|
||||
transition: all 0.3s ease;
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
background-color: tint(@primary-color, 90%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ul li&-highlight-enter {
|
||||
animation: transferHighlightIn 1s ease;
|
||||
transition: none;
|
||||
}
|
||||
|
||||
&-body-with-search {
|
||||
padding-top: 34px;
|
||||
}
|
||||
|
||||
&-content {
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
&-item {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
padding: 7px 16px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
&-item:not(&-item-disabled):hover {
|
||||
cursor: pointer;
|
||||
background-color: tint(@primary-color, 90%);
|
||||
}
|
||||
|
||||
&-item-disabled {
|
||||
cursor: not-allowed;
|
||||
color: @btn-disable-color;
|
||||
}
|
||||
|
||||
&-item-highlight-enter {
|
||||
animation: transferHighlightIn 1s ease;
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
|
||||
&-footer {
|
||||
border-top: 1px solid @border-color-split;
|
||||
border-radius: 0 0 @border-radius-base @border-radius-base;
|
||||
|
Loading…
Reference in New Issue
Block a user