UNPKG

primeng

Version:

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![npm version](https://badge.fury.io/js/primeng.svg)](https://badge.fury.io/js/primeng) [![npm downloads](https://img.shields.io/npm/dm/primeng.sv

1,121 lines (1,120 loc) 145 kB
import * as i0 from '@angular/core'; import { Injectable, EventEmitter, Component, ViewEncapsulation, Input, Output, ViewChild, ContentChildren, Directive, HostListener, ChangeDetectionStrategy, NgModule } from '@angular/core'; import * as i3 from '@angular/common'; import { CommonModule } from '@angular/common'; import { Subject } from 'rxjs'; import { DomHandler } from 'primeng/dom'; import * as i2 from 'primeng/paginator'; import { PaginatorModule } from 'primeng/paginator'; import * as i1 from 'primeng/api'; import { PrimeTemplate, SharedModule } from 'primeng/api'; import { ObjectUtils } from 'primeng/utils'; import * as i5 from 'primeng/ripple'; import { RippleModule } from 'primeng/ripple'; import * as i4 from '@angular/cdk/scrolling'; import { CdkVirtualScrollViewport, ScrollingModule } from '@angular/cdk/scrolling'; class TreeTableService { constructor() { this.sortSource = new Subject(); this.selectionSource = new Subject(); this.contextMenuSource = new Subject(); this.uiUpdateSource = new Subject(); this.totalRecordsSource = new Subject(); this.sortSource$ = this.sortSource.asObservable(); this.selectionSource$ = this.selectionSource.asObservable(); this.contextMenuSource$ = this.contextMenuSource.asObservable(); this.uiUpdateSource$ = this.uiUpdateSource.asObservable(); this.totalRecordsSource$ = this.totalRecordsSource.asObservable(); } onSort(sortMeta) { this.sortSource.next(sortMeta); } onSelectionChange() { this.selectionSource.next(); } onContextMenu(node) { this.contextMenuSource.next(node); } onUIUpdate(value) { this.uiUpdateSource.next(value); } onTotalRecordsChange(value) { this.totalRecordsSource.next(value); } } TreeTableService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.0.4", ngImport: i0, type: TreeTableService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); TreeTableService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.0.4", ngImport: i0, type: TreeTableService }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.0.4", ngImport: i0, type: TreeTableService, decorators: [{ type: Injectable }] }); class TreeTable { constructor(el, zone, tableService, filterService) { this.el = el; this.zone = zone; this.tableService = tableService; this.filterService = filterService; this.lazy = false; this.lazyLoadOnInit = true; this.first = 0; this.pageLinks = 5; this.alwaysShowPaginator = true; this.paginatorPosition = 'bottom'; this.currentPageReportTemplate = '{currentPage} of {totalPages}'; this.showFirstLastIcon = true; this.showPageLinks = true; this.defaultSortOrder = 1; this.sortMode = 'single'; this.resetPageOnSort = true; this.selectionChange = new EventEmitter(); this.contextMenuSelectionChange = new EventEmitter(); this.contextMenuSelectionMode = "separate"; this.compareSelectionBy = 'deepEquals'; this.loadingIcon = 'pi pi-spinner'; this.showLoader = true; this.virtualScrollDelay = 150; this.virtualRowHeight = 28; this.columnResizeMode = 'fit'; this.rowTrackBy = (index, item) => item; this.filters = {}; this.filterDelay = 300; this.filterMode = 'lenient'; this.onFilter = new EventEmitter(); this.onNodeExpand = new EventEmitter(); this.onNodeCollapse = new EventEmitter(); this.onPage = new EventEmitter(); this.onSort = new EventEmitter(); this.onLazyLoad = new EventEmitter(); this.sortFunction = new EventEmitter(); this.onColResize = new EventEmitter(); this.onColReorder = new EventEmitter(); this.onNodeSelect = new EventEmitter(); this.onNodeUnselect = new EventEmitter(); this.onContextMenuSelect = new EventEmitter(); this.onHeaderCheckboxToggle = new EventEmitter(); this.onEditInit = new EventEmitter(); this.onEditComplete = new EventEmitter(); this.onEditCancel = new EventEmitter(); this._value = []; this._totalRecords = 0; this._sortOrder = 1; this.selectionKeys = {}; } ngOnInit() { if (this.lazy && this.lazyLoadOnInit) { this.onLazyLoad.emit(this.createLazyLoadMetadata()); } this.initialized = true; } ngAfterContentInit() { this.templates.forEach((item) => { switch (item.getType()) { case 'caption': this.captionTemplate = item.template; break; case 'header': this.headerTemplate = item.template; break; case 'body': this.bodyTemplate = item.template; break; case 'loadingbody': this.loadingBodyTemplate = item.template; break; case 'footer': this.footerTemplate = item.template; break; case 'summary': this.summaryTemplate = item.template; break; case 'colgroup': this.colGroupTemplate = item.template; break; case 'emptymessage': this.emptyMessageTemplate = item.template; break; case 'paginatorleft': this.paginatorLeftTemplate = item.template; break; case 'paginatorright': this.paginatorRightTemplate = item.template; break; case 'paginatordropdownitem': this.paginatorDropdownItemTemplate = item.template; break; case 'frozenheader': this.frozenHeaderTemplate = item.template; break; case 'frozenbody': this.frozenBodyTemplate = item.template; break; case 'frozenfooter': this.frozenFooterTemplate = item.template; break; case 'frozencolgroup': this.frozenColGroupTemplate = item.template; break; } }); } ngOnChanges(simpleChange) { if (simpleChange.value) { this._value = simpleChange.value.currentValue; if (!this.lazy) { this.totalRecords = (this._value ? this._value.length : 0); if (this.sortMode == 'single' && this.sortField) this.sortSingle(); else if (this.sortMode == 'multiple' && this.multiSortMeta) this.sortMultiple(); else if (this.hasFilter()) //sort already filters this._filter(); } this.updateSerializedValue(); this.tableService.onUIUpdate(this.value); } if (simpleChange.sortField) { this._sortField = simpleChange.sortField.currentValue; //avoid triggering lazy load prior to lazy initialization at onInit if (!this.lazy || this.initialized) { if (this.sortMode === 'single') { this.sortSingle(); } } } if (simpleChange.sortOrder) { this._sortOrder = simpleChange.sortOrder.currentValue; //avoid triggering lazy load prior to lazy initialization at onInit if (!this.lazy || this.initialized) { if (this.sortMode === 'single') { this.sortSingle(); } } } if (simpleChange.multiSortMeta) { this._multiSortMeta = simpleChange.multiSortMeta.currentValue; if (this.sortMode === 'multiple') { this.sortMultiple(); } } if (simpleChange.selection) { this._selection = simpleChange.selection.currentValue; if (!this.preventSelectionSetterPropagation) { this.updateSelectionKeys(); this.tableService.onSelectionChange(); } this.preventSelectionSetterPropagation = false; } } get value() { return this._value; } set value(val) { this._value = val; } updateSerializedValue() { this.serializedValue = []; if (this.paginator) this.serializePageNodes(); else this.serializeNodes(null, this.filteredNodes || this.value, 0, true); } serializeNodes(parent, nodes, level, visible) { if (nodes && nodes.length) { for (let node of nodes) { node.parent = parent; const rowNode = { node: node, parent: parent, level: level, visible: visible && (parent ? parent.expanded : true) }; this.serializedValue.push(rowNode); if (rowNode.visible && node.expanded) { this.serializeNodes(node, node.children, level + 1, rowNode.visible); } } } } serializePageNodes() { let data = this.filteredNodes || this.value; this.serializedValue = []; if (data && data.length) { const first = this.lazy ? 0 : this.first; for (let i = first; i < (first + this.rows); i++) { let node = data[i]; if (node) { this.serializedValue.push({ node: node, parent: null, level: 0, visible: true }); this.serializeNodes(node, node.children, 1, true); } } } } get totalRecords() { return this._totalRecords; } set totalRecords(val) { this._totalRecords = val; this.tableService.onTotalRecordsChange(this._totalRecords); } get sortField() { return this._sortField; } set sortField(val) { this._sortField = val; } get sortOrder() { return this._sortOrder; } set sortOrder(val) { this._sortOrder = val; } get multiSortMeta() { return this._multiSortMeta; } set multiSortMeta(val) { this._multiSortMeta = val; } get selection() { return this._selection; } set selection(val) { this._selection = val; } updateSelectionKeys() { if (this.dataKey && this._selection) { this.selectionKeys = {}; if (Array.isArray(this._selection)) { for (let node of this._selection) { this.selectionKeys[String(ObjectUtils.resolveFieldData(node.data, this.dataKey))] = 1; } } else { this.selectionKeys[String(ObjectUtils.resolveFieldData(this._selection.data, this.dataKey))] = 1; } } } onPageChange(event) { this.first = event.first; this.rows = event.rows; if (this.lazy) this.onLazyLoad.emit(this.createLazyLoadMetadata()); else this.serializePageNodes(); this.onPage.emit({ first: this.first, rows: this.rows }); this.tableService.onUIUpdate(this.value); if (this.scrollable) { this.resetScrollTop(); } } sort(event) { let originalEvent = event.originalEvent; if (this.sortMode === 'single') { this._sortOrder = (this.sortField === event.field) ? this.sortOrder * -1 : this.defaultSortOrder; this._sortField = event.field; this.sortSingle(); if (this.resetPageOnSort && this.scrollable) { this.resetScrollTop(); } } if (this.sortMode === 'multiple') { let metaKey = originalEvent.metaKey || originalEvent.ctrlKey; let sortMeta = this.getSortMeta(event.field); if (sortMeta) { if (!metaKey) { this._multiSortMeta = [{ field: event.field, order: sortMeta.order * -1 }]; if (this.resetPageOnSort && this.scrollable) { this.resetScrollTop(); } } else { sortMeta.order = sortMeta.order * -1; } } else { if (!metaKey || !this.multiSortMeta) { this._multiSortMeta = []; if (this.resetPageOnSort && this.scrollable) { this.resetScrollTop(); } } this.multiSortMeta.push({ field: event.field, order: this.defaultSortOrder }); } this.sortMultiple(); } } sortSingle() { if (this.sortField && this.sortOrder) { if (this.lazy) { this.onLazyLoad.emit(this.createLazyLoadMetadata()); } else if (this.value) { this.sortNodes(this.value); if (this.hasFilter()) { this._filter(); } } let sortMeta = { field: this.sortField, order: this.sortOrder }; this.onSort.emit(sortMeta); this.tableService.onSort(sortMeta); this.updateSerializedValue(); } } sortNodes(nodes) { if (!nodes || nodes.length === 0) { return; } if (this.customSort) { this.sortFunction.emit({ data: nodes, mode: this.sortMode, field: this.sortField, order: this.sortOrder }); } else { nodes.sort((node1, node2) => { let value1 = ObjectUtils.resolveFieldData(node1.data, this.sortField); let value2 = ObjectUtils.resolveFieldData(node2.data, this.sortField); let result = null; if (value1 == null && value2 != null) result = -1; else if (value1 != null && value2 == null) result = 1; else if (value1 == null && value2 == null) result = 0; else if (typeof value1 === 'string' && typeof value2 === 'string') result = value1.localeCompare(value2, undefined, { numeric: true }); else result = (value1 < value2) ? -1 : (value1 > value2) ? 1 : 0; return (this.sortOrder * result); }); } for (let node of nodes) { this.sortNodes(node.children); } } sortMultiple() { if (this.multiSortMeta) { if (this.lazy) { this.onLazyLoad.emit(this.createLazyLoadMetadata()); } else if (this.value) { this.sortMultipleNodes(this.value); if (this.hasFilter()) { this._filter(); } } this.onSort.emit({ multisortmeta: this.multiSortMeta }); this.updateSerializedValue(); this.tableService.onSort(this.multiSortMeta); } } sortMultipleNodes(nodes) { if (!nodes || nodes.length === 0) { return; } if (this.customSort) { this.sortFunction.emit({ data: this.value, mode: this.sortMode, multiSortMeta: this.multiSortMeta }); } else { nodes.sort((node1, node2) => { return this.multisortField(node1, node2, this.multiSortMeta, 0); }); } for (let node of nodes) { this.sortMultipleNodes(node.children); } } multisortField(node1, node2, multiSortMeta, index) { let value1 = ObjectUtils.resolveFieldData(node1.data, multiSortMeta[index].field); let value2 = ObjectUtils.resolveFieldData(node2.data, multiSortMeta[index].field); let result = null; if (value1 == null && value2 != null) result = -1; else if (value1 != null && value2 == null) result = 1; else if (value1 == null && value2 == null) result = 0; if (typeof value1 == 'string' || value1 instanceof String) { if (value1.localeCompare && (value1 != value2)) { return (multiSortMeta[index].order * value1.localeCompare(value2, undefined, { numeric: true })); } } else { result = (value1 < value2) ? -1 : 1; } if (value1 == value2) { return (multiSortMeta.length - 1) > (index) ? (this.multisortField(node1, node2, multiSortMeta, index + 1)) : 0; } return (multiSortMeta[index].order * result); } getSortMeta(field) { if (this.multiSortMeta && this.multiSortMeta.length) { for (let i = 0; i < this.multiSortMeta.length; i++) { if (this.multiSortMeta[i].field === field) { return this.multiSortMeta[i]; } } } return null; } isSorted(field) { if (this.sortMode === 'single') { return (this.sortField && this.sortField === field); } else if (this.sortMode === 'multiple') { let sorted = false; if (this.multiSortMeta) { for (let i = 0; i < this.multiSortMeta.length; i++) { if (this.multiSortMeta[i].field == field) { sorted = true; break; } } } return sorted; } } createLazyLoadMetadata() { return { first: this.first, rows: this.rows, sortField: this.sortField, sortOrder: this.sortOrder, filters: this.filters, globalFilter: this.filters && this.filters['global'] ? this.filters['global'].value : null, multiSortMeta: this.multiSortMeta }; } resetScrollTop() { if (this.virtualScroll) this.scrollToVirtualIndex(0); else this.scrollTo({ top: 0 }); } scrollToVirtualIndex(index) { if (this.scrollableViewChild) { this.scrollableViewChild.scrollToVirtualIndex(index); } if (this.scrollableFrozenViewChild) { this.scrollableFrozenViewChild.scrollToVirtualIndex(index); } } scrollTo(options) { if (this.scrollableViewChild) { this.scrollableViewChild.scrollTo(options); } if (this.scrollableFrozenViewChild) { this.scrollableFrozenViewChild.scrollTo(options); } } isEmpty() { let data = this.filteredNodes || this.value; return data == null || data.length == 0; } getBlockableElement() { return this.el.nativeElement.children[0]; } onColumnResizeBegin(event) { let containerLeft = DomHandler.getOffset(this.containerViewChild.nativeElement).left; this.lastResizerHelperX = (event.pageX - containerLeft + this.containerViewChild.nativeElement.scrollLeft); event.preventDefault(); } onColumnResize(event) { let containerLeft = DomHandler.getOffset(this.containerViewChild.nativeElement).left; DomHandler.addClass(this.containerViewChild.nativeElement, 'p-unselectable-text'); this.resizeHelperViewChild.nativeElement.style.height = this.containerViewChild.nativeElement.offsetHeight + 'px'; this.resizeHelperViewChild.nativeElement.style.top = 0 + 'px'; this.resizeHelperViewChild.nativeElement.style.left = (event.pageX - containerLeft + this.containerViewChild.nativeElement.scrollLeft) + 'px'; this.resizeHelperViewChild.nativeElement.style.display = 'block'; } onColumnResizeEnd(event, column) { let delta = this.resizeHelperViewChild.nativeElement.offsetLeft - this.lastResizerHelperX; let columnWidth = column.offsetWidth; let newColumnWidth = columnWidth + delta; let minWidth = column.style.minWidth || 15; if (columnWidth + delta > parseInt(minWidth)) { if (this.columnResizeMode === 'fit') { let nextColumn = column.nextElementSibling; while (!nextColumn.offsetParent) { nextColumn = nextColumn.nextElementSibling; } if (nextColumn) { let nextColumnWidth = nextColumn.offsetWidth - delta; let nextColumnMinWidth = nextColumn.style.minWidth || 15; if (newColumnWidth > 15 && nextColumnWidth > parseInt(nextColumnMinWidth)) { if (this.scrollable) { let scrollableView = this.findParentScrollableView(column); let scrollableBodyTable = DomHandler.findSingle(scrollableView, '.p-treetable-scrollable-body table') || DomHandler.findSingle(scrollableView, '.p-treetable-virtual-scrollable-body table'); let scrollableHeaderTable = DomHandler.findSingle(scrollableView, 'table.p-treetable-scrollable-header-table'); let scrollableFooterTable = DomHandler.findSingle(scrollableView, 'table.p-treetable-scrollable-footer-table'); let resizeColumnIndex = DomHandler.index(column); this.resizeColGroup(scrollableHeaderTable, resizeColumnIndex, newColumnWidth, nextColumnWidth); this.resizeColGroup(scrollableBodyTable, resizeColumnIndex, newColumnWidth, nextColumnWidth); this.resizeColGroup(scrollableFooterTable, resizeColumnIndex, newColumnWidth, nextColumnWidth); } else { column.style.width = newColumnWidth + 'px'; if (nextColumn) { nextColumn.style.width = nextColumnWidth + 'px'; } } } } } else if (this.columnResizeMode === 'expand') { if (this.scrollable) { let scrollableView = this.findParentScrollableView(column); let scrollableBody = DomHandler.findSingle(scrollableView, '.p-treetable-scrollable-body') || DomHandler.findSingle(scrollableView, 'cdk-virtual-scroll-viewport'); let scrollableHeader = DomHandler.findSingle(scrollableView, '.p-treetable-scrollable-header'); let scrollableFooter = DomHandler.findSingle(scrollableView, '.p-treetable-scrollable-footer'); let scrollableBodyTable = DomHandler.findSingle(scrollableView, '.p-treetable-scrollable-body table') || DomHandler.findSingle(scrollableView, 'cdk-virtual-scroll-viewport table'); let scrollableHeaderTable = DomHandler.findSingle(scrollableView, 'table.p-treetable-scrollable-header-table'); let scrollableFooterTable = DomHandler.findSingle(scrollableView, 'table.p-treetable-scrollable-footer-table'); scrollableBodyTable.style.width = scrollableBodyTable.offsetWidth + delta + 'px'; scrollableHeaderTable.style.width = scrollableHeaderTable.offsetWidth + delta + 'px'; if (scrollableFooterTable) { scrollableFooterTable.style.width = scrollableFooterTable.offsetWidth + delta + 'px'; } let resizeColumnIndex = DomHandler.index(column); const scrollableBodyTableWidth = column ? scrollableBodyTable.offsetWidth + delta : newColumnWidth; const scrollableHeaderTableWidth = column ? scrollableHeaderTable.offsetWidth + delta : newColumnWidth; const isContainerInViewport = this.containerViewChild.nativeElement.offsetWidth >= scrollableBodyTableWidth; let setWidth = (container, table, width, isContainerInViewport) => { if (container && table) { container.style.width = isContainerInViewport ? width + DomHandler.calculateScrollbarWidth(scrollableBody) + 'px' : 'auto'; table.style.width = width + 'px'; } }; setWidth(scrollableBody, scrollableBodyTable, scrollableBodyTableWidth, isContainerInViewport); setWidth(scrollableHeader, scrollableHeaderTable, scrollableHeaderTableWidth, isContainerInViewport); setWidth(scrollableFooter, scrollableFooterTable, scrollableHeaderTableWidth, isContainerInViewport); this.resizeColGroup(scrollableHeaderTable, resizeColumnIndex, newColumnWidth, null); this.resizeColGroup(scrollableBodyTable, resizeColumnIndex, newColumnWidth, null); this.resizeColGroup(scrollableFooterTable, resizeColumnIndex, newColumnWidth, null); } else { this.tableViewChild.nativeElement.style.width = this.tableViewChild.nativeElement.offsetWidth + delta + 'px'; column.style.width = newColumnWidth + 'px'; let containerWidth = this.tableViewChild.nativeElement.style.width; this.containerViewChild.nativeElement.style.width = containerWidth + 'px'; } } this.onColResize.emit({ element: column, delta: delta }); } this.resizeHelperViewChild.nativeElement.style.display = 'none'; DomHandler.removeClass(this.containerViewChild.nativeElement, 'p-unselectable-text'); } findParentScrollableView(column) { if (column) { let parent = column.parentElement; while (parent && !DomHandler.hasClass(parent, 'p-treetable-scrollable-view')) { parent = parent.parentElement; } return parent; } else { return null; } } resizeColGroup(table, resizeColumnIndex, newColumnWidth, nextColumnWidth) { if (table) { let colGroup = table.children[0].nodeName === 'COLGROUP' ? table.children[0] : null; if (colGroup) { let col = colGroup.children[resizeColumnIndex]; let nextCol = col.nextElementSibling; col.style.width = newColumnWidth + 'px'; if (nextCol && nextColumnWidth) { nextCol.style.width = nextColumnWidth + 'px'; } } else { throw "Scrollable tables require a colgroup to support resizable columns"; } } } onColumnDragStart(event, columnElement) { this.reorderIconWidth = DomHandler.getHiddenElementOuterWidth(this.reorderIndicatorUpViewChild.nativeElement); this.reorderIconHeight = DomHandler.getHiddenElementOuterHeight(this.reorderIndicatorDownViewChild.nativeElement); this.draggedColumn = columnElement; event.dataTransfer.setData('text', 'b'); // For firefox } onColumnDragEnter(event, dropHeader) { if (this.reorderableColumns && this.draggedColumn && dropHeader) { event.preventDefault(); let containerOffset = DomHandler.getOffset(this.containerViewChild.nativeElement); let dropHeaderOffset = DomHandler.getOffset(dropHeader); if (this.draggedColumn != dropHeader) { let targetLeft = dropHeaderOffset.left - containerOffset.left; let targetTop = containerOffset.top - dropHeaderOffset.top; let columnCenter = dropHeaderOffset.left + dropHeader.offsetWidth / 2; this.reorderIndicatorUpViewChild.nativeElement.style.top = dropHeaderOffset.top - containerOffset.top - (this.reorderIconHeight - 1) + 'px'; this.reorderIndicatorDownViewChild.nativeElement.style.top = dropHeaderOffset.top - containerOffset.top + dropHeader.offsetHeight + 'px'; if (event.pageX > columnCenter) { this.reorderIndicatorUpViewChild.nativeElement.style.left = (targetLeft + dropHeader.offsetWidth - Math.ceil(this.reorderIconWidth / 2)) + 'px'; this.reorderIndicatorDownViewChild.nativeElement.style.left = (targetLeft + dropHeader.offsetWidth - Math.ceil(this.reorderIconWidth / 2)) + 'px'; this.dropPosition = 1; } else { this.reorderIndicatorUpViewChild.nativeElement.style.left = (targetLeft - Math.ceil(this.reorderIconWidth / 2)) + 'px'; this.reorderIndicatorDownViewChild.nativeElement.style.left = (targetLeft - Math.ceil(this.reorderIconWidth / 2)) + 'px'; this.dropPosition = -1; } this.reorderIndicatorUpViewChild.nativeElement.style.display = 'block'; this.reorderIndicatorDownViewChild.nativeElement.style.display = 'block'; } else { event.dataTransfer.dropEffect = 'none'; } } } onColumnDragLeave(event) { if (this.reorderableColumns && this.draggedColumn) { event.preventDefault(); this.reorderIndicatorUpViewChild.nativeElement.style.display = 'none'; this.reorderIndicatorDownViewChild.nativeElement.style.display = 'none'; } } onColumnDrop(event, dropColumn) { event.preventDefault(); if (this.draggedColumn) { let dragIndex = DomHandler.indexWithinGroup(this.draggedColumn, 'ttreorderablecolumn'); let dropIndex = DomHandler.indexWithinGroup(dropColumn, 'ttreorderablecolumn'); let allowDrop = (dragIndex != dropIndex); if (allowDrop && ((dropIndex - dragIndex == 1 && this.dropPosition === -1) || (dragIndex - dropIndex == 1 && this.dropPosition === 1))) { allowDrop = false; } if (allowDrop && ((dropIndex < dragIndex && this.dropPosition === 1))) { dropIndex = dropIndex + 1; } if (allowDrop && ((dropIndex > dragIndex && this.dropPosition === -1))) { dropIndex = dropIndex - 1; } if (allowDrop) { ObjectUtils.reorderArray(this.columns, dragIndex, dropIndex); this.onColReorder.emit({ dragIndex: dragIndex, dropIndex: dropIndex, columns: this.columns }); } this.reorderIndicatorUpViewChild.nativeElement.style.display = 'none'; this.reorderIndicatorDownViewChild.nativeElement.style.display = 'none'; this.draggedColumn.draggable = false; this.draggedColumn = null; this.dropPosition = null; } } handleRowClick(event) { let targetNode = event.originalEvent.target.nodeName; if (targetNode == 'INPUT' || targetNode == 'BUTTON' || targetNode == 'A' || (DomHandler.hasClass(event.originalEvent.target, 'p-clickable'))) { return; } if (this.selectionMode) { this.preventSelectionSetterPropagation = true; let rowNode = event.rowNode; let selected = this.isSelected(rowNode.node); let metaSelection = this.rowTouched ? false : this.metaKeySelection; let dataKeyValue = this.dataKey ? String(ObjectUtils.resolveFieldData(rowNode.node.data, this.dataKey)) : null; if (metaSelection) { let metaKey = event.originalEvent.metaKey || event.originalEvent.ctrlKey; if (selected && metaKey) { if (this.isSingleSelectionMode()) { this._selection = null; this.selectionKeys = {}; this.selectionChange.emit(null); } else { let selectionIndex = this.findIndexInSelection(rowNode.node); this._selection = this.selection.filter((val, i) => i != selectionIndex); this.selectionChange.emit(this.selection); if (dataKeyValue) { delete this.selectionKeys[dataKeyValue]; } } this.onNodeUnselect.emit({ originalEvent: event.originalEvent, node: rowNode.node, type: 'row' }); } else { if (this.isSingleSelectionMode()) { this._selection = rowNode.node; this.selectionChange.emit(rowNode.node); if (dataKeyValue) { this.selectionKeys = {}; this.selectionKeys[dataKeyValue] = 1; } } else if (this.isMultipleSelectionMode()) { if (metaKey) { this._selection = this.selection || []; } else { this._selection = []; this.selectionKeys = {}; } this._selection = [...this.selection, rowNode.node]; this.selectionChange.emit(this.selection); if (dataKeyValue) { this.selectionKeys[dataKeyValue] = 1; } } this.onNodeSelect.emit({ originalEvent: event.originalEvent, node: rowNode.node, type: 'row', index: event.rowIndex }); } } else { if (this.selectionMode === 'single') { if (selected) { this._selection = null; this.selectionKeys = {}; this.selectionChange.emit(this.selection); this.onNodeUnselect.emit({ originalEvent: event.originalEvent, node: rowNode.node, type: 'row' }); } else { this._selection = rowNode.node; this.selectionChange.emit(this.selection); this.onNodeSelect.emit({ originalEvent: event.originalEvent, node: rowNode.node, type: 'row', index: event.rowIndex }); if (dataKeyValue) { this.selectionKeys = {}; this.selectionKeys[dataKeyValue] = 1; } } } else if (this.selectionMode === 'multiple') { if (selected) { let selectionIndex = this.findIndexInSelection(rowNode.node); this._selection = this.selection.filter((val, i) => i != selectionIndex); this.selectionChange.emit(this.selection); this.onNodeUnselect.emit({ originalEvent: event.originalEvent, node: rowNode.node, type: 'row' }); if (dataKeyValue) { delete this.selectionKeys[dataKeyValue]; } } else { this._selection = this.selection ? [...this.selection, rowNode.node] : [rowNode.node]; this.selectionChange.emit(this.selection); this.onNodeSelect.emit({ originalEvent: event.originalEvent, node: rowNode.node, type: 'row', index: event.rowIndex }); if (dataKeyValue) { this.selectionKeys[dataKeyValue] = 1; } } } } this.tableService.onSelectionChange(); } this.rowTouched = false; } handleRowTouchEnd(event) { this.rowTouched = true; } handleRowRightClick(event) { if (this.contextMenu) { const node = event.rowNode.node; if (this.contextMenuSelectionMode === 'separate') { this.contextMenuSelection = node; this.contextMenuSelectionChange.emit(node); this.onContextMenuSelect.emit({ originalEvent: event.originalEvent, node: node }); this.contextMenu.show(event.originalEvent); this.tableService.onContextMenu(node); } else if (this.contextMenuSelectionMode === 'joint') { this.preventSelectionSetterPropagation = true; let selected = this.isSelected(node); let dataKeyValue = this.dataKey ? String(ObjectUtils.resolveFieldData(node.data, this.dataKey)) : null; if (!selected) { if (this.isSingleSelectionMode()) { this.selection = node; this.selectionChange.emit(node); } else if (this.isMultipleSelectionMode()) { this.selection = [node]; this.selectionChange.emit(this.selection); } if (dataKeyValue) { this.selectionKeys[dataKeyValue] = 1; } } this.contextMenu.show(event.originalEvent); this.onContextMenuSelect.emit({ originalEvent: event.originalEvent, node: node }); } } } toggleNodeWithCheckbox(event) { this.selection = this.selection || []; this.preventSelectionSetterPropagation = true; let node = event.rowNode.node; let selected = this.isSelected(node); if (selected) { this.propagateSelectionDown(node, false); if (event.rowNode.parent) { this.propagateSelectionUp(node.parent, false); } this.selectionChange.emit(this.selection); this.onNodeUnselect.emit({ originalEvent: event, node: node }); } else { this.propagateSelectionDown(node, true); if (event.rowNode.parent) { this.propagateSelectionUp(node.parent, true); } this.selectionChange.emit(this.selection); this.onNodeSelect.emit({ originalEvent: event, node: node }); } this.tableService.onSelectionChange(); } toggleNodesWithCheckbox(event, check) { let data = this.filteredNodes || this.value; this._selection = check && data ? data.slice() : []; if (check) { if (data && data.length) { for (let node of data) { this.propagateSelectionDown(node, true); } } } else { this._selection = []; this.selectionKeys = {}; } this.preventSelectionSetterPropagation = true; this.selectionChange.emit(this._selection); this.tableService.onSelectionChange(); this.onHeaderCheckboxToggle.emit({ originalEvent: event, checked: check }); } propagateSelectionUp(node, select) { if (node.children && node.children.length) { let selectedChildCount = 0; let childPartialSelected = false; let dataKeyValue = this.dataKey ? String(ObjectUtils.resolveFieldData(node.data, this.dataKey)) : null; for (let child of node.children) { if (this.isSelected(child)) selectedChildCount++; else if (child.partialSelected) childPartialSelected = true; } if (select && selectedChildCount == node.children.length) { this._selection = [...this.selection || [], node]; node.partialSelected = false; if (dataKeyValue) { this.selectionKeys[dataKeyValue] = 1; } } else { if (!select) { let index = this.findIndexInSelection(node); if (index >= 0) { this._selection = this.selection.filter((val, i) => i != index); if (dataKeyValue) { delete this.selectionKeys[dataKeyValue]; } } } if (childPartialSelected || selectedChildCount > 0 && selectedChildCount != node.children.length) node.partialSelected = true; else node.partialSelected = false; } } let parent = node.parent; if (parent) { this.propagateSelectionUp(parent, select); } } propagateSelectionDown(node, select) { let index = this.findIndexInSelection(node); let dataKeyValue = this.dataKey ? String(ObjectUtils.resolveFieldData(node.data, this.dataKey)) : null; if (select && index == -1) { this._selection = [...this.selection || [], node]; if (dataKeyValue) { this.selectionKeys[dataKeyValue] = 1; } } else if (!select && index > -1) { this._selection = this.selection.filter((val, i) => i != index); if (dataKeyValue) { delete this.selectionKeys[dataKeyValue]; } } node.partialSelected = false; if (node.children && node.children.length) { for (let child of node.children) { this.propagateSelectionDown(child, select); } } } isSelected(node) { if (node && this.selection) { if (this.dataKey) { return this.selectionKeys[ObjectUtils.resolveFieldData(node.data, this.dataKey)] !== undefined; } else { if (this.selection instanceof Array) return this.findIndexInSelection(node) > -1; else return this.equals(node, this.selection); } } return false; } findIndexInSelection(node) { let index = -1; if (this.selection && this.selection.length) { for (let i = 0; i < this.selection.length; i++) { if (this.equals(node, this.selection[i])) { index = i; break; } } } return index; } isSingleSelectionMode() { return this.selectionMode === 'single'; } isMultipleSelectionMode() { return this.selectionMode === 'multiple'; } equals(node1, node2) { return this.compareSelectionBy === 'equals' ? (node1 === node2) : ObjectUtils.equals(node1.data, node2.data, this.dataKey); } filter(value, field, matchMode) { if (this.filterTimeout) { clearTimeout(this.filterTimeout); } if (!this.isFilterBlank(value)) { this.filters[field] = { value: value, matchMode: matchMode }; } else if (this.filters[field]) { delete this.filters[field]; } this.filterTimeout = setTimeout(() => { this._filter(); this.filterTimeout = null; }, this.filterDelay); } filterGlobal(value, matchMode) { this.filter(value, 'global', matchMode); } isFilterBlank(filter) { if (filter !== null && filter !== undefined) { if ((typeof filter === 'string' && filter.trim().length == 0) || (filter instanceof Array && filter.length == 0)) return true; else return false; } return true; } _filter() { if (this.lazy) { this.onLazyLoad.emit(this.createLazyLoadMetadata()); } else { if (!this.value) { return; } if (!this.hasFilter()) { this.filteredNodes = null; if (this.paginator) { this.totalRecords = this.value ? this.value.length : 0; } } else { let globalFilterFieldsArray; if (this.filters['global']) { if (!this.columns && !this.globalFilterFields) throw new Error('Global filtering requires dynamic columns or globalFilterFields to be defined.'); else globalFilterFieldsArray = this.globalFilterFields || this.columns; } this.filteredNodes = []; const isStrictMode = this.filterMode === 'strict'; let isValueChanged = false; for (let node of this.value) { let copyNode = Object.assign({}, node); let localMatch = true; let globalMatch = false; let paramsWithoutNode; for (let prop in this.filters) { if (this.filters.hasOwnProperty(prop) && prop !== 'global') { let filterMeta = this.filters[prop]; let filterField = prop; let filterValue = filterMeta.value; let filterMatchMode = filterMeta.matchMode || 'startsWith'; let filterConstraint = this.filterService.filters[filterMatchMode]; paramsWithoutNode = { filterField, filterValue, filterConstraint, isStrictMode }; if ((isStrictMode && !(this.findFilteredNodes(copyNode, paramsWithoutNode) || this.isFilterMatched(copyNode, paramsWithoutNode))) || (!isStrictMode && !(this.isFilterMatched(copyNode, paramsWithoutNode) || this.findFilteredNodes(copyNode, paramsWithoutNode)))) { localMatch = false; } if (!localMatch) { break; } } } if (this.filters['global'] && !globalMatch && globalFilterFieldsArray) { for (let j = 0; j < globalFilterFieldsArray.length; j++) { let copyNodeForGlobal = Object.assign({}, copyNode); let filterField = globalFilterFieldsArray[j].field || globalFilterFieldsArray[j]; let filterValue = this.filters['global'].value; let filterConstraint = this.filterService.filters[this.filters['global'].matchMode]; paramsWithoutNode = { filterField, filterValue, filterConstraint, isStrictMode }; if ((isStrictMode && (this.findFilteredNodes(copyNodeForGlobal, paramsWithoutNode) || this.isFilterMatched(copyNodeForGlobal, paramsWithoutNode))) || (!isStrictMode && (this.isFilterMatched(copyNodeForGlobal, paramsWithoutNode) || this.findFilteredNodes(copyNodeForGlobal, paramsWithoutNode)))) { globalMatch = true; copyNode = copyNodeForGlobal; } } } let matches = localMatch; if (this.filters['global']) { matches = localMatch && globalMatch; } if (matches) { this.filteredNodes.push(copyNode); } isValueChanged = isValueChanged || !localMatch || globalMatch || (localMatch && this.filteredNodes.length > 0) || (!globalMatch && this.filteredNodes.length === 0); } if (!isValueChanged) { this.filteredNodes = null; } if (this.paginator) { this.totalRecords = this.filteredNodes ? this.filteredNodes.length : this.value ? this.value.length : 0; } } } this.first = 0; const filteredValue = this.filteredNodes || this.value; this.onFilter.emit({ filters: this.filters, filteredValue: filteredValue }); this.tableService.onUIUpdate(filteredValue); this.updateSerializedValue(); if (this.scrollable) { this.resetScrollTop(); } } findFilteredNodes(node, paramsWithoutNode) { if (node) { let matched = false; if (node.children) { let childNodes = [...node.children]; node.children = []; for (let childNode of childNodes)