I trying to generate PDF
with charts generated by Chart.js
library
but javascript does not render at all.
Do you see something I had missed?
# config/packages/knp_snappy.yaml
knp_snappy:
pdf:
enabled: true
binary: '%env(WKHTMLTOPDF_PATH)%'
options:
debug-javascript: true
enable-javascript: true
javascript-delay: 200
no-stop-slow-scripts: true
image:
enabled: true
binary: '%env(WKHTMLTOIMAGE_PATH)%'
options: []
PHP Symfony part
/**
* Download pdf.
*
* @param string $slug
* @param string $language
*
* @return Response
*
* @throws \Psr\Cache\CacheException
* @throws \Psr\Cache\InvalidArgumentException
*/
public function __invoke(string $slug, string $language): Response
{
$this->pdfFilesService->setPdfLanguage($language);
$base64Images = $this->pdfFilesService->getBase64Images($slug);
$profile = $this->profileData->execute($slug, $language);
$filename = $profile['name'].'-report.pdf';
$path = $this->parameterBag->get('app.private_pdf_storage').'/'.$filename;
$html = $this->templating->render('download_pdf.twig', \array_merge($base64Images, [
'profile' => $profile,
'language' => $language,
]));
$this->pdf->generateFromHtml([$html], $path, [], true);
return new Response(
$path,
200,
[
'Content-Type' => 'application/pdf',
'Content-Disposition' => 'inline; filename="'.$path.'"',
]
);
}
Twig
<section>
<div id="barMulti"></div>
</section>
<script type="text/javascript" src="{{ chartJs }}"></script>
<script type="text/javascript">
function getDataMulti(type) {
return {
// The type of chart we want to create
type,
// The data for our dataset
data: {
labels: [ ... ],
datasets: [
{
backgroundColor: "#F4F7F9",
data: [3,7,4,5,5,2,6,8,9,7]
},
{
backgroundColor: "#66C4E0",
data: [3,7,4,5,5,2,6,8,9,7]
},
{
backgroundColor: "#009DCD",
data: [3,7,4,5,5,2,6,8,9,7]
},
]
},
// Configuration options go here
options: {
legend: {
display: false,
},
animation: {
duration: 0
},
scales: {
yAxes: [{
gridLines: {
color: "#454D57",
},
ticks: {
padding: 20,
fontStyle: 'bold',
fontColor: '#F4F7F9',
min: 0,
max: 100,
}
}],
xAxes: [
{
gridLines: {
color: "#454D57"
},
ticks: {
fontStyle: 'bold',
fontColor: '#F4F7F9',
padding: 20,
callback: function(label) {
if (/\s/.test(label)) {
return label.split(" ");
}
return label;
}
}
}
]
}
}
}
}
// var barMulti = document.getElementById('barMulti');
var barMulti = document.getElementById('barMulti');
new Chart(barMulti, getDataMulti('bar'));
</script>
wkhtmltopdf
is not a perfect library but it is opensource and free to use, so we need to be grateful and try to help its usage or improve by contributing.
As the first step, you need to test your HTML/TWIG template for working Javascript.
<script>
document.body.innerHTML = "Testing JavaScript PDF Rendering"
</script>
If this is not working then check your wkhtmltopdf
configuration
# config/packages/knp_snappy.yaml
knp_snappy:
pdf:
enabled: true
binary: '%env(WKHTMLTOPDF_PATH)%'
options:
debug-javascript: true
enable-javascript: true
javascript-delay: 1500
no-stop-slow-scripts: true
After you are sure that Javascript works in wkhtmltopdf
Most important thing. You need to wrap your canvas
element with styled
div
<div class="reportGraph">
<canvas id="barMulti"></canvas>
</div>
and in head
or css
put styled class
.reportGraph {
width:850px
}
or maybe style canvas container by inline css
Then add this script file after including of chart.js
library
<script>
// wkhtmltopdf 0.12.5 crash fix.
// https://github.com/wkhtmltopdf/wkhtmltopdf/issues/3242#issuecomment-518099192
'use strict';
(function(setLineDash) {
CanvasRenderingContext2D.prototype.setLineDash = function() {
if(!arguments[0].length){
arguments[0] = [1,0];
}
// Now, call the original method
return setLineDash.apply(this, arguments);
};
})(CanvasRenderingContext2D.prototype.setLineDash);
Function.prototype.bind = Function.prototype.bind || function (thisp) {
var fn = this;
return function () {
return fn.apply(thisp, arguments);
};
};
</script>
Then add another script
tag in which you will render your chart.
<script>
function drawGraphs() {
new Chart(
document.getElementById("canvas"), {
"responsive": false,
"type":"line",
"data":{"labels":["January","February","March","April","May","June","July"],"datasets":[{"label":"My First Dataset","data":[65,59,80,81,56,55,40],"fill":false,"borderColor":"rgb(75, 192, 192)","lineTension":0.1}]},
"options":{}
}
);
}
window.onload = function() {
drawGraphs();
};
</script>