diff --git a/examples/components/EventAction/cmpt-event-action/TableEvent.jsx b/examples/components/EventAction/cmpt-event-action/TableEvent.jsx new file mode 100644 index 000000000..2537aca6f --- /dev/null +++ b/examples/components/EventAction/cmpt-event-action/TableEvent.jsx @@ -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' + } + ] + } + ] + } + ] +}; diff --git a/examples/components/Example.jsx b/examples/components/Example.jsx index c354a21ec..992941376 100644 --- a/examples/components/Example.jsx +++ b/examples/components/Example.jsx @@ -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) } ] }, diff --git a/src/renderers/Table/HeadCellFilterDropdown.tsx b/src/renderers/Table/HeadCellFilterDropdown.tsx index aa37f6da8..623b36a8d 100644 --- a/src/renderers/Table/HeadCellFilterDropdown.tsx +++ b/src/renderers/Table/HeadCellFilterDropdown.tsx @@ -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< diff --git a/src/renderers/Table/HeadCellSearchDropdown.tsx b/src/renderers/Table/HeadCellSearchDropdown.tsx index 6192a4f94..ee0d4978b 100644 --- a/src/renderers/Table/HeadCellSearchDropdown.tsx +++ b/src/renderers/Table/HeadCellSearchDropdown.tsx @@ -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) { diff --git a/src/renderers/Table/TableContent.tsx b/src/renderers/Table/TableContent.tsx index 84fdb962f..c3ffd63ea 100644 --- a/src/renderers/Table/TableContent.tsx +++ b/src/renderers/Table/TableContent.tsx @@ -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; store: ITableStore; dispatchEvent?: Function; + onEvent?: OnEventProps } @observer @@ -130,7 +132,8 @@ export class TableContent extends React.Component { 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 { data={data} rowsProps={{ data, - dispatchEvent + dispatchEvent, + onEvent }} > )} diff --git a/src/renderers/Table/TableRow.tsx b/src/renderers/Table/TableRow.tsx index d00dbed66..7d3d01e36 100644 --- a/src/renderers/Table/TableRow.tsx +++ b/src/renderers/Table/TableRow.tsx @@ -47,7 +47,7 @@ export class TableRow extends React.Component { const rendererEvent = await dispatchEvent( 'rowClick', createObject(data, { - item + rowItem: item?.data }) ); @@ -119,6 +119,7 @@ export class TableRow extends React.Component { classnames: cx, parent, itemAction, + onEvent, ...rest } = this.props; @@ -132,7 +133,7 @@ export class TableRow extends React.Component { 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 { return ( { ); } - 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 { } 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 { 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 { @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 { 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 { props: any ) => this.renderCell(region, column, item, props, true), data, - dispatchEvent + dispatchEvent, + onEvent }} /> )} @@ -2311,13 +2304,13 @@ export default class Table extends React.Component { 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 { 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 { autoFillHeight, itemActions, emptyIcon, - dispatchEvent + dispatchEvent, + onEvent } = this.props; // 理论上来说 store.rows 应该也行啊 @@ -2689,6 +2687,7 @@ export default class Table extends React.Component { locale={locale} translate={translate} dispatchEvent={dispatchEvent} + onEvent={onEvent} /> ); } diff --git a/src/store/table.ts b/src/store/table.ts index d738e9c2e..312bbef87 100644 --- a/src/store/table.ts +++ b/src/store/table.ts @@ -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) {