Merge pull request #4379 from wanglinfang2014/feat-table-1-event-action

feat: table事件动作调整、补充示例
This commit is contained in:
hsm-lv 2022-05-18 17:19:52 +08:00 committed by GitHub
commit 9f24d57ee7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 462 additions and 50 deletions

View File

@ -0,0 +1,397 @@
export default {
type: 'page',
title: '表格组件事件',
regions: ['body', 'toolbar', 'header'],
body: [
{
type: 'tpl',
tpl: '事件',
inline: false,
wrapperComponent: 'h1'
},
{
type: 'tpl',
tpl: '选择表格项事件',
inline: false,
wrapperComponent: 'h2'
},
{
type: 'service',
api: '/api/mock2/sample?perPage=10',
body: [
{
type: 'table',
source: '$rows',
selectable: true,
multiple: true,
columns: [
{
name: 'id',
label: 'ID'
},
{
name: 'browser',
label: 'Browser'
},
{
name: 'version',
label: 'Version'
}
],
onEvent: {
selectedChange: {
actions: [
{
actionType: 'toast',
args: {
msgType: 'info',
msg: '选中${event.data.selectedItems.length}项数据;未选中${event.data.unSelectedItems.length}项数据'
}
}
]
}
}
}
]
},
{
type: 'tpl',
tpl: '列排序、列搜索、列筛选事件',
inline: false,
wrapperComponent: 'h2'
},
{
type: 'service',
api: '/api/mock2/sample?perPage=10',
body: [
{
type: 'table',
source: '$rows',
columns: [
{
name: 'id',
label: 'ID',
searchable: true
},
{
name: 'browser',
label: 'Browser',
filterable: {
options: [
'Internet Explorer 4.0',
'Internet Explorer 5.0'
]
}
},
{
name: 'version',
label: 'Version',
sortable: true
}
],
onEvent: {
columnSort: {
actions: [
{
actionType: 'toast',
args: {
msgType: 'info',
msg: '列排序数据:${event.data|json}'
}
}
]
},
columnFilter: {
actions: [
{
actionType: 'toast',
args: {
msgType: 'info',
msg: '列筛选数据:${event.data|json}'
}
}
]
},
columnSearch: {
actions: [
{
actionType: 'toast',
args: {
msgType: 'info',
msg: '列搜索数据:${event.data|json}'
}
}
]
}
}
}
]
},
{
type: 'tpl',
tpl: '行排序事件',
inline: false,
wrapperComponent: 'h2'
},
{
type: 'service',
api: '/api/mock2/sample?perPage=10',
body: [
{
type: 'table',
source: '$rows',
draggable: true,
columns: [
{
name: 'id',
label: 'ID'
},
{
name: 'browser',
label: 'Browser'
},
{
name: 'version',
label: 'Version'
}
],
onEvent: {
orderChange: {
actions: [
{
actionType: 'toast',
args: {
msgType: 'info',
msg: '${event.data.movedItems.length}行发生移动'
}
}
]
}
}
}
]
},
{
type: 'tpl',
tpl: '列显示变化事件',
inline: false,
wrapperComponent: 'h2'
},
{
type: 'service',
api: '/api/mock2/sample?perPage=10',
body: [
{
type: 'table',
source: '$rows',
columnsTogglable: true,
columns: [
{
name: 'id',
label: 'ID'
},
{
name: 'browser',
label: 'Browser'
},
{
name: 'version',
label: 'Version'
}
],
onEvent: {
columnToggled: {
actions: [
{
actionType: 'toast',
args: {
msgType: 'info',
msg: '当前显示${event.data.columns.length}列'
}
}
]
}
}
}
]
},
{
type: 'tpl',
tpl: '行单击事件',
inline: false,
wrapperComponent: 'h2'
},
{
type: 'service',
api: '/api/mock2/sample?perPage=10',
body: [
{
type: 'table',
source: '$rows',
columns: [
{
name: 'id',
label: 'ID'
},
{
name: 'browser',
label: 'Browser'
},
{
name: 'version',
label: 'Version'
}
],
onEvent: {
rowClick: {
actions: [
{
actionType: 'toast',
args: {
msgType: 'info',
msg: '行单击数据:${event.data|json}'
}
}
]
}
}
}
]
},
{
type: 'divider'
},
{
type: 'tpl',
tpl: '动作',
inline: false,
wrapperComponent: 'h1'
},
{
type: 'tpl',
tpl: '设置表格选中项',
inline: false,
wrapperComponent: 'h2'
},
{
type: 'button-toolbar',
className: 'm-b',
buttons: [
{
name: 'trigger1',
id: 'trigger1',
type: 'action',
label: '设置表格第一项选中',
level: 'primary',
onEvent: {
click: {
actions: [
{
actionType: 'select',
componentId: 'table-select',
description: '点击设置指定表格第一项内容选中',
args: {
selected: 'data.rowIndex === 0'
}
}
]
}
}
},
{
name: 'trigger2',
id: 'trigger2',
type: 'action',
label: '设置表格全部项选中',
level: 'primary',
onEvent: {
click: {
actions: [
{
actionType: 'selectAll',
componentId: 'table-select',
description: '点击设置指定表格全部内容选中'
}
]
}
}
},
{
name: 'trigger3',
id: 'trigger3',
type: 'action',
label: '清空表格全部选中项',
level: 'primary',
onEvent: {
click: {
actions: [
{
actionType: 'clearAll',
componentId: 'table-select',
description: '点击设置指定表格全部选中项清空'
}
]
}
}
},
{
name: 'trigger4',
id: 'trigger4',
type: 'action',
label: '开启表格行排序',
level: 'primary',
onEvent: {
click: {
actions: [
{
actionType: 'initDrag',
componentId: 'table-select',
description: '点击开启表格行排序功能'
}
]
}
}
}
]
},
{
type: 'service',
api: '/api/mock2/sample?perPage=10',
body: [
{
id: 'table-select',
type: 'table',
source: '$rows',
selectable: true,
multiple: true,
columns: [
{
name: 'id',
label: 'ID'
},
{
name: 'browser',
label: 'Browser'
},
{
name: 'version',
label: 'Version'
}
]
}
]
}
]
};

View File

@ -82,6 +82,7 @@ import FormEventActionSchema from './EventAction/cmpt-event-action/FormEvent';
import TransferEventSchema from './EventAction/cmpt-event-action/TransferEvent';
import ServiceEventSchema from './EventAction/cmpt-event-action/ServiceEvent';
import CarouselEventSchema from './EventAction/cmpt-event-action/CarouselEvent';
import TableEventSchema from './EventAction/cmpt-event-action/TableEvent';
import ReloadFormActionSchema from './EventAction/reload-action/ReloadForm';
import ReloadSelectActionSchema from './EventAction/reload-action/ReloadSelect';
import ReloadChartActionSchema from './EventAction/reload-action/ReloadChart';
@ -695,6 +696,11 @@ export const examples = [
label: 'Service组件',
path: 'examples/event/service',
component: makeSchemaRenderer(ServiceEventSchema)
},
{
label: '表格组件',
path: 'examples/event/table',
component: makeSchemaRenderer(TableEventSchema)
}
]
},

View File

@ -100,9 +100,9 @@ export class HeadCellFilterDropDown extends React.Component<
}
}
}
if (
this.props.data[name] !== prevProps.data[name] &&
const value = this.props.data ? this.props.data[name] : undefined;
const prevValue = prevProps.data ? prevProps.data[name] : undefined;
if (value !== prevValue &&
this.state.filterOptions.length &&
prevState.filterOptions !== this.props.filterOptions
) {
@ -174,7 +174,8 @@ export class HeadCellFilterDropDown extends React.Component<
const rendererEvent = await dispatchEvent(
'columnFilter',
createObject(data, {
[name]: value
filterName: name,
filterValue: value
})
);
@ -202,7 +203,8 @@ export class HeadCellFilterDropDown extends React.Component<
const rendererEvent = await dispatchEvent(
'columnFilter',
createObject(data, {
[name]: query
filterName: name,
filterValue: query
})
);
@ -239,7 +241,7 @@ export class HeadCellFilterDropDown extends React.Component<
<span
className={cx(
`${ns}TableCell-filterBtn`,
typeof data[name] !== 'undefined' ? 'is-active' : ''
data && typeof data[name] !== 'undefined' ? 'is-active' : ''
)}
>
<span onClick={this.open}>

View File

@ -204,7 +204,10 @@ export class HeadCellSearchDropDown extends React.Component<
const rendererEvent = await dispatchEvent(
'columnSearch',
createObject(data, values)
createObject(data, {
searchName: name,
searchValue: values
})
);
if (rendererEvent?.prevented) {

View File

@ -10,6 +10,7 @@ import ItemActionsWrapper from './ItemActionsWrapper';
import {SchemaTpl, SchemaIcon} from '../../Schema';
import {generateIcon} from '../../utils/icon';
import {Icon} from '../../components/icons';
import {OnEventProps} from '../../utils/renderer-event';
export interface TableContentProps extends LocaleProps {
className?: string;
@ -60,6 +61,7 @@ export interface TableContentProps extends LocaleProps {
itemActions?: Array<Action>;
store: ITableStore;
dispatchEvent?: Function;
onEvent?: OnEventProps
}
@observer
@ -130,7 +132,8 @@ export class TableContent extends React.Component<TableContentProps> {
affixRow,
store,
emptyIcon,
dispatchEvent
dispatchEvent,
onEvent
} = this.props;
const tableClassName = cx('Table-table', this.props.tableClassName);
@ -230,7 +233,8 @@ export class TableContent extends React.Component<TableContentProps> {
data={data}
rowsProps={{
data,
dispatchEvent
dispatchEvent,
onEvent
}}
></TableBody>
)}

View File

@ -47,7 +47,7 @@ export class TableRow extends React.Component<TableRowProps> {
const rendererEvent = await dispatchEvent(
'rowClick',
createObject(data, {
item
rowItem: item?.data
})
);
@ -119,6 +119,7 @@ export class TableRow extends React.Component<TableRowProps> {
classnames: cx,
parent,
itemAction,
onEvent,
...rest
} = this.props;
@ -132,7 +133,7 @@ export class TableRow extends React.Component<TableRowProps> {
data-id={item.id}
data-index={item.newIndex}
onClick={
checkOnItemClick || itemAction ? this.handleItemClick : undefined
checkOnItemClick || itemAction || onEvent?.rowClick ? this.handleItemClick : undefined
}
className={cx(itemClassName, {
'is-hovered': item.isHover,
@ -196,7 +197,7 @@ export class TableRow extends React.Component<TableRowProps> {
return (
<tr
onClick={
checkOnItemClick || itemAction ? this.handleItemClick : undefined
checkOnItemClick || itemAction || onEvent?.rowClick ? this.handleItemClick : undefined
}
data-index={item.depth === 1 ? item.newIndex : undefined}
data-id={item.id}

View File

@ -957,16 +957,28 @@ export default class Table extends React.Component<TableProps, object> {
);
}
handleSaveOrder() {
const {store, onSaveOrder} = this.props;
async handleSaveOrder() {
const {store, onSaveOrder, data, dispatchEvent} = this.props;
const movedItems = store.movedRows.map(item => item.data);
const items = store.rows.map(item => item.getDataWithModifiedChilden());
const rendererEvent = await dispatchEvent(
'orderChange',
createObject(data, {movedItems})
);
if (rendererEvent?.prevented) {
return;
}
if (!onSaveOrder || !store.movedRows.length) {
return;
}
onSaveOrder(
store.movedRows.map(item => item.data),
store.rows.map(item => item.getDataWithModifiedChilden())
movedItems,
items
);
}
@ -1231,7 +1243,7 @@ export default class Table extends React.Component<TableProps, object> {
}
initDragging() {
const {store, classPrefix: ns, data, dispatchEvent} = this.props;
const {store, classPrefix: ns} = this.props;
this.sortable = new Sortable(
(this.table as HTMLElement).querySelector('tbody') as HTMLElement,
{
@ -1246,15 +1258,6 @@ export default class Table extends React.Component<TableProps, object> {
return;
}
const rendererEvent = await dispatchEvent(
'orderChange',
createObject(data, {oldIndex: e.oldIndex, newIndex: e.newIndex})
);
if (rendererEvent?.prevented) {
return;
}
const parent = e.to as HTMLElement;
if (e.oldIndex < parent.childNodes.length - 1) {
parent.insertBefore(e.item, parent.childNodes[e.oldIndex]);
@ -1384,24 +1387,12 @@ export default class Table extends React.Component<TableProps, object> {
@autobind
async handleDrop() {
const {store, data, dispatchEvent} = this.props;
const {store} = this.props;
const tr = this.draggingTr;
const tbody = tr.parentElement!;
const index = Array.prototype.indexOf.call(tbody.childNodes, tr);
const item: IRow = store.getRowById(tr.getAttribute('data-id')!) as any;
const rendererEvent = await dispatchEvent(
'orderChange',
createObject(data, {
oldIndex: this.originIndex,
newIndex: index
})
);
if (rendererEvent?.prevented) {
return;
}
// destroy
this.handleDragEnd();
@ -2154,7 +2145,8 @@ export default class Table extends React.Component<TableProps, object> {
rowClassNameExpr,
rowClassName,
itemAction,
dispatchEvent
dispatchEvent,
onEvent
} = this.props;
const hideHeader = store.filteredColumns.every(column => !column.label);
const columnsGroup = store.columnGroup;
@ -2242,7 +2234,8 @@ export default class Table extends React.Component<TableProps, object> {
props: any
) => this.renderCell(region, column, item, props, true),
data,
dispatchEvent
dispatchEvent,
onEvent
}}
/>
)}
@ -2311,13 +2304,13 @@ export default class Table extends React.Component<TableProps, object> {
onClick={async () => {
const {data, dispatchEvent} = this.props;
const allToggled = !(store.activeToggaleColumns.length === store.toggableColumns.length);
const rendererEvent = await dispatchEvent(
'columnToggled',
createObject(data, {
toggled: !(
store.activeToggaleColumns.length ===
store.toggableColumns.length
)
columns: allToggled
? store.toggableColumns.map(column => column.pristine)
: []
})
);
@ -2352,12 +2345,16 @@ export default class Table extends React.Component<TableProps, object> {
key={column.index}
onClick={async () => {
const {data, dispatchEvent} = this.props;
let columns = store.activeToggaleColumns.map(item => item.pristine);
if (!column.toggled) {
columns.push(column.pristine)
} else {
columns = columns.filter(c => c.name !== column.pristine.name);
}
const rendererEvent = await dispatchEvent(
'columnToggled',
createObject(data, {
column,
toggled: !column.toggled
columns
})
);
@ -2642,7 +2639,8 @@ export default class Table extends React.Component<TableProps, object> {
autoFillHeight,
itemActions,
emptyIcon,
dispatchEvent
dispatchEvent,
onEvent
} = this.props;
// 理论上来说 store.rows 应该也行啊
@ -2689,6 +2687,7 @@ export default class Table extends React.Component<TableProps, object> {
locale={locale}
translate={translate}
dispatchEvent={dispatchEvent}
onEvent={onEvent}
/>
);
}

View File

@ -666,7 +666,7 @@ export const TableStore = iRendererStore
},
get disabledHeadCheckbox() {
const selectedLength = self.data?.selectedItems.length;
const selectedLength = self.data?.selectedItems?.length;
const maxLength = self.maxKeepItemSelectionLength;
if (!self.data || !self.keepItemSelectionOnPageChange || !maxLength) {