@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 }]
            }] } });