laravel-snappy: Google charts not rendering in PDF

I could not figure out how to make Google Visualization Charts load in my pdf.

I tried with a high javascript-delay but still not working. Rendering the view works fine though.

Thanks

    $pdf = \PDF::loadView('invoice', compact('data'));

    $pdf->setOptions([
            'enable-javascript' => true,
            'javascript-delay' => 10000,
            'images' => true,
            'enable-smart-shrinking' => true,
            'no-stop-slow-scripts' => true
        ]);

    return $pdf->download('invoice.pdf');

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 22 (1 by maintainers)

Most upvoted comments

Thank you! This worked!

For reference: google.charts.load('current', {packages: ['corechart']}); var interval = setInterval(function() { if ( google.visualization !== undefined && google.visualization.DataTable !== undefined && google.visualization.PieChart !== undefined ){ clearInterval(interval); window.status = 'ready'; drawCharts(); } }, 100);

Encountered this issue recently. I have tried all the workarounds to fix the loading issue - setOnLoadCallback, delays, setInterval, setTimeout. Also tried upgrading the wkhtml version.

What worked for me is explicitly define the Google Charts version number to use. In my case version 44.

<script>google.load("visualization", "44", {packages:["corechart"]});</script>

Note: using version “1” now means you are using the current version. Per Google document - “All ‘jsapi’ requests are now being redirected to the new loader. If you were loading version ‘1’ or ‘1.0’, you will now be loading ‘current’.”

I had this same issue, tried @Abisco solution but it didn’t work too.

        $pdf = SnappyPDF::loadView('report', []);
        $pdf->setOption('enable-javascript', true);
        $pdf->setOption('no-stop-slow-scripts', true);
        $pdf->setOption('margin-bottom', 0);
        $pdf->setOption('margin-top', 0);
        $pdf->setOption('margin-left', 0);
        $pdf->setOption('margin-right', 0);
        $pdf->setOption('page-size', 'A4');
        $pdf->setOption('lowquality', false);
        $pdf->setOption('disable-smart-shrinking', true);
        $pdf->setOption('images', true);
        $pdf->setOption('window-status', 'ready');
        $pdf->setOption('run-script', 'window.setTimeout(function(){window.status="ready";},5000);');
        return $pdf->inline();
<head>
    <script src="http://www.gstatic.com/charts/loader.js"></script>
    <script>

      function init() {
        google.charts.load('current', {packages: ['corechart']});
        var interval = setInterval(function () {
          if (google.visualization !== undefined && google.visualization.DataTable !== undefined && google.visualization.PieChart !== undefined) {
            clearInterval(interval);
            window.status = 'ready';
            drawChart();
          }
        }, 100);
      }

      function drawChart() {
        // Define the chart to be drawn.
        var data = new google.visualization.DataTable();
        data.addColumn('string', 'Element');
        data.addColumn('number', 'Percentage');
        data.addRows([
          ['Nitrogen', 0.78],
          ['Oxygen', 0.21],
          ['Other', 0.01]
        ]);

        var chart = new google.visualization.PieChart(document.getElementById('myPieChart'));
        chart.draw(data, null);
      }
    </script>
</head>
<body onload="init()">
<div id="myPieChart" style="width: 500px; height: 500px;"></div>
</body>

Update: Solved the issue by using wkhtmltopdf 0.12.5

Any current solution? I couldn’t make it work with version 0.12.6 of wkhtmltopdf. When I use window.status it just freezes and never finishes loading the pages.

Thanks for the reply @henryavila ! You are right, the problem seems to be proper to wkhtmltopdf only.

By the way, the fact is that I generate a PDF but not showing it on a webpage. It’s a PDF automatically generated from a view in Laravel, so my question is : Chrome Headless seems to generate a PDF from a webpage, BUT does it will work in my case too… ? I will take a look anyway but i’m curious to know.

@runerod, I’m generating the pdf from laravel view too. Here is the code I’m running in production (code extracted and adapted)

$view = \Illuminate\Support\Facades\View::make($viewName, $data, $mergeData);
$handler = \Spatie\Browsershot\Browsershot::html($view);

// Set any of puppeteer option. see: https://github.com/puppeteer/puppeteer/blob/v1.9.0/docs/api.md#pagepdfoptions
$handler->setOption('format', 'A4');
$handler->setOption('landscape', 'false');
// see more example in https://github.com/spatie/browsershot#usage


// Pass any argument to Headless Chrome itself
// Sell all possible aruments here: https://peter.sh/experiments/chromium-command-line-switches/
$handler->addChromiumArguments([
   'font-render-hinting' => 'none', // Fix text align in pdf
])

// Necessary for chart to work. The Chrome will wait until all scripts are loaded
$handler->waitUntilNetworkIdle();

// "screen" or "print" (default). using screen allow to generate a pdf exctly as displayed in browser
$handler->emulateMedia('screen'); 


// get the pdf as raw data (encoded string). Usefull when attaching data in Email
$handler->pdf();

// Save the pdf in the $filePath location
$handler->save($filePath); 

Hope it helps.

I resolved removing the “callback”:

function init() {
    google.load("visualization", "44", {
      packages: ["corechart"]
    });
    {
      var interval = setInterval(function () {
        if (google.visualization !== undefined && google.visualization.DataTable !== undefined
          && google.visualization.ColumnChart !== undefined) {
          clearInterval(interval);
          drawCharts();
          window.status = 'ready';
        }
      }, 100);
    }
  }

And again, it was broken. Thank you mate, you saved me. It begins to be really complicated to generate PDF with charts with laravel-snappy, honestly. I’m thinking about switching to a front end generator…

I resolved removing the “callback”:

function init() {
    google.load("visualization", "44", {
      packages: ["corechart"]
    });
    {
      var interval = setInterval(function () {
        if (google.visualization !== undefined && google.visualization.DataTable !== undefined
          && google.visualization.ColumnChart !== undefined) {
          clearInterval(interval);
          drawCharts();
          window.status = 'ready';
        }
      }, 100);
    }
  }

Anyone having this problem, The Solution that I was using <script type="text/javascript" src="https://www.google.com/jsapi"></script> stop working.

The solution points by @Abisco Works great for me. Thanks

I found out it was related to this issue

I tried the old way to import google charts

       <script type="text/javascript" src="https://www.google.com/jsapi"></script>
       <script type="text/javascript">
           google.load("visualization", "1", {packages:["corechart"]});
           google.setOnLoadCallback(drawChart);
       </script>

Worked fine but not the latest version…

Please let me know you figured out a solution to load the latest version. Thanks