Export PDF using PDFMake in Angular

In this article, we saw how to export, open & print PDF in angular using PDFMake. In a few days ago we discuss on export pdf using jsPDF. Let’s create a new application then we need to install “PDFMake”. We take an example to generate an online Resume PDF.
Full Demo Online Resume Builder


ng new pdf-generate

“pdf-generate” you need to write your application’s name. Then it will take some time to create the project. After successfully installing that, you need to go to their directory. For example “cd pdf-generate”. To Run angular applications, it required to run “ng serve”.


After we need to install “PDFMake”


npm install --save pdfmake

After install module. In Angular component or service add below import statement


import pdfMake from 'pdfmake/build/pdfmake';
import pdfFonts from 'pdfmake/build/vfs_fonts';
pdfMake.vfs = pdfFonts.pdfMake.vfs;

PDF formatting and design configuration are written in document-definition-object.


generatePdf(){
  const documentDefinition = { content: 'PDF Content To draw' };
  pdfmake.createPdf(documentDefinition).open();
 }

PDFMake Conatains below methods.

Method Description
Download pdfMake.createPdf(docDefinition).download();
Download the PDF
Open PDF pdfMake.createPdf(docDefinition).open();
Open the PDF in new window
Open PDF Same Window pdfMake.createPdf(docDefinition).open({}, window);
Open the PDF in new window
Print PDF pdfMake.createPdf(docDefinition).print();
Print the PDF

Let’s create app.component.ts for the resume building online. display in the below code.


import { Component, VERSION } from '@angular/core';
import pdfMake from 'pdfmake/build/pdfmake';
import pdfFonts from 'pdfmake/build/vfs_fonts';


export class Resume {
    name: string;
    address: string;
    contactNo: number;
    email: string;
    skills: Skill[] = [];

     constructor() {
       this.skills.push(new Skill());
    }
}
//skill export
export class Skill {
    value: string;
}
@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  name = 'Angular ' + VERSION.major;

   resume = new Resume();


   constructor() {

     pdfMake.vfs = pdfFonts.pdfMake.vfs;

     this.resume = JSON.parse(sessionStorage.getItem('resume')) || new Resume();

    //skills
    if (!this.resume.skills || this.resume.skills.length === 0) {
      this.resume.skills = [];
      this.resume.skills.push(new Skill());
    }

   }

   generatePdf(action = 'open') {
    console.log(pdfMake);
    const documentDefinition = this.getDocumentDefinition();

    switch (action) {
      case 'open': pdfMake.createPdf(documentDefinition).open(); break;
      case 'print': pdfMake.createPdf(documentDefinition).print(); break;
      case 'download': pdfMake.createPdf(documentDefinition).download(); break;

      default: pdfMake.createPdf(documentDefinition).open(); break;
    }

  }

  addSkill() {
    this.resume.skills.push(new Skill());
  }

   resetForm() {
    this.resume = new Resume();
  }

  getDocumentDefinition() {
    sessionStorage.setItem('resume', JSON.stringify(this.resume));
    return {
      content: [
        {
          text: 'RESUME',
          bold: true,
          fontSize: 20,
          alignment: 'center',
          margin: [0, 0, 0, 20]
        },
        {
          columns: [
            [{
              text: this.resume.name,
              style: 'name'
            },
            {
              text: this.resume.address
            },
            {
              text: 'Email : ' + this.resume.email,
            },
            {
              text: 'Contant No : ' + this.resume.contactNo,
            }
            ]
          ]
        },
        {
          text: 'Skills',
          style: 'header'
        },
        {
          columns : [
            {
              ul : [
                ...this.resume.skills.filter((value, index) => index % 3 === 0).map(s => s.value)
              ]
            },
            {
              ul : [
                ...this.resume.skills.filter((value, index) => index % 3 === 1).map(s => s.value)
              ]
            },
            {
              ul : [
                ...this.resume.skills.filter((value, index) => index % 3 === 2).map(s => s.value)
              ]
            }
          ]
        }
      ],
      info: {
        title: this.resume.name + '_RESUME',
        author: this.resume.name,
        subject: 'RESUME',
        keywords: 'RESUME, ONLINE RESUME',
      },
        styles: {
          header: {
            fontSize: 18,
            bold: true,
            margin: [0, 20, 0, 10],
            decoration: 'underline'
          },
          name: {
            fontSize: 16,
            bold: true
          },
          jobTitle: {
            fontSize: 14,
            bold: true,
            italics: true
          },
          sign: {
            margin: [0, 50, 0, 10],
            alignment: 'right',
            italics: true
          },
          tableHeader: {
            bold: true,
          }
        }
    };
  }

}


<nav class="navbar navbar-expand navbar-light bg-secondary d-flex justify-content-between">
  <div class="navbar-brand mb-0 h1 text-white">ONLINE RESUME</div>
 
</nav>
<br>
<div class="container-fluid">
  <form #resumeForm="ngForm">
    <div class="row">
      <div class="col-md-8">

        <div class="shadow-sm card">
          <div class="card-body">
            <h4 class="card-title d-flex align-items-center">
              <i class="material-icons">
                account_box
              </i>
              Personal Details</h4>
            <div class="row">
              <div class="col-md-6">
                <div class="form-group">
                  <input type="text" class="form-control" [(ngModel)]="resume.name" name="name" placeholder="Name"
                    #Name="ngModel" required
                    [ngClass]="{'is-invalid': Name.invalid && (Name.touched || resumeForm.submitted) }">
                </div>
                <div class="form-group">
                  <div class="form-group">
                    <textarea class="form-control" [(ngModel)]="resume.address" name="address" rows="3"
                      placeholder="Address" #Address="ngModel" required
                      [ngClass]="{'is-invalid': Address.invalid && (Address.touched || resumeForm.submitted) }"></textarea>
                  </div>
                </div>
              </div>
              <div class="col-md-6">
                <div class="form-group">
                  <input type="text" class="form-control" [(ngModel)]="resume.contactNo" name="contactNo"
                    placeholder="Contact No." #ContactNo="ngModel" required
                    [ngClass]="{'is-invalid': ContactNo.invalid && (ContactNo.touched || resumeForm.submitted) }">
                </div>
                <div class="form-group">
                  <input type="text" class="form-control" [(ngModel)]="resume.email" name="emailId"
                    placeholder="Email ID" #Email="ngModel" required
                    [ngClass]="{'is-invalid': Email.invalid && (Email.touched || resumeForm.submitted) }">
                </div>
              </div>
            </div>
          </div>
        </div>

  <br>
        <div class="shadow-sm card">
          <div class="card-body">
            <div class="d-flex justify-content-between card-title">
              <h4 class="d-flex align-items-center">
                <i class="material-icons">
                  rule
                </i>
                Skills</h4>
              <button class="btn btn-default" (click)="addSkill()">+</button>
            </div>
            <div class="row">
              <div class="col-md-4" *ngFor="let s of resume.skills; let i=index">
                <div class="form-group">
                  <input type="text" class="form-control" name="skill{{i}}" [(ngModel)]="s.value"
                    placeholder="e.g. Angular / Node / PHP " #Skill="ngModel" required
                    [ngClass]="{'is-invalid': Skill.invalid && (Skill.touched || resumeForm.submitted) }">
                </div>
              </div>
            </div>
          </div>
        </div>

      </div>

       <div class="col-md-4">
        <div class="shadow-sm card action-buttons">
          <button (click)="resumeForm.valid ? generatePdf('open') : ''"
            class="btn btn-secondary d-flex align-items-center justify-content-center mb-1">
            <i class="material-icons">
              picture_as_pdf
            </i> <span>&nbsp;Open PDF</span></button>
          <button (click)="resumeForm.valid ? generatePdf('download') : ''"
            class="btn btn-secondary d-flex align-items-center justify-content-center  mb-1">
            <i class="material-icons">
              cloud_download
            </i><span>&nbsp;Download PDF</span></button>
          <button (click)="resumeForm.valid ? generatePdf('print') : ''"
            class="btn btn-secondary d-flex align-items-center justify-content-center  mb-1">
            <i class="material-icons">
              print
            </i><span>&nbsp;Print PDF</span></button>

          <button type='reset' (click)="resetForm()"
            class="btn btn-secondary d-flex align-items-center justify-content-center  mb-1">
            <i class="material-icons">
              clear
            </i><span>&nbsp;Reset</span></button>
        </div>

        
      </div>
    </div>
  </form>
</div>


<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.14.0/css/all.min.css" integrity="sha512-1PKOgIY59xJ8Co8+NE6FZ+LOAZKjy+KY8iq0G4B3CyeY6wYHN3yt9PW0XpSriVlkMXe40PTKnXrLnZ9+fkDaog==" crossorigin="anonymous" />

<link href="https://fonts.googleapis.com/icon?family=Material+Icons"
      rel="stylesheet">




Output

Below is the full embeded code export PDF in Angular using PDFMake. you can easily used in your application.
Example

Spread the love
  •  
  •  
  •  
  •  
  • 4
  • 2
  •  
  •