Search code examples
angularjswkhtmltopdf

WKHTMLTOPDF and Angular


Trying to download the PDF for a page that uses Angular. Sometimes it works, sometimes it doesn't: the page is rendered with {{ }} not interpreted.

How can I download the PDF of the fully-rendered page (there are some HTTP requests done with Angular, and lots of data manipulation done before the data is shown)?

EDIT (code) (the code is not relevant):

Back-end:

 ...
 wkhtmltopdf(url, options, function(code, signal) {
     //'url' points to a route that has 'res.render()' binded to it

     //Download the file
 });
 ...

 res.render('template', { data: data });

 ...

Front-end:

<html>
        <head>
                ...
        </head>

        <body>
                <div ng-app=".." class="container" ng-controller="..">

                </div>

                <script src='/angular/lib/jquery/jquery.min.js'></script>
                <script src='//ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/jquery-ui.min.js'></script>
                <script src='/angular/lib/bootstrap/bootstrap.min.js'></script>
                <script src='/angular/lib/angular/angular.min.js'></script>
                <script src='/angular/lib/underscore/underscore.js'></script>
                <script src='/angular/lib/morris/morris.min.js'></script>
                <script src='/angular/lib/morris/raphael-min.js'></script>

                ...
        </body>
</html>

Solution

  • You need to make sure Javascript has time to execute before wkhtmltopdf does its rendering. There are at least two ways to do this:

    1. The simple but rather bad way is to pass the --javascript-delay option with some number of milliseconds to give the page enough time to render before being converted to pdf.

    2. The slightly more complicated but better way is to pass the --window-status option with some string. If you do that, wkhtmltopdf will not render the pdf until the value window.status is equal to the string you passed with the option. Then, in your app, you should set this value manually after your page has rendered.