feat:穿梭框组件事件&动作扩充

This commit is contained in:
sqzhou 2022-03-29 21:38:59 +08:00
parent a5f6f48fb2
commit 0f55c27f1d
11 changed files with 244 additions and 12 deletions

View File

@ -0,0 +1,57 @@
export default {
type: 'page',
title: '穿梭框类事件',
regions: ['body', 'toolbar', 'header'],
body: [
{
name: 'trigger1',
id: 'trigger1',
type: 'action',
label: '穿梭框1',
level: 'primary',
className: 'mr-3 mb-3',
onEvent: {
click: {
actions: [
{
actionType: 'selectAll',
componentId: 'transfer-change-receiver'
}
]
}
}
},
{
"label": "穿梭器",
"id": 'transfer-change-receiver',
"type": "transfer",
"name": "transfer-change-receiver",
"options": [
{
"label": "诸葛亮",
"value": "zhugeliang"
},
{
"label": "曹操",
"value": "caocao"
},
{
"label": "钟无艳",
"value": "zhongwuyan"
},
{
"label": "李白",
"value": "libai"
},
{
"label": "韩信",
"value": "hanxin"
},
{
"label": "云中君",
"value": "yunzhongjun"
}
]
}
]
};

View File

@ -86,6 +86,7 @@ import WizardEventSchema from './EventAction/WizardEvent';
import InputTreeEventSchema from './EventAction/InputTreeEvent';
import treeSelectEventSchema from './EventAction/treeSelectEvent';
import FormEventActionSchema from './EventAction/FormEvent';
import TransferEventSchema from './EventAction/TransferEvent';
import WizardSchema from './Wizard';
import ChartSchema from './Chart';
import EChartsEditorSchema from './ECharts';
@ -604,6 +605,11 @@ export const examples = [
label: 'form表单',
path: 'examples/event/form',
component: makeSchemaRenderer(FormEventActionSchema)
},
{
label: '穿梭框类组件',
path: 'examples/event/transfer',
component: makeSchemaRenderer(TransferEventSchema)
}
]
},

View File

@ -29,6 +29,8 @@ export interface PickerContainerProps extends ThemeProps, LocaleProps {
popOverContainer?: any;
popOverClassName?: string;
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'full';
onOpen?: () => void;
onClose?: () => void;
}
export interface PickerContainerState {
@ -57,9 +59,12 @@ export class PickerContainer extends React.Component<
@autobind
handleClick() {
this.setState({
isOpened: true
});
this.setState(
{
isOpened: true
},
(() => this.props.onOpen?.())
);
}
@autobind
@ -68,8 +73,14 @@ export class PickerContainer extends React.Component<
{
isOpened: false
},
callback || (() => this.props.onCancel?.())
);
() => {
this.props?.onClose?.();
if (callback) {
callback();
return
}
this.props?.onCancel?.();
})
}
@autobind

View File

@ -45,6 +45,8 @@ export interface TabsTransferProps
colIndex: number,
rowIndex: number
) => JSX.Element;
onTabChange?: (key: number) => void;
activeKey: number
}
export interface TabsTransferState {
@ -134,7 +136,9 @@ export class TabsTransfer extends React.Component<
}
@autobind
handleTabChange() {
handleTabChange(key: number) {
this.props?.onTabChange?.(key);
this.handleSeachCancel();
}
@ -225,7 +229,7 @@ export class TabsTransfer extends React.Component<
@autobind
renderSelect() {
const {options, placeholder, classnames: cx, translate: __} = this.props;
const {options, placeholder, activeKey, classnames: cx, translate: __} = this.props;
const showOptions = options.filter(item => item.visible !== false);
if (!Array.isArray(options) || !options.length) {
@ -241,6 +245,7 @@ export class TabsTransfer extends React.Component<
mode="line"
className={cx('TabsTransfer-tabs')}
onSelect={this.handleTabChange}
activeKey={activeKey}
>
{showOptions.map((option, index) => (
<Tab

View File

@ -78,6 +78,8 @@ export interface TransferProps
states: ResultItemRenderStates
) => JSX.Element;
sortable?: boolean;
onRef?: (ref: Transfer) => void;
onSelectAll?: (options: Options) => void;
}
export interface TransferState {
@ -102,6 +104,10 @@ export class Transfer<
unmounted = false;
cancelSearch?: () => void;
componentDidMount() {
this.props?.onRef?.(this);
}
componentWillUnmount() {
this.lazySearch.cancel();
this.unmounted = true;
@ -109,7 +115,7 @@ export class Transfer<
@autobind
toggleAll() {
const {options, option2value, onChange, value} = this.props;
const {options, option2value, onChange, value, onSelectAll} = this.props;
let valueArray = BaseSelection.value2array(value, options, option2value);
const availableOptions = flattenTree(options).filter(
(option, index, list) =>
@ -128,6 +134,9 @@ export class Transfer<
? valueArray.map(item => option2value(item))
: valueArray;
// > 0 全选
newValue.length > 0 && onSelectAll && onSelectAll(newValue);
onChange && onChange(newValue);
}

View File

@ -16,6 +16,10 @@ export interface TransferPickerProps extends Omit<TransferProps, 'itemRender'> {
*
*/
borderMode?: 'full' | 'half' | 'none';
onFocus?: Function;
onBlur?: Function;
}
export class TransferPicker extends React.Component<TransferPickerProps> {
@ -26,6 +30,16 @@ export class TransferPicker extends React.Component<TransferPickerProps> {
this.optionModified = false;
}
@autobind
onFoucs() {
this.props?.onFocus?.();
}
@autobind
onBlur() {
this.props?.onBlur?.();
}
render() {
const {
classnames: cx,
@ -42,6 +56,8 @@ export class TransferPicker extends React.Component<TransferPickerProps> {
return (
<PickerContainer
title={__('Select.placeholder')}
onOpen={this.onFoucs}
onClose={this.onBlur}
bodyRender={({onClose, value, onChange, setState, ...states}) => {
return (
<Transfer

View File

@ -15,6 +15,7 @@ import {
spliceTree
} from '../../utils/helper';
import {BaseSelection, ItemRenderStates} from '../../components/Selection';
import {Action} from '../../types';
/**
* TabsTransfer
@ -35,10 +36,32 @@ export interface TabsTransferProps
| 'className'
| 'descriptionClassName'
> {}
interface BaseTransferState {
activeKey: number
}
export class BaseTabsTransferRenderer<
T extends OptionsControlProps = TabsTransferProps
> extends BaseTransferRenderer<T> {
state: BaseTransferState = {
activeKey: 0
}
@autobind
async onTabChange(key: number) {
const {dispatchEvent} = this.props;
const rendererEvent = await dispatchEvent('tab-change', {value: key});
if (rendererEvent?.prevented) {
return;
}
this.setState({
activeKey: key
});
}
@autobind
async handleTabSearch(
term: string,
@ -220,6 +243,25 @@ export class TabsTransferRenderer extends BaseTabsTransferRenderer<TabsTransferP
return BaseSelection.itemRender(option, states);
}
// 动作
doAction(action: Action) {
const {resetValue, onChange} = this.props;
const activeKey = action?.activeKey as number;
switch (action.actionType) {
case 'clear':
onChange('');
break;
case 'reset':
onChange(resetValue);
break;
case 'changeTabKey':
this.setState({
activeKey
});
break;
}
}
render() {
const {
className,
@ -240,6 +282,7 @@ export class TabsTransferRenderer extends BaseTabsTransferRenderer<TabsTransferP
return (
<div className={cx('TabsTransferControl', className)}>
<TabsTransfer
activeKey={this.state.activeKey}
value={selectedOptions}
disabled={disabled}
options={options}
@ -255,6 +298,7 @@ export class TabsTransferRenderer extends BaseTabsTransferRenderer<TabsTransferP
resultTitle={resultTitle}
optionItemRender={this.optionItemRender}
resultItemRender={this.resultItemRender}
onTabChange={this.onTabChange}
/>
<Spinner overlay key="info" show={loading} />

View File

@ -7,6 +7,7 @@ import {TabsTransferControlSchema} from './TabsTransfer';
import {autobind, createObject} from '../../utils/helper';
import {Option, optionValueCompare} from '../../components/Select';
import {BaseSelection, ItemRenderStates} from '../../components/Selection';
import {Action} from '../../types';
/**
* TabsTransferPicker 穿
@ -28,10 +29,19 @@ export interface TabsTransferProps
| 'descriptionClassName'
> {}
interface BaseTransferState {
activeKey: number
}
@OptionsControl({
type: 'tabs-transfer-picker'
})
export class TabsTransferPickerRenderer extends BaseTabsTransferRenderer<TabsTransferProps> {
state: BaseTransferState = {
activeKey: 0
}
@autobind
optionItemRender(option: any, states: ItemRenderStates) {
const {menuTpl, render, data} = this.props;
@ -52,6 +62,20 @@ export class TabsTransferPickerRenderer extends BaseTabsTransferRenderer<TabsTra
return BaseSelection.itemRender(option, states);
}
// 动作
doAction(action: Action) {
const {resetValue, onChange} = this.props;
switch (action.actionType) {
case 'clear':
onChange('');
break;
case 'reset':
onChange(resetValue);
break;
}
}
render() {
const {
className,
@ -68,12 +92,14 @@ export class TabsTransferPickerRenderer extends BaseTabsTransferRenderer<TabsTra
resultTitle,
pickerSize,
leftMode,
leftOptions
leftOptions,
} = this.props;
return (
<div className={cx('TabsTransferControl', className)}>
<TabsTransferPicker
activeKey={this.state.activeKey}
onTabChange={this.onTabChange}
value={selectedOptions}
disabled={disabled}
options={options}

View File

@ -4,7 +4,7 @@ import {
FormOptionsControl
} from './Options';
import React from 'react';
import Transfer from '../../components/Transfer';
import Transfer, {Transfer as BaseTransfer} from '../../components/Transfer';
import type {Option} from './Options';
import {
autobind,
@ -27,6 +27,7 @@ import {
ItemRenderStates as ResultItemRenderStates,
ResultList
} from '../../components/ResultList';
import {Action} from '../../types';
/**
* Transfer
@ -127,6 +128,9 @@ export interface BaseTransferProps
export class BaseTransferRenderer<
T extends OptionsControlProps = BaseTransferProps
> extends React.Component<T> {
tranferRef?: BaseTransfer;
@autobind
async handleChange(value: Array<Option> | Option, optionModified?: boolean) {
const {
@ -315,6 +319,33 @@ export class BaseTransferRenderer<
);
}
@autobind
getRef(ref: BaseTransfer) {
this.tranferRef = ref;
}
@autobind
onSelectAll(options: Option[]) {
const {dispatchEvent} = this.props;
dispatchEvent('selectAll', options);
}
// 动作
doAction(action: Action, data: object, throwErrors: boolean) {
const {resetValue, onChange} = this.props;
switch (action.actionType) {
case 'clear':
onChange('');
break;
case 'reset':
onChange(resetValue);
break;
case 'selectAll':
this.tranferRef?.toggleAll();
break;
}
}
render() {
const {
className,
@ -379,6 +410,8 @@ export class BaseTransferRenderer<
resultTitle={resultTitle}
optionItemRender={this.optionItemRender}
resultItemRender={this.resultItemRender}
onSelectAll={this.onSelectAll}
onRef={this.getRef}
/>
<Spinner overlay key="info" show={loading} />

View File

@ -7,9 +7,10 @@ import React from 'react';
import {Api} from '../../types';
import Spinner from '../../components/Spinner';
import {BaseTransferRenderer, TransferControlSchema} from './Transfer';
import TabsTransfer from '../../components/TabsTransfer';
import {SchemaApi, SchemaObject} from '../../Schema';
import TransferPicker from '../../components/TransferPicker';
import {autobind} from '../../utils/helper';
import {Action} from '../../types';
/**
* TransferPicker 穿
@ -44,6 +45,26 @@ export interface TabsTransferProps
type: 'transfer-picker'
})
export class TransferPickerRenderer extends BaseTransferRenderer<TabsTransferProps> {
@autobind
dispatchEvent(name: string) {
const {dispatchEvent, data} = this.props;
dispatchEvent(name, data);
}
// 动作
doAction(action: Action) {
const {resetValue, onChange} = this.props;
switch (action.actionType) {
case 'clear':
onChange('');
break;
case 'reset':
onChange(resetValue);
break;
}
}
render() {
const {
className,
@ -104,6 +125,8 @@ export class TransferPickerRenderer extends BaseTransferRenderer<TabsTransferPro
leftOptions={leftOptions}
optionItemRender={this.optionItemRender}
resultItemRender={this.resultItemRender}
onFocus={() => this.dispatchEvent('focus')}
onBlur={() => this.dispatchEvent('blur')}
/>
<Spinner overlay key="info" show={loading} />

View File

@ -109,7 +109,9 @@ export interface Action extends Button {
| 'goto-step'
| 'expand'
| 'collapse'
| 'step-submit';
| 'step-submit'
| 'selectAll'
| 'changeTabKey';
api?: Api;
asyncApi?: Api;
payload?: any;