A package called "pdfmake" enables pdf creation/download on front-end without any backend interaction. It would kick out the print css style from your app.
Environment
React 16.13.1
TypeScript 4.0.2
pdfmake 0.1.68
pdfmake
Official site(pdfmake)
Try playground to understand how it works.
Install
yarn add pdfmake
Example
This time let's make an employee list downloadable in pdf format using pdfmake.
EmployeeList.tsx
import { getPdfOptions } from '../../domain/employee';
import { Employee } from '../../typings';
import pdfMake from 'pdfmake/build/pdfmake';
import pdfFonts from 'pdfmake/build/vfs_fonts';
pdfMake.vfs = pdfFonts.pdfMake.vfs;
export function Employee(props: any) {
...
// In real world, this would be from redux state or aync fetch.
const employeeList: Employee[] = [
{ id: 'xxx', name: 'sample', email: 'test@mail.com', designation: 'Japan', department: 'Sample Dept.', age: 22, address: 'sample address #3333', contact: '11110000011' },
{ ... },
{ ... },
];
const onClickPdfMakeHandler = async () => {
const options = getPdfOptions(employeeList);
const d = new Date();
const date = `${d.getDate()}_${d.getMonth()+1}_${d.getFullYear()}`
pdfMake.createPdf(options).download(`Employee_list_${date}.pdf`);
}
...
return (
...
<button onClick={onClickPdfMakeHandler}
...
)
}
employee.ts
import _ from 'lodash';
export const getPdfOptions = (employeeList: Employee[]): any => {
const keys = ['fullName', 'email', 'employmentType', 'designation', 'department', 'age', 'address', 'contact', 'joinDate'];
const excludedKeys = ['id', 'updatedAt', 'createdAt', 'salary', 'rate', 'fixedRate', 'commission'];
const records = employeeList.map(employee => {
return _.compact(keys.map(key => {
if (excludedKeys.includes(key)) {
return null;
}
return employee[key] ?? '-';
}));
});
return {
info: {
title: 'Employee list',
},
pageSize: 'A4',
pageOrientation: 'landscape',
footer: function(currentPage: number, pageCount: number) {
return [
{ text: `Employee Management Sytem - ${currentPage.toString()} of ${pageCount}`, alignment: 'right', fontSize: 10, color: '#aaa', margin: [ 0, 0, 30, 10] }
]
},
content: [
{ text: 'Employee List', margin: [ 0, 16 ], fontSize: 16, bold: true },
{
layout: 'lightHorizontalLines',
fontSize: 10,
table: {
// headers are automatically repeated if the table spans over multiple pages
// you can declare how many rows should be treated as headers
headerRows: 1,
body: [ keys, ...records],
}
},
],
}
}
For more details, please refer to the offical document.