reactjs - tutorial - Generando un archivo PDF desde React Components
react tutorial (4)
El renderizado reacciona ya que el pdf es generalmente un dolor, pero hay una forma de evitarlo utilizando lienzo.
La idea es convertir: HTML -> Canvas -> PNG (o JPEG) -> PDF
Para lograr lo anterior, necesitarás:
import React, {Component, PropTypes} from ''react'';
// download html2canvas and jsPDF and save the files in app/ext, or somewhere else
// the built versions are directly consumable
// import {html2canvas, jsPDF} from ''app/ext'';
export default class Export extends Component {
constructor(props) {
super(props);
}
printDocument() {
const input = document.getElementById(''divToPrint'');
html2canvas(input)
.then((canvas) => {
const imgData = canvas.toDataURL(''image/png'');
const pdf = new jsPDF();
pdf.addImage(imgData, ''JPEG'', 0, 0);
// pdf.output(''dataurlnewwindow'');
pdf.save("download.pdf");
})
;
}
render() {
return (<div>
<div className="mb5">
<button onClick={this.printDocument}>Print</button>
</div>
<div id="divToPrint" className="mt4" {...css({
backgroundColor: ''#f5f5f5'',
width: ''210mm'',
minHeight: ''297mm'',
marginLeft: ''auto'',
marginRight: ''auto''
})}>
<div>Note: Here the dimensions of div are same as A4</div>
<div>You Can add any component here</div>
</div>
</div>);
}
}
El fragmento no funcionará aquí porque los archivos necesarios no se importan.
Se está utilizando un enfoque alternativo en esta respuesta , donde se eliminan los pasos intermedios y simplemente puede convertir de HTML a PDF. También hay una opción para hacer esto en la documentación de jsPDF, pero a partir de la observación personal, siento que se logra una mayor precisión cuando dom se convierte en png primero.
Actualización 0: 14 de septiembre de 2018.
El texto en los archivos PDF creados por este enfoque no será seleccionable. Si ese es un requisito, este artículo puede resultarle útil.
He estado construyendo una aplicación de votación. Las personas pueden crear sus encuestas y obtener datos sobre las preguntas que hacen. Me gustaría agregar la funcionalidad para permitir que los usuarios descarguen los resultados en forma de PDF.
Por ejemplo, tengo dos componentes que son responsables de captar la pregunta y los datos.
<QuestionBox />
<ViewCharts />
Estoy intentando generar ambos componentes en un archivo PDF. El usuario puede descargar este archivo PFD. He encontrado algunos paquetes que permiten la representación de un PDF dentro de un componente. Sin embargo, no pude encontrar uno que pueda generar PDF desde una secuencia de entrada que consiste en un DOM virtual. Si quiero lograr esto desde cero, ¿qué enfoque debo seguir?
Esta puede o no ser una forma subóptima de hacer las cosas, pero la solución más simple para el problema de varias páginas que encontré fue asegurar que toda la representación se realice antes de llamar al método jsPDFObj.save.
En cuanto a la representación de artículos ocultos, esto se resuelve con una solución similar a la sustitución del texto de la imagen css, coloco absolutamente el elemento a representar -9999px fuera de la página izquierda, esto no afecta al diseño y permite que el elemento sea visible para html2pdf , especialmente cuando se usan pestañas, acordeones y otros componentes de la interfaz de usuario que dependen de {display: none}
.
Este método ajusta los requisitos previos en una promesa y llama a pdf.save()
en el método finally()
. No puedo estar seguro de que esto sea infalible, o un anti-patrón, pero parece que funciona en la mayoría de los casos que le he lanzado.
// Get List of paged elements.
let elems = document.querySelectorAll(''.elemClass'');
let pdf = new jsPDF("portrait", "mm", "a4");
// Fix Graphics Output by scaling PDF and html2canvas output to 2
pdf.scaleFactor = 2;
// Create a new promise with the loop body
let addPages = new Promise((resolve,reject)=>{
elems.forEach((elem, idx) => {
// Scaling fix set scale to 2
html2canvas(elem, {scale: "2"})
.then(canvas =>{
if(idx < elems.length - 1){
pdf.addImage(canvas.toDataURL("image/png"), 0, 0, 210, 297);
pdf.addPage();
} else {
pdf.addImage(canvas.toDataURL("image/png"), 0, 0, 210, 297);
console.log("Reached last page, completing");
})
setTimeout(resolve, 100, "Timeout adding page #" + idx);
})
addPages.finally(()=>{
console.log("Saving PDF");
pdf.save();
});
Puede usar ReactDOMServer para procesar su componente a HTML y luego usarlo en jsPDF.
Primero hacen las importaciones:
import React from "react";
import ReactDOMServer from "react-dom/server";
entonces:
var doc = new jsPDF();
doc.fromHTML(ReactDOMServer.renderToStaticMarkup(this.render()));
doc.save("myDocument.pdf");
Prefiero usar:
renderToStaticMarkup
en lugar de:
renderToString
Como los anteriores incluyen código HTML que reacciona se basa en.
npm install jspdf --save
// código en reaccionar
importar jsPDF desde ''jspdf'';
var doc = new jsPDF ()
doc.fromHTML ("JOmin", 1, 1)
al hacer clic //
doc.save ("name.pdf")