diff --git a/src/app/demo/pc/table/demo-set.module.ts b/src/app/demo/pc/table/demo-set.module.ts index f6cfbe00cd..d9eb18e708 100644 --- a/src/app/demo/pc/table/demo-set.module.ts +++ b/src/app/demo/pc/table/demo-set.module.ts @@ -109,6 +109,8 @@ import {TableProgressDemoComponent} from "./progress/demo.component"; import {TableProgressDemoModule} from "./progress/demo.module"; import { TableExpandDemoComponent } from './expand/demo.component'; import { TableExpandDemoModule } from './expand/demo.module'; +import { TableExpandTableDemoComponent } from './expand-rows/demo.component'; +import { TableExpandTableDemoModule } from './expand-rows/demo.module'; import { TableUpdateAdditionalColumnDefineDemoComponent } from "./update-additional-column-defines/demo.component"; import { TableUpdateAdditionalColumnDefineDemoModule } from "./update-additional-column-defines/demo.module"; import { TableExpandPageableDemoComponent } from './expand-pageable/demo.component'; @@ -280,6 +282,9 @@ export const routerConfig = [ { path: 'expand', component: TableExpandDemoComponent }, + { + path: 'expand-rows', component: TableExpandTableDemoComponent + }, { path: 'expand-pageable', component: TableExpandPageableDemoComponent }, @@ -303,7 +308,7 @@ export const routerConfig = [ TableNoDataDemoModule, TableHtmlRendererDemoModule, RebuildTableDataDemoModule, TableCellSelectRenderDemoModule, TableMixinTableDemoModule, TreeTableDemoModule, TableCellEditablePropertyDemoModule,TableDraggableDemoModule, TableUpdateColumnDefinesDemoModule, TableAutoSaveDemoModule, TableCellRenderFullDemoModule, TableAutoFillUpDemoModule, TableAutoPageableDemoModule, TableColumnWidthDemoModule, TableProgressDemoModule, TableExpandDemoModule, - TableExpandPageableDemoModule, TableUpdateAdditionalColumnDefineDemoModule + TableExpandPageableDemoModule, TableUpdateAdditionalColumnDefineDemoModule, TableExpandTableDemoModule ] }) export class TableDemoModule { diff --git a/src/app/demo/pc/table/expand-rows/demo.component.css b/src/app/demo/pc/table/expand-rows/demo.component.css new file mode 100644 index 0000000000..2abb249c14 --- /dev/null +++ b/src/app/demo/pc/table/expand-rows/demo.component.css @@ -0,0 +1,7 @@ +.demo-buttons { + margin-bottom: 12px; +} + +.demo-buttons span { + margin-right: 4px; +} \ No newline at end of file diff --git a/src/app/demo/pc/table/expand-rows/demo.component.html b/src/app/demo/pc/table/expand-rows/demo.component.html new file mode 100644 index 0000000000..6aeff70dfd --- /dev/null +++ b/src/app/demo/pc/table/expand-rows/demo.component.html @@ -0,0 +1,28 @@ + + + + + + +Table Expand + +
+ 展开方式 + +
+
+ 数据更新后是否保持打开 + +
+
+ 更新数据 + 重置数据 + 展开/关闭第三行 +
+ +
展开数据发生了变化的行数:{{row}}
+ +信息展示 + + \ No newline at end of file diff --git a/src/app/demo/pc/table/expand-rows/demo.component.ts b/src/app/demo/pc/table/expand-rows/demo.component.ts new file mode 100644 index 0000000000..b99b503ea6 --- /dev/null +++ b/src/app/demo/pc/table/expand-rows/demo.component.ts @@ -0,0 +1,105 @@ +import { Component, ViewChild } from "@angular/core"; +import { TableData, JigsawTable, TableCellSwitchRenderer, TableCellCheckboxRenderer } from "jigsaw/public_api"; + +@Component({ + templateUrl: './demo.component.html', + styleUrls: ['./demo.component.css'] +}) +export class TableExpandTableDemoComponent { + action = ['toggle']; + tableData: TableData; + remainOpen: boolean = false; + + @ViewChild('tableCmp') + tableCmp: JigsawTable; + + row: number; + + constructor() { + this.resetData(); + } + + rowData = [ + ["cell-1", { data: false, renderer: TableCellSwitchRenderer }, { + data: `点击`, + renderer: 'html' + }, "cell-4", "cell-5", "cell-6", { data: true, renderer: TableCellCheckboxRenderer }], + ["cell-1", { data: true, renderer: TableCellSwitchRenderer }, { + data: ``, + renderer: 'html' + }, "cell-4", "cell-5", "cell-6", { data: false, renderer: TableCellCheckboxRenderer }], + ["cell-1", { data: false, renderer: TableCellSwitchRenderer, rendererInitData: { valid: false } }, { + data: ` 图标`, + renderer: 'html' + }, "cell-4", "cell-5", "cell-6", { data: false, renderer: TableCellCheckboxRenderer, rendererInitData: { valid: false } }], + ["cell-1", { data: true, renderer: TableCellSwitchRenderer, rendererInitData: { disabled: true } }, , { + data: `文本`, + renderer: 'html' + }, "cell-4", "cell-5", "cell-6", { data: true, renderer: TableCellCheckboxRenderer, rendererInitData: { disabled: true } }] + ] + + onClick() { + alert("按钮被点击了"); + } + + rowClick(rowIndex: number) { + this.tableCmp.expand(rowIndex, this.rowData, this, { + remainOpenAfterDataChanges: this.remainOpen, action: this.action[0] + }); + }; + + updateData() { + this.tableData.fromObject({ + data: [ + ["Emily", "", "$15128", "2017/4/21", "HR II", 23, ""], + ["Shirley", "", "$11845", "2017/4/25", "R&D Dept II", 42, ""], + ["Easton", "", "$17636", "2017/4/24", "Marketing I", 36, ""], + ["Emily", "", "$15128", "2017/4/21", "HR II", 65, ""], + ["Shirley", "", "$11845", "2017/4/25", "R&D Dept II", 71, ""], + ], + field: ["name", "switch", "salary", "enroll-date", "office", "progress", "checkbox"], + header: ["姓名", "开关组件", "薪资", "入职日期", "部门", "工作进度", "多选框"] + }) + } + + resetData() { + this.tableData = new TableData(); + this.tableData.fromObject({ + data: [ + ["Emily", "", "$15128", "2017/4/21", "HR II", 23, ""], + ["Shirley", "", "$11845", "2017/4/25", "R&D Dept II", 42, ""], + ["Easton", "", "$17636", "2017/4/24", "Marketing I", 36, ""], + ["Emily", "", "$15128", "2017/4/21", "HR II", 65, ""], + ["Shirley", "", "$11845", "2017/4/25", "R&D Dept II", 71, ""], + ["Easton", "", "$17636", "2017/4/24", "Marketing I", 56, ""], + ["Emily", "", "$15128", "2017/4/21", "HR II", 17, ""], + ["Shirley", "", "$11845", "2017/4/25", "R&D Dept II", 38, ""], + ["Easton", "", "$17636", "2017/4/24", "Marketing I", 9, ""], + ["Emily", "", "$15128", "2017/4/21", "HR II", 100, ""], + ["Shirley", "", "$11845", "2017/4/25", "R&D Dept II", 11, ""], + ["Easton", "", "$17636", "2017/4/24", "Marketing I", 82, ""] + ], + field: ["name", "switch", "salary", "enroll-date", "office", "progress", "checkbox"], + header: ["姓名", "开关组件", "薪资", "入职日期", "部门", "工作进度", "多选框"] + }) + } + + expandRow(rowIndex: number) { + this.tableCmp.expand(rowIndex, this.rowData, this, { + remainOpenAfterDataChanges: this.remainOpen, action: this.action[0] + }); + } + + rowExpandDataChange($event) { + this.row = $event.row; + } + + + + + // ==================================================================== + // ignore the following lines, they are not important to this demo + // ==================================================================== + summary: string = ''; + description: string = ''; +} diff --git a/src/app/demo/pc/table/expand-rows/demo.module.ts b/src/app/demo/pc/table/expand-rows/demo.module.ts new file mode 100644 index 0000000000..7965afb68a --- /dev/null +++ b/src/app/demo/pc/table/expand-rows/demo.module.ts @@ -0,0 +1,17 @@ +import {NgModule} from '@angular/core'; +import { + JigsawTableModule, JigsawButtonModule, JigsawHeaderModule, JigsawButtonBarModule, JigsawSwitchModule +} from "jigsaw/public_api"; +import {JigsawDemoDescriptionModule} from "app/demo-description/demo-description"; +import {TableExpandTableDemoComponent} from './demo.component'; + +@NgModule({ + imports: [ + JigsawTableModule, JigsawDemoDescriptionModule, JigsawButtonModule, JigsawHeaderModule, + JigsawButtonBarModule, JigsawSwitchModule + ], + declarations: [TableExpandTableDemoComponent], + exports: [TableExpandTableDemoComponent] +}) +export class TableExpandTableDemoModule { +} diff --git a/src/app/demo/pc/table/expand/demo.component.html b/src/app/demo/pc/table/expand/demo.component.html index 4ab44adc7c..ce251c6a24 100644 --- a/src/app/demo/pc/table/expand/demo.component.html +++ b/src/app/demo/pc/table/expand/demo.component.html @@ -4,8 +4,8 @@ -Table -expand +Table Expand +
展开方式 @@ -19,5 +19,7 @@ 重置数据 展开/关闭第三行
+ +信息展示 - + \ No newline at end of file diff --git a/src/app/demo/pc/table/expand/demo.component.ts b/src/app/demo/pc/table/expand/demo.component.ts index 88d85b4b9f..0ce00ed220 100644 --- a/src/app/demo/pc/table/expand/demo.component.ts +++ b/src/app/demo/pc/table/expand/demo.component.ts @@ -1,5 +1,5 @@ import { Component, ViewChild } from "@angular/core"; -import { TableData, ColumnDefine, JigsawTable } from "jigsaw/public_api"; +import { TableData, ColumnDefine, JigsawTable, TableCellSwitchRenderer } from "jigsaw/public_api"; @Component({ templateUrl: './demo.component.html', diff --git a/src/jigsaw/pc-components/table/table.ts b/src/jigsaw/pc-components/table/table.ts index a7e3368cf1..734b508f42 100644 --- a/src/jigsaw/pc-components/table/table.ts +++ b/src/jigsaw/pc-components/table/table.ts @@ -3,6 +3,7 @@ ChangeDetectionStrategy, ChangeDetectorRef, Component, + ComponentFactoryResolver, ElementRef, EventEmitter, Injector, @@ -15,7 +16,8 @@ QueryList, Renderer2, ViewChild, - ViewChildren + ViewChildren, + ApplicationRef } from "@angular/core"; import {CommonModule} from "@angular/common"; import {Subscription} from "rxjs"; @@ -23,7 +25,7 @@ import {TranslateModule, TranslateService} from "@ngx-translate/core"; import {PerfectScrollbarDirective, PerfectScrollbarModule} from "ngx-perfect-scrollbar"; import {AbstractJigsawComponent, JigsawCommonModule, WingsTheme} from "../../common/common"; import {JigsawTableCellInternalComponent, JigsawTableHeaderInternalComponent} from "./table-inner.components"; -import {TableData} from "../../common/core/data/table-data"; +import {TableData, TableDataMatrix} from "../../common/core/data/table-data"; import {AffixUtils, InternalUtils} from "../../common/core/utils/internal-utils"; import { _getColumnIndex, @@ -58,10 +60,10 @@ import {TableUtils} from "./table-utils"; }) export class JigsawTable extends AbstractJigsawComponent implements OnInit, AfterViewInit, OnDestroy { - constructor(private _renderer: Renderer2, private _elementRef: ElementRef, - protected _zone: NgZone, private _changeDetectorRef: ChangeDetectorRef, - // @RequireMarkForCheck 需要用到,勿删 - private _injector: Injector) { + constructor(private _renderer: Renderer2, private _elementRef: ElementRef, protected _zone: NgZone, private _changeDetectorRef: ChangeDetectorRef, + private _componentFactoryResolver: ComponentFactoryResolver, private _applicationRef: ApplicationRef, + // @RequireMarkForCheck 需要用到,勿删 + private _injector: Injector) { super(); if (CommonUtils.getBrowserType() == 'Firefox') { this._$isFFBrowser = true; @@ -151,6 +153,8 @@ export class JigsawTable extends AbstractJigsawComponent implements OnInit, Afte public selectedRowChange: EventEmitter = new EventEmitter(); @Output() public rowExpand: EventEmitter = new EventEmitter(); + @Output() + public rowExpandDataChange = new EventEmitter<{ row: number, data: TableDataMatrix }>(); private _getColumnIndex(field: string): [number, TableData] { return _getColumnIndex(this.data, this._additionalData, field); @@ -905,7 +909,7 @@ export class JigsawTable extends AbstractJigsawComponent implements OnInit, Afte /** * 展开行 */ - public expand(rowIndex: number, rawHtml: string, rawHtmlContext?: object, options?: TableRowExpandOptions): void { + public expand(rowIndex: number, rawHtml: string | TableDataMatrix, rawHtmlContext?: object, options?: TableRowExpandOptions): void { const rowElement = this._rowElementRefs.toArray()[rowIndex]?.nativeElement; if (!rowElement) { return; @@ -926,9 +930,11 @@ export class JigsawTable extends AbstractJigsawComponent implements OnInit, Afte // 已经打开了,但此时人家要求再打开,需要更新一下内容 const rowInfo = this._allExpandedRows.find(i => i?.element === rowElement.nextSibling); rowInfo.remainOpen = options?.remainOpenAfterDataChanges; - rowInfo.element.children[0].innerHTML = TrustedHtmlHelper.updateHtml( - CommonUtils.isUndefined(rawHtml) ? "" : rawHtml, rawHtmlContext, []); - return; + if (typeof rawHtml === 'string') { + rowInfo.element.children[0].innerHTML = TrustedHtmlHelper.updateHtml( + CommonUtils.isUndefined(rawHtml) ? "" : rawHtml, rawHtmlContext, []); + return; + } } if (!expanded && action == 'show') { // 该行还没打开,人家要求打开 @@ -948,26 +954,107 @@ export class JigsawTable extends AbstractJigsawComponent implements OnInit, Afte private _allExpandedRows: { element: HTMLTableRowElement, remainOpen: boolean, rowIndex: number, currentPage: number }[] = []; - private _showExpansion(rowElement: HTMLTableRowElement, rawHtml: string, context: object, remainOpen: boolean, rowIndex: number): void { - const tr = document.createElement('tr'); - const trustedEle = document.createElement('td'); - const headerEle = this._headerComponents.toArray(); - trustedEle.colSpan = headerEle.length; - tr.classList.add('jigsaw-table-row-expansion'); - tr.insertBefore(trustedEle, tr.lastElementChild); - - const trustedHtml = CommonUtils.isUndefined(rawHtml) ? "" : rawHtml; - trustedEle.innerHTML = TrustedHtmlHelper.updateHtml(trustedHtml, context, []); - rowElement.parentNode.insertBefore(tr, rowElement.nextSibling); - const data: IPageable = this.data; - const currentPage = data?.pagingInfo instanceof PagingInfo ? data.pagingInfo.currentPage : undefined; - this._allExpandedRows.push({ element: tr, rowIndex, remainOpen, currentPage }); + private _showExpansion(rowElement: HTMLTableRowElement, rawHtml: string | TableDataMatrix, context: object, remainOpen: boolean, rowIndex: number): void { + if (typeof rawHtml === 'string') { + + const tr = document.createElement('tr'); + const trustedEle = document.createElement('td'); + const headerEle = this._headerComponents.toArray(); + trustedEle.colSpan = headerEle.length; + tr.classList.add('jigsaw-table-row-expansion'); + tr.insertBefore(trustedEle, tr.lastElementChild); + + const trustedHtml = CommonUtils.isUndefined(rawHtml) ? "" : rawHtml; + trustedEle.innerHTML = TrustedHtmlHelper.updateHtml(trustedHtml, context, []); + rowElement.parentNode.insertBefore(tr, rowElement.nextSibling); + const data: IPageable = this.data; + const currentPage = data?.pagingInfo instanceof PagingInfo ? data.pagingInfo.currentPage : undefined; + this._allExpandedRows.push({ element: tr, rowIndex, remainOpen, currentPage }); + } + + if (rawHtml instanceof Array) { + const tableData = new TableData(); + const data = []; + const field = []; + + rawHtml.forEach(row => { + const rowData = []; + row.forEach((cell, colIndex) => { + if (CommonUtils.isUndefined(cell.data)) { + rowData.push(cell); + } else { + rowData.push(cell.data) + } + field.push('row-expand-field' + colIndex) + }) + data.push(rowData); + }) + + tableData.fromObject({ + data: data, + field: field, + header: field + }) + + tableData.onRefresh(() => { + this.rowExpandDataChange.emit({ row: rowIndex, data: tableData.data }) + }) + + const trEleArr = []; + rawHtml.forEach((row, rowIndex) => { + const tr = document.createElement('tr'); + tr.classList.add('jigsaw-table-row-expansion'); + + row.forEach((cell, colIndex) => { + const td = document.createElement('td'); + + if (cell.renderer === 'html') { + const trustedHtml = CommonUtils.isUndefined(cell.data) ? "" : cell.data; + td.innerHTML = TrustedHtmlHelper.updateHtml(trustedHtml, context, []); + tr.appendChild(td); + return; + } + + let factory = this._componentFactoryResolver.resolveComponentFactory(JigsawTableCellInternalComponent); + const componentRef = factory.create(this._injector, [], td); + let cellSettings = cell; + if (typeof cell === 'string') { + cellSettings = { + renderer: DefaultCellRenderer, + data: cell + } + } + + componentRef.instance.field = 'row-expand-field' + colIndex; + componentRef.instance.row = rowIndex; + componentRef.instance.tableData = tableData; + componentRef.instance.additionalData = new TableData(); + componentRef.instance.renderer = cellSettings.renderer; + componentRef.instance.rendererInitData = cellSettings.rendererInitData; + componentRef.instance.cellData = cellSettings.data; + this._applicationRef.attachView(componentRef.hostView); + tr.appendChild(td); + }) + trEleArr.push(tr); + }) + + trEleArr.reverse().forEach(tr => { + rowElement.parentNode.insertBefore(tr, rowElement.nextSibling); + const data: IPageable = this.data; + const currentPage = data?.pagingInfo instanceof PagingInfo ? data.pagingInfo.currentPage : undefined; + this._allExpandedRows.push({ element: tr, rowIndex, remainOpen, currentPage }); + }) + } } private _hideExpansion(rowElement: HTMLTableRowElement): void { const index = this._allExpandedRows.findIndex(i => i?.element === rowElement.nextSibling); + if (index == -1) { + return; + } this._allExpandedRows.splice(index, 1); rowElement.nextSibling.remove(); + this._hideExpansion(rowElement); } private _clearExpansion() {