Multi-Page Content

The Drawing library enables you to generate multi-page content in PDF, prevent the page-split, and render page templates.

For more information on how to render multi-page content with the PDF Export component, refer to its documentation.

Rendering Multi-Page Content

To render a multi-page PDF file, set multiPage: true to the Group object that you pass to exportPDF (master group). As a result, the group contains only Group shapes—one shape for each page (page groups). If the page group does not override the PDF options that you pass to the master group, the PDF options are applied to each page group.

The available options that can be overwritten are:

If the paperSize option for the master group is set to "auto" and the page groups do not override it, the paper size for each individual page is determined by its corresponding group. This means that the pages of the final document might be of different sizes.

Manual Page Breaking

To manually specify the page breaks, use the drawDOM method which allows you to create multi-page PDF content. As a result, a page break, which matches the forcePageBreak CSS selector, occurs before each element.

import { Component } from '@angular/core';
import { exportElement } from './export-element';

@Component({
  selector: 'my-app',
  template: `
    <button (click)="onClick(drawMe)">Export PDF...</button>
    <div #drawMe>
        <h3>Page 1</h3>
        <h3 class='page-break'>Page 2</h3>
    </div>
  `
})
export class AppComponent {
  public onClick(element) {
    exportElement(element, {
        forcePageBreak: '.page-break'
    });
  }
}

import { drawDOM, exportPDF, DrawOptions, Group } from '@progress/kendo-drawing';
import { saveAs } from '@progress/kendo-file-saver';

export function exportElement(element: HTMLElement, options?: DrawOptions) {
    drawDOM(element, options).then((group: Group) => {
        return exportPDF(group);
    }).then((dataUri) => {
        saveAs(dataUri, 'export.pdf');
    });
}

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';

@NgModule({
  imports:      [ BrowserModule ],
  declarations: [ AppComponent ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';

enableProdMode();
platformBrowserDynamic().bootstrapModule(AppModule);

Automatic Page Breaking

The drawDOM method supports automatic page breaking. To automatically implement the page breaks, set the paperSize and margin options. You will still be able to apply the forcePageBreak configuration to manually specify the break points.

For more information, refer to the known limitations of the Drawing library and the PDF Export component.

import { Component } from '@angular/core';
import { exportElement } from './export-element';

@Component({
  selector: 'my-app',
  template: `
    <button (click)="onClick(drawMe)">Export PDF...</button>
    <div #drawMe>
        <p>
            Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer felis libero, lobortis ac rutrum quis, varius a velit. Donec lacus erat, cursus sed porta quis, adipiscing et ligula. Duis volutpat, sem pharetra accumsan pharetra, mi ligula cursus felis, ac aliquet leo diam eget risus. Integer facilisis, justo cursus venenatis vehicula, massa nisl tempor sem, in ullamcorper neque mauris in orci.
        </p>
        <p>
            Ut orci ligula, varius ac consequat in, rhoncus in dolor. Mauris pulvinar molestie accumsan. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Aenean velit ligula, pharetra quis aliquam sed, scelerisque sed sapien. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Aliquam dui mi, vulputate vitae pulvinar ac, condimentum sed eros.
        </p>
        <p>
            Aliquam at nisl quis est adipiscing bibendum. Nam malesuada eros facilisis arcu vulputate at aliquam nunc tempor. In commodo scelerisque enim, eget sodales lorem condimentum rutrum. Phasellus sem metus, ultricies at commodo in, tristique non est. Morbi vel mauris eget mauris commodo elementum. Nam eget libero lacus, ut sollicitudin ante. Nam odio quam, suscipit a fringilla eget, dignissim nec arcu. Donec tristique arcu ut sapien elementum pellentesque.
        </p>
        <p>
            Maecenas vitae eros vel enim molestie cursus. Proin ut lacinia ipsum. Nam at elit arcu, at porttitor ipsum. Praesent id viverra lorem. Nam lacinia elementum fermentum. Nulla facilisi. Nulla bibendum erat sed sem interdum suscipit. Vestibulum eget molestie leo. Aliquam erat volutpat. Ut sed nulla libero. Suspendisse id euismod quam. Aliquam interdum turpis vitae purus consectetur in pulvinar libero accumsan. In id augue dui, ac volutpat ante. Suspendisse purus est, ullamcorper id bibendum sed, placerat id leo.
        </p>
    </div>
  `,
  styles: [`
    p {
        font-size: 20px;
    }
  `]
})
export class AppComponent {
  public onClick(element) {
    exportElement(element, {
        paperSize: "A4",
        margin: "2cm"
    });
  }
}

import { drawDOM, exportPDF, DrawOptions, Group } from '@progress/kendo-drawing';
import { saveAs } from '@progress/kendo-file-saver';

export function exportElement(element: HTMLElement, options?: DrawOptions) {
    drawDOM(element, options).then((group: Group) => {
        return exportPDF(group);
    }).then((dataUri) => {
        saveAs(dataUri, 'export.pdf');
    });
}

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';

@NgModule({
  imports:      [ BrowserModule ],
  declarations: [ AppComponent ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';

enableProdMode();
platformBrowserDynamic().bootstrapModule(AppModule);

Page Templates

When you request multi-page output through the forcePageBreak or paperSize options, you can additionally specify a page template. The page template is inserted into each page before the output is produced and you can position it relatively to the page by using CSS. The template has to be a function which receives the number of the current page (pageNum) and the total number of pages (totalPages).

import { Component } from '@angular/core';
import { exportElement } from './export-element';

@Component({
  selector: 'my-app',
  template: `
    <button (click)="onClick(drawMe)">Export PDF...</button>
    <div #drawMe>
        <h3>Page 1</h3>
        <h3 class='page-break'>Page 2</h3>
    </div>
  `
})
export class AppComponent {
  public onClick(element) {
    exportElement(element, {
        forcePageBreak: '.page-break',
        template: (data) => `<span>Page ${ data.pageNum } of ${ data.totalPages }</span>`
    });
  }
}

import { drawDOM, exportPDF, DrawOptions, Group } from '@progress/kendo-drawing';
import { saveAs } from '@progress/kendo-file-saver';

export function exportElement(element: HTMLElement, options?: DrawOptions) {
    drawDOM(element, options).then((group: Group) => {
        return exportPDF(group);
    }).then((dataUri) => {
        saveAs(dataUri, 'export.pdf');
    });
}

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';

@NgModule({
  imports:      [ BrowserModule ],
  declarations: [ AppComponent ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';

enableProdMode();
platformBrowserDynamic().bootstrapModule(AppModule);

Preventing Page Breaking in Elements

To prevent specific elements from being split across pages, use the keepTogether option. keepTogether accepts CSS selectors that are passable to querySelector.

All elements from the following example which have the "prevent-split" CSS class are kept within the boundaries of the pages and their content is not split. If they fall on a margin, they will be moved to the next page.

import { Component } from '@angular/core';
import { exportElement } from './export-element';

@Component({
  selector: 'my-app',
  template: `
    <button (click)="onClick(drawMe)">Export PDF...</button>
    <div #drawMe>
        <p>
            Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer felis libero, lobortis ac rutrum quis, varius a velit. Donec lacus erat, cursus sed porta quis, adipiscing et ligula. Duis volutpat, sem pharetra accumsan pharetra, mi ligula cursus felis, ac aliquet leo diam eget risus. Integer facilisis, justo cursus venenatis vehicula, massa nisl tempor sem, in ullamcorper neque mauris in orci.
        </p>
        <p>
            Ut orci ligula, varius ac consequat in, rhoncus in dolor. Mauris pulvinar molestie accumsan. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Aenean velit ligula, pharetra quis aliquam sed, scelerisque sed sapien. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Aliquam dui mi, vulputate vitae pulvinar ac, condimentum sed eros.
        </p>
        <p>
            Aliquam at nisl quis est adipiscing bibendum. Nam malesuada eros facilisis arcu vulputate at aliquam nunc tempor. In commodo scelerisque enim, eget sodales lorem condimentum rutrum. Phasellus sem metus, ultricies at commodo in, tristique non est. Morbi vel mauris eget mauris commodo elementum. Nam eget libero lacus, ut sollicitudin ante. Nam odio quam, suscipit a fringilla eget, dignissim nec arcu. Donec tristique arcu ut sapien elementum pellentesque.
        </p>
        <p>
            Maecenas vitae eros vel enim molestie cursus. Proin ut lacinia ipsum. Nam at elit arcu, at porttitor ipsum. Praesent id viverra lorem. Nam lacinia elementum fermentum. Nulla facilisi. Nulla bibendum erat sed sem interdum suscipit. Vestibulum eget molestie leo. Aliquam erat volutpat. Ut sed nulla libero. Suspendisse id euismod quam. Aliquam interdum turpis vitae purus consectetur in pulvinar libero accumsan. In id augue dui, ac volutpat ante. Suspendisse purus est, ullamcorper id bibendum sed, placerat id leo.
        </p>
    </div>
  `,
  styles: [`
    p {
        font-size: 20px;
    }
  `]
})
export class AppComponent {
  public onClick(element) {
    exportElement(element, {
        paperSize: "A4",
        margin: "2cm",
        keepTogether: 'p'
    });
  }
}

import { drawDOM, exportPDF, DrawOptions, Group } from '@progress/kendo-drawing';
import { saveAs } from '@progress/kendo-file-saver';

export function exportElement(element: HTMLElement, options?: DrawOptions) {
    drawDOM(element, options).then((group: Group) => {
        return exportPDF(group);
    }).then((dataUri) => {
        saveAs(dataUri, 'export.pdf');
    });
}

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';

@NgModule({
  imports:      [ BrowserModule ],
  declarations: [ AppComponent ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';

enableProdMode();
platformBrowserDynamic().bootstrapModule(AppModule);

In this article