0
I am trying to generate a PDF of a page made in HTML. This page has a chart created with Chart Js. I would like to click on the button to generate a PDF of the chart. However, clicking the Button generates the Uncaught (in Promise) error Error: Element is not Attached to a Document. Do you know where I might be making some shortcoming for such a mistake ?
I’m using html2canvas (as I have been reading that it is necessary to first convert the file to PNG).
I’m also using the jspdf to convert the file to PDF.
Follow the code below that is presenting problems:
window.onload = function() {
//Chamando função ao carregar a página.
let pegar = pegarStatusAtividades(configuraDados);
html2canvas(document.querySelector("#canvas_status_atividades")).then(canvas => {
document.body.appendChild(canvas)
});
// Função que transforma canvas em imagem e exporta para PDF
// Você pode usar $(.'elemento').click() do jQuery para disparar a função
$('#gerar-pdf').on('click', function() {
html2canvas($('#canvas_status_atividades'), {
onrendered: function(canvas) {
var imgData = canvas.toDataURL('image/png');
var pdf = new jsPDF('p', 'mm');
pdf.addImage(imgData, 'PNG', 10, 10);
pdf.save('test.pdf');
}
});
});
}
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<!-- Required meta tags -->
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE-edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Aprendendo</title>
<link href="_bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet">
<!-- ARQUIVO CSS DO BOOTSTRAP -->
<link href="_chart/dist/Chart.css" rel="stylesheet">
<script src="_chart/dist/Chart.js"></script>
</head>
<body>
<div class="row">
<div class="col-lg-12">
<h1 class="text-center">Gráficos de Status das Atividades</h1>
</div>
</div>
<div class="container-fluid" id="container-canvas">
<div class="row">
<div class="col-lg-8 offset-lg-2">
<canvas id="canvas_status_atividades" width="400" height="400"></canvas>
</div>
</div>
<div class="row">
<div class="col-lg-8 offset-lg-2">
<button class="btn btn-primary" id="gerar-pdf">Gerar PDF</button>
</div>
</div>
</div>
<script src="_jquery/jquery-3.3.1.min.js"></script>
<!-- ARQUIVO JQUERY -->
<script src="_bootstrap/4.3.1/js/bootstrap.min.js"></script>
<!-- ARQUIVO BOOTSTRAP -->
<script src="_jsPDF/dist/jspdf.min.js"></script>
<!-- ARQUIVO jspdf -->
<script src="_html2canvas/html2canvas.js"></script>
<!-- ARQUIVO html2canvas -->
<script src="scripts/script.js"></script>
</body>
</html>
OBS: The Chart is generated without problems with the JS Chart:
Very good, William. Thank you very much, man. Let me ask you one more question. If I want, instead of just picking up a chart, pick up the whole page (because the page has multiple graphics), as I would ?
– Gato de Schrödinger
Like, pick up all the same. Menu, footer and other html elements of the page.
– Gato de Schrödinger
@Jason-Theinternship. in this case you will have to use html2canvas itself, but take a look if you are using the latest version and if there is no other script getting in the way, I would personally replace the canvas at the time in the snapshot by the image made by toDataURL and then use HTML2CANVAS
– Guilherme Nascimento
I’m using the latest yes. I got it on https://html2canvas.hertzen.com/.
– Gato de Schrödinger
William, could you help me with that ? I’m a layman and it’s the first time I’m using html2canvas and jspdf.
– Gato de Schrödinger
@Jason-Theinternship.may be some script of yours that is affecting the canvas, tried to use
html2canvas(document.body, {
and the same error occurs?– Guilherme Nascimento
When I do this, no error is generated, but also the PDF is not generated.
– Gato de Schrödinger
@Jason-Theinternship. but if nothing is generated is pq has another error, you made my suggestion, only at the time of snapshot change the canvas by the generated image and then apply html2canvas?
– Guilherme Nascimento
Snapshot occurs at the time of the pdf.addImage line ?
– Gato de Schrödinger
@Jason-Theinternship. take
canvas_status_atividades.toDataURL()
adds withvar nova = new Image; nova.src = canvas_status_atividades.toDataURL();
, then take the variablenova
, being like this:canvas_status_atividades.parentNode.replaceChild(canvas_status_atividades, nova);
, there inside theonrendered
do the opposite to restore:onrendered: function () { nova.parentNode.replaceChild(nova, canvas_status_atividades); ... }
and at least try to grab the screenshot and open in awindow.open
, the PDF part you do after.– Guilherme Nascimento
Sorry, William. I couldn’t follow your reasoning. I’m going to google it. But thank you for your answer to my question. It has already been useful to me in the matter of printing the graphics. Thank you!
– Gato de Schrödinger
William, the script would look something like this at the beginning ? https://jsfiddle.net/28pycq4x/
– Gato de Schrödinger
@Jason-Theinternship. you pasted the onrendered loose, you do so: https://pastebin.com/raw/U0zSbAKR
– Guilherme Nascimento
William, gave an error in the line of replaceChild. Showed that one parameter of replace is not the son of the other. Uncaught Domexception: Failed to execute 'replaceChild' on 'Node': The Node to be replaced is not a Child of this Node.
– Gato de Schrödinger
And even in this case, it wouldn’t do the same thing as that code, which only shows the PDF, did ?
– Gato de Schrödinger
I’ll leave my complete code for you to see how it is. If you can help me solve this, I would appreciate it. I was trying to generate these PDF in PHP with Wkhtmltopdf, but I also found problems. The charts of the Charts do not appear with this lib. I am 4 days trying to do this, but I have not been succeeding. Follow the link. https://jsfiddle.net/97ub84aL/
– Gato de Schrödinger
@Jason-Theinternship. I’ll see when I get home and send you a gist or fiddle with a functional example ;)
– Guilherme Nascimento
Thank you, William.
– Gato de Schrödinger