mirror of
https://gitee.com/baidu/amis.git
synced 2024-11-29 18:48:45 +08:00
feat:穿梭框组件事件&动作扩充
This commit is contained in:
parent
a5f6f48fb2
commit
0f55c27f1d
57
examples/components/EventAction/TransferEvent.jsx
Normal file
57
examples/components/EventAction/TransferEvent.jsx
Normal 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"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
@ -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)
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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} />
|
||||
|
@ -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}
|
||||
|
@ -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} />
|
||||
|
@ -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} />
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user