@progress/kendo-angular-treelist
Version:
Kendo UI TreeList for Angular - Display hierarchical data in an Angular tree grid view that supports sorting, filtering, paging, and much more.
265 lines (264 loc) • 10.6 kB
JavaScript
/**-----------------------------------------------------------------------------------------
* Copyright © 2025 Progress Software Corporation. All rights reserved.
* Licensed under commercial license. See LICENSE.md in the project root for more information
*-------------------------------------------------------------------------------------------*/
import { Component, Input, ContentChild, ContentChildren, ElementRef, NgZone, QueryList } from '@angular/core';
import { take } from 'rxjs/operators';
import { SuspendService } from '../scrolling/suspend.service';
import { PDFService } from './pdf.service';
import { PDFMarginComponent } from './pdf-margin.component';
import { PDFTemplateDirective } from './pdf-template.directive';
import { exportElement, cloneNode } from './export-element';
import { TreeListQuery } from './treelist-query';
import { ColumnBase } from '../columns/column-base';
import { PDFExportComponent } from '@progress/kendo-angular-pdf-export';
import { isDocumentAvailable } from '@progress/kendo-angular-common';
import * as i0 from "@angular/core";
import * as i1 from "./pdf.service";
import * as i2 from "../scrolling/suspend.service";
const createElement = (tagName, className) => {
if (!isDocumentAvailable()) {
return;
}
const element = document.createElement(tagName);
if (className) {
element.className = className;
}
return element;
};
const createDiv = (className) => {
return createElement('div', className);
};
/**
* Configures the settings for exporting TreeList to PDF ([see example]({% slug pdfexport_treelist %})).
*
* @example
* ```html
* <kendo-treelist>
* <kendo-treelist-pdf [allPages]="true" [fileName]="'export.pdf'"></kendo-treelist-pdf>
* </kendo-treelist>
* ```
*
* @remarks
* Supported children components are: {@link PDFMarginComponent}.
*/
export class PDFComponent extends PDFExportComponent {
pdfService;
suspendService;
ngZone;
/**
* Specifies if the export includes all TreeList pages, starting from the first one.
*/
allPages;
columns = new QueryList();
marginComponent;
pageTemplateDirective;
progress;
component;
container;
skip;
pageSize;
originalHeight;
originalOverflow;
saveSubscription;
drawSubscription;
renderAllPages;
originalColumns;
constructor(pdfService, suspendService, ngZone, element) {
super(element);
this.pdfService = pdfService;
this.suspendService = suspendService;
this.ngZone = ngZone;
this.saveSubscription = pdfService.savePDF.subscribe(this.savePDF.bind(this));
this.drawSubscription = pdfService.drawPDF.subscribe(this.drawPDF.bind(this));
this.reset = this.reset.bind(this);
this.draw = this.draw.bind(this);
}
ngOnDestroy() {
this.saveSubscription.unsubscribe();
this.drawSubscription.unsubscribe();
this.reset();
}
savePDF(component) {
this.createPDF(component, this.draw);
}
drawPDF({ component, promise }) {
this.createPDF(component, () => {
this.createExportGroup(promise);
});
}
createPDF(component, callback) {
const pageSize = component.pageSize;
const total = component.view.totalVisible;
const columns = this.columns.toArray();
if (columns.length) {
this.originalColumns = component.columns.toArray();
}
this.component = component;
this.suspendService.scroll = true;
this.pdfService.exporting = true;
this.initProgress();
this.renderAllPages = this.allPages && pageSize < total;
if (this.renderAllPages) {
this.skip = component.skip;
this.pageSize = pageSize;
this.changePage(0, total, callback, columns);
}
else if (columns.length || component.virtualColumns) {
this.changeColumns(columns, callback);
}
else {
callback();
}
}
initProgress() {
const wrapperElement = this.component.wrapper.nativeElement;
const progress = this.progress = createDiv('k-loading-pdf-mask');
const overlay = cloneNode(wrapperElement);
progress.appendChild(overlay);
progress.appendChild(createDiv('k-loading-color'));
progress.appendChild(createElement('span', 'k-i-loading k-icon'));
this.originalHeight = wrapperElement.style.height;
this.originalOverflow = wrapperElement.style.overflow;
wrapperElement.style.height = wrapperElement.offsetHeight + 'px';
wrapperElement.style.overflow = 'hidden';
wrapperElement.appendChild(progress);
this.applyScroll(overlay);
}
applyScroll(overlay) {
const query = new TreeListQuery(this.component.wrapper.nativeElement);
const content = query.content();
if (content) {
const overlayQuery = new TreeListQuery(overlay);
const overlayContent = overlayQuery.content();
overlayContent.scrollTop = content.scrollTop;
overlayContent.scrollLeft = content.scrollLeft;
overlayQuery.header().scrollLeft = query.header().scrollLeft;
const footer = query.footer();
if (footer) {
overlayQuery.footer().scrollLeft = footer.scrollLeft;
}
const lockedContent = query.content(true);
if (lockedContent) {
const overlayLockedContent = overlayQuery.content(true);
overlayLockedContent.scrollTop = lockedContent.scrollTop;
overlayLockedContent.scrollLeft = lockedContent.scrollLeft;
}
}
}
draw() {
this.createExportElement((element) => {
this.save(element, this.fileName);
});
}
createExportGroup(promise) {
this.createExportElement((element) => {
this.exportElement(element).then(group => promise.resolve(group));
});
}
createExportElement(callback) {
this.ngZone.runOutsideAngular(() => {
const container = this.container = createDiv('k-grid-pdf-export-element');
const element = exportElement(this.component.wrapper.nativeElement);
container.appendChild(element);
document.body.appendChild(container);
callback(element);
});
}
drawOptions() {
const options = super.drawOptions();
options._destructive = true;
return options;
}
cleanup() {
super.cleanup();
this.pdfService.exporting = false;
if (this.component) {
const originalColumns = this.originalColumns;
delete this.originalColumns;
if (this.renderAllPages) {
this.changePage(this.skip, this.pageSize, this.reset, originalColumns);
}
else if (originalColumns || this.component.virtualColumns) {
this.changeColumns(originalColumns, this.reset);
}
else {
this.reset();
}
}
else {
this.reset();
}
this.removeContainer();
}
removeContainer() {
if (this.container) {
document.body.removeChild(this.container);
delete this.container;
}
}
changePage(skip, _take, callback, columns) {
this.ngZone.run(() => {
const onPageChanged = () => {
if ((columns && columns.length) || this.component.virtualColumns) {
this.changeColumns(columns, callback);
}
else {
this.onStable(callback);
}
};
this.component.notifyPageChange('pdf', { skip: skip, take: _take });
if (this.component.view.loading) {
this.component.view.dataLoaded.pipe(take(1)).subscribe(onPageChanged);
}
else {
onPageChanged();
}
});
}
changeColumns(columns, callback) {
this.ngZone.run(() => {
this.onStable(callback);
if (columns && columns.length) {
this.component.columns.reset(columns);
}
});
}
reset() {
this.suspendService.scroll = false;
this.renderAllPages = false;
if (!this.component) {
return;
}
const wrapperElement = this.component.wrapper.nativeElement;
wrapperElement.removeChild(this.progress);
wrapperElement.style.height = this.originalHeight;
wrapperElement.style.overflow = this.originalOverflow;
delete this.progress;
delete this.component;
}
onStable(callback) {
this.ngZone.onStable.asObservable().pipe(take(1)).subscribe(callback);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PDFComponent, deps: [{ token: i1.PDFService }, { token: i2.SuspendService }, { token: i0.NgZone }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: PDFComponent, isStandalone: true, selector: "kendo-treelist-pdf", inputs: { allPages: "allPages" }, queries: [{ propertyName: "marginComponent", first: true, predicate: PDFMarginComponent, descendants: true }, { propertyName: "pageTemplateDirective", first: true, predicate: PDFTemplateDirective, descendants: true }, { propertyName: "columns", predicate: ColumnBase }], usesInheritance: true, ngImport: i0, template: '', isInline: true });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PDFComponent, decorators: [{
type: Component,
args: [{
selector: 'kendo-treelist-pdf',
template: '',
standalone: true
}]
}], ctorParameters: function () { return [{ type: i1.PDFService }, { type: i2.SuspendService }, { type: i0.NgZone }, { type: i0.ElementRef }]; }, propDecorators: { allPages: [{
type: Input
}], columns: [{
type: ContentChildren,
args: [ColumnBase]
}], marginComponent: [{
type: ContentChild,
args: [PDFMarginComponent, { static: false }]
}], pageTemplateDirective: [{
type: ContentChild,
args: [PDFTemplateDirective, { static: false }]
}] } });