/******************************************************************************************************************* * FarrisPrimengTreeTableBindingDirective指令说明 * * ***************************************************************************************************************** * * 1. 依赖primeng版本: primeng:^9.0.0,primeicons:^4.0.0 * * 2. 由于可编辑树表无法触发编辑单元格的关闭事件onEditComplete,因此对priemeng的node_modules\primeng\fesm5\primeng-treetable.js脚本作出修改: * 源码修改如下,+表示新增加的脚本语句: * * TreeTable.prototype.updateEditingCell = function (cell, data, field) { //+ 参数增加data和field * this.editingCell = cell; * this.editingCellData = data; //+ * this.editingCellField = field; //+ * this.bindDocumentEditListener(); * }; * * TreeTable.prototype.bindDocumentEditListener = function () { * var _this = this; * if (!this.documentEditListener) { * this.documentEditListener = function (event) { * if (_this.editingCell && !_this.editingCellClick && _this.isEditingCellValid()) { * domhandler_1.DomHandler.removeClass(_this.editingCell, 'ui-editing-cell'); * _this.editingCell = null; * _this.onEditComplete.emit({ field: _this.editingCellField, data: _this.editingCellData });//+ * _this.unbindDocumentEditListener(); * } * _this.editingCellClick = false; * }; * document.addEventListener('click', this.documentEditListener); * } * }; * * TreeTable.prototype.bindDocumentEditListener = function () { * var _this = this; * if (!this.documentEditListener) { * this.documentEditListener = function (event) { * if (_this.editingCell && !_this.editingCellClick && _this.isEditingCellValid()) { * domhandler_1.DomHandler.removeClass(_this.editingCell, 'ui-editing-cell'); * _this.editingCell = null; * _this.onEditComplete.emit({ field: _this.editingCellField, data: _this.editingCellData });//+ * _this.unbindDocumentEditListener(); * } * _this.editingCellClick = false; * }; * document.addEventListener('click', this.documentEditListener); * } * }; * * TTEditableColumn.prototype.openCell = function () { * var _this = this; * this.tt.updateEditingCell(this.el.nativeElement,this.data, this.field);//+ * domhandler_1.DomHandler.addClass(this.el.nativeElement, 'ui-editing-cell'); * this.tt.onEditInit.emit({ field: this.field, data: this.data }); * this.zone.runOutsideAngular(function () { * setTimeout(function () { * var focusable = domhandler_1.DomHandler.findSingle(_this.el.nativeElement, 'input, textarea'); * if (focusable) { * focusable.focus(); * } * }, 50); * }); * }; * * TTEditableColumn.prototype.onClick = function (event) { * if (this.isEnabled()) { * this.tt.editingCellClick = true; * if (this.tt.editingCell) { * if (this.tt.editingCell !== this.el.nativeElement) { * if (!this.tt.isEditingCellValid()) { * return; * } * this.tt.onEditComplete.emit({ field: this.tt.oldField, data: this.tt.oldDdata });//+ * DomHandler.removeClass(this.tt.editingCell, 'ui-editing-cell'); * this.openCell(); * } * } * else { * this.openCell(); * } * } * }; * * TTEditableColumn.prototype.openCell = function () { * var _this = this; * this.tt.updateEditingCell(this.el.nativeElement,this.data, this.field); * DomHandler.addClass(this.el.nativeElement, 'ui-editing-cell'); * this.tt.onEditInit.emit({ field: this.field, data: this.data }); * this.tt.oldField= this.field; //+ * this.tt.oldDdata=this.data; //+ * this.zone.runOutsideAngular(function () { * setTimeout(function () { * var focusable = DomHandler.findSingle(_this.el.nativeElement, 'input, textarea'); * if (focusable) { * focusable.focus(); * } * }, 50); * }); * }; * * 3. HTML模板 * (1) 不启用多表头 * * * * * {{col.header}} * * * * * * * * * * * * {{ col | formatCellData : rowData }} * * * * * * * (2) 启用多表头 * * * * * * {{col.header}} * * * * * * * * * * * * {{ col | formatCellData : rowData }} * * * * * * * 多表头数据格式: * this.treeGridColumnHeaders=[ * [{ header: 'Brand',rowspan:3, colspan:1},{ header: 'Sale Rate',rowspan:1, colspan:4}], * [{ header: 'Sales',rowspan:1, colspan:2},{ header: 'Profits',rowspan:1, colspan:2}], * [{ header: 'Last Year',rowspan:1, colspan:1},{ header: 'This Year',rowspan:1, colspan:1},{ header: 'Last Year',rowspan:1, colspan:1},{ header: 'This Year',rowspan:1, colspan:1}], * ] **********************************************************************************************************************/ import { OnInit, OnChanges, SimpleChanges, EventEmitter } from '@angular/core'; import { FrameContext } from '@farris/devkit'; import { TreeTable } from 'primeng/treetable'; import { TreeNode } from 'primeng/api'; import { DateTimeHelperService } from '@farris/ui-common/date'; export interface FarrisPrimengTreeNode extends TreeNode { id?: string; } export declare class FarrisPrimengTreeTableBindingDirective implements OnInit, OnChanges { private treeTable; private frameContext; private dateService; private selectedRowId; private treeTableSelectedEvent; /** * 分级码信息字段,属性可能有两种格式的值:分级码字段(主表)或从表前端codes/分级码字段(子表) */ hierarchyInfoKey: string; columns: any; /** * 内码,数据的唯一标识 */ idField: string; /** * 节点选择变更事件 */ nodeSelectChange: EventEmitter; private oldTreeNodeMap; /** * 分级码的字段编号,从hierarchyInfoKey属性中解析获取 */ private hierarchyInfoField; /** * 绑定数据 */ private readonly bindingData; /** * 绑定数据列表 */ private readonly bindingList; private getHierarchyInfoField; constructor(treeTable: TreeTable, frameContext: FrameContext, dateService: DateTimeHelperService); ngOnChanges(changes: SimpleChanges): void; ngOnInit(): void; /** * 获取树列表绑定数据对应的实体数组 * @returns 实体数组 */ private getEntityArr; /** * 将真实顺序标记到对应的实体上 * @param entityArr 实体数组 * @param treeNodes 树节点 */ private setActualIndex; /** * 前序递归遍历树节点并在对应实体上标记序号 * @param treeNode 树节点 * @param counter 序号器 * @param entityArr 实体数组 * @description * 在进行前端校验时,按照Entity在数组中的下标生成(错误提示的)行号的方式不适用于树列表, * 因为树列表可以在已经添加的节点上加入子节点,而Entity总是在最后追加新对象,导致二者的顺序不一定相同, * 所以在绑定数据的时候将树节点在列表中的真实顺序通过一个附加的属性(__ACTUAL_INDEX__)赋给Entity示例, * 当Entity调用validate方法时,检查是否存在该属性,如果存在则应用该属性的值作为行号。 */ private traverseTree; /** * 处理数据变更 * @param change 变更 * @returns 是否跳过绑定数据的整体刷新 * @description * 目的是尽量少的重新构造整个树列表,比如在发生值变化事件时尽量只更改变化的值就结束, * 如果任何变化都重新构造树,会导致Tab键切换功能难以实现等问题。 */ private handleChange; /** * 处理行切换变更 * @param change 变更 * @returns 是否跳过绑定数据的整体刷新 */ private handleSelectionChanged; /** * 处理行切换变更 * @param change 变更 * @returns 是否跳过绑定数据的整体刷新 */ private handleValueChanged; /** * 通过主键值查找树节点 * @param treeNode 树根节点 * @param primaryKey 主键名 * @param keyValue 主键值 * @returns 树节点 * @todo 递归遍历实现比较低效,考虑通过oldTreeNodeMap查找树节点 */ private findTreeNodeById; /** * 绑定数据 */ private bindData; private updateSelectedRow; onEditInitHandler(event: any): void; onEditCompleteHandler(event: any): void; onNodeExpandHandler(event: any): void; onNodeCollapseHandler(event: any): void; onNodeSelectHandler(event: any): void; onNodeUnselectHandler(event: any): void; private setNodeExpandedValue; private setCurrentIdToBindingList; private getPaths; private updateBindingList; private getBindingPathArray; private getValue; protected setChecks(ids: string[]): void; }