13

Trying to use client-side pdf library pdfmake in my Angular 2 (version=4.2.x) project.

In .angular-cli.json file, I declared js like this:

"scripts": [
    "../node_modules/pdfmake/build/pdfmake.js",
    "../node_modules/pdfmake/build/vfs_fonts.js"
  ]

And then in app.component.ts, I used it like this:

import * as pdfMake from 'pdfmake';

@Component({
selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
   pdf: any;
   downloadPdf() {
    let item = {firstName: 'Peter', lastName: 'Parker'};
    this.pdf = pdfMake;
    this.pdf.createPdf(buildPdf(item)).open();
  }
}

function buildPdf(value) {
   var pdfContent = value;
   var docDefinition = {
     content: [{
    text: 'My name is: ' + pdfContent.firstName  + ' ' + pdfContent.lastName + '.'
     }]
   }
   console.log(pdfContent);
   return docDefinition;
}

I hit below error in browser console when loading the app:

Uncaught TypeError: fs.readFileSync is not a function
at Object.<anonymous> (linebreaker.js:15)
at Object.<anonymous> (linebreaker.js:161)
at Object.../../../../linebreak/src/linebreaker.js (linebreaker.js:161)
at __webpack_require__ (bootstrap b937441…:54)
at Object.../../../../pdfmake/src/textTools.js (textTools.js:4)
at __webpack_require__ (bootstrap b937441…:54)
at Object.../../../../pdfmake/src/docMeasure.js (docMeasure.js:4)
at __webpack_require__ (bootstrap b937441…:54)
at Object.../../../../pdfmake/src/layoutBuilder.js (layoutBuilder.js:7)
at __webpack_require__ (bootstrap b937441…:54)

My workaround for solving this problem is:

Copy pdfmake.js and vfs_fonts.js to assets folder, and then add this to index.html:

<script src='assets/pdfmake.min.js'></script>
<script src='assets/vfs_fonts.js'></script>

Remove this from app.component.ts

import * as pdfMake from 'pdfmake';

And add this to app.component.ts:

declare var pdfMake: any;

Finally remove this from .angular-cli.js:

"../node_modules/pdfmake/build/pdfmake.js",
"../node_modules/pdfmake/build/vfs_fonts.js"

It works but it's still a workaround.

Anyone knows how to use this library in Angular/Typscript way?

Thanks a lot!

5 Answers 5

27

Following the instruction above made by @benny_boe , I've made it work! Let me summarize it as below:

First,

npm install pdfmake --save

Second, add below to typings.d.ts:

declare module 'pdfmake/build/pdfmake.js';
declare module 'pdfmake/build/vfs_fonts.js';

Third, in the file where pdfMake is being used, either component or service, add below lines:

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

Last, use pdfMake.xxx() as usual.

Sign up to request clarification or add additional context in comments.

5 Comments

When you do it like this, you might end up with duplicates of the pdfmake. Try the source map explorer to inspect your bundles if you've got it in your vendor AND your scripts bundles..
Yes, you're right, I don't have to add those 2 js to scripts section in .angular-cli.json. I've updated my post by removing the old second step. Thanks!
Is it [import * as pdfMake from 'pdfmake/build/pdfmake.js';] or [import pdfMake from 'pdfmake/build/pdfmake';] ?
If we follow this procedure, this is causing an issue while building with AOT. Does this happen with you guys too ?
@kharish Have you tried there min version...??? try to add pdfmake/build/pdfmake.min.js or pdfmake/build/pdfmake.min
13

So first things first. You do not need to add you 3rd party scripts to the .angular-cli.json AND add an import in your TS files. Take a look at the Global scripts Story from the Angular CLI.

Once you import a library via the scripts array, you should not import it via a import statement in your TypeScript code...

(There are no typings for pdfmake so you'll need to declare them when unsing the config file..)

So if you want to add it to your TS File... replace your import * as pdfMake from 'pdfmake'; (its the server-side version!) with the client-side version ('pdfmake/build/pdfmake'). You'll also need to add the fonts ('pdfmake/build/vfs_fonts') otherwise you'll get an error too.

When your imports are looking like this it should work:

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

3 Comments

Thanks! But it doesn't work, and the error is: Uncaught TypeError: Cannot read property 'pdfMake' of undefined. Please advise.
Yes, I've made it work by following Global scripts story you mentioned. Thanks a lot! I'll summarize it in another reply.
Glad to hear that you've got it working! I've tried my solution with the latest beta of Angular CLI (1.3.0-beta.1) and it works. On what version are you on?
3

Another simple approach when using global scripts according to angular-cli Stories Global Scripts if you follow the instruction carefully. IF the library doesn't have any typings.

On angular-cli.json file

"scripts": [
  "../node_modules/pdfmake/build/pdfmake.min.js",
  "../node_modules/pdfmake/build/vfs_fonts.js"
],

ON src/typings.d.ts file

Add declare var pdfMake: any; line below.

Now anywhere in your application the pdfMake global variable is now available.

Try to log pdfMake in the contructor or any init methods

ngOnInit() { console.log(pdfMake); }

OUTPUT

{
    createdPdf: f(t),
    vfs: {
        Roboto-Italic.ttf: "some long encoded string...",
        Roboto-Medium.ttf: "some long encoded string...",
        Roboto-MediumItalic.ttf: "some long encoded string...",
        Roboto-Regular.ttf: "some long encoded string...",
    }
}

Which means it is ready to use.

Comments

1
npm i pdfmake;

import * as pdfMake from 'pdfmake/build/pdfmake';
import * as pdfFonts from 'pdfmake/build/vfs_fonts';

pdfMake.vfs = pdfFonts.pdfMake.vfs;
  var dd = {
    content: [
      {
        layout: 'lightHorizontalLines', // optional
        table: {
          // headers are automatically repeated if the table spans over multiple pages
          // you can declare how many rows should be treated as headers
          headerRows: 1,
          widths: [ '*', 'auto', 100, '*' ],

          body: [
            [ 'First', 'Second', 'Third', 'The last one' ],
            [ 'Value 1', 'Value 2', 'Value 3', 'Value 4' ],
            [ { text: 'Bold value', bold: true }, 'Val 2', 'Val 3', 'Val 4' ]
          ]
        }
      }
    ]
  };
pdfMake.createPdf(dd).download();

1 Comment

Thank you for this code snippet, which might provide some limited, immediate help. A proper explanation would greatly improve its long-term value by showing why this is a good solution to the problem and would make it more useful to future readers with other, similar questions. Please edit your answer to add some explanation, including the assumptions you’ve made.
0

For Angular19 and pdfMake version 0.2.18, this imports worked for me:

import pdfMake from 'pdfmake/build/pdfmake';
import pdfFonts from 'pdfmake/build/vfs_fonts';
(pdfMake as any).vfs = pdfFonts;

I hope this saves someone time.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.