Reputation: 193
I'm currently using the react-to-print library in my React application to enable printing functionality for a component. However, whenever I trigger the print action, a print dialog box pops up, which I'd like to disable to streamline the printing process.
import React, { useEffect, useRef } from 'react';
import { useReactToPrint } from 'react-to-print';
import LocalPrintshopIcon from '@mui/icons-material/LocalPrintshop';
import IconButton from '@mui/material/IconButton';
import Tooltip from '@mui/material/Tooltip';
import { findGrandTotal, convertTimestamp } from '../utils/functions';
import { businessDetailsData, invoiceDetailsData } from './data';
export const ViewInvoice = () => {
const ComponentRef = useRef();
const handlePrint = useReactToPrint({
content: () => ComponentRef.current,
});
const invoiceDetails = invoiceDetailsData;
const businessDetails = businessDetailsData;
useEffect(() => {
const handleHotkey = (event) => {
if (event.ctrlKey && event.key.toUpperCase() === 'P') {
event.preventDefault();
handlePrint()
}
};
document.body.addEventListener('keydown', handleHotkey);
return () => {
document.body.removeEventListener('keydown', handleHotkey);
};
}, []);
return (
<>
<div className="w-full flex items-center md:justify-start justify-center relative">
<Tooltip title="Print Invoice">
<IconButton
onClick={handlePrint}
style={{
position: 'fixed',
top: '10px',
right: '30px',
zIndex: '1000px',
color: '#F7CCAC',
}}
>
<LocalPrintshopIcon style={{ fontSize: '50px' }} />
</IconButton>
</Tooltip>
<div
className="w-full md:w-2/3 shadow-xl mx-auto mt-8 rounded"
ref={ComponentRef}
>
<div className="w-full bg-black flex items-center">
<div className="w-1/2 h-[100%] p-8 ">
<img
src={businessDetails ? businessDetails[0].data.logo : ''}
alt="Logo"
className="w-[150px]"
/>
</div>
<div className="w-1/2 px-6 py-4">
<h3 className="text-gray-50 text-2xl mb-8">Invoice</h3>
<p className="text-gray-50 text-sm mb-1">Invoice ID:</p>
{invoiceDetails && (
<p className="text-gray-300 mb-5 text-sm">
{invoiceDetails.id.slice(0, 5)}
</p>
)}
<p className="text-gray-50 text-sm mb-1">Date:</p>
{invoiceDetails && (
<p className="text-gray-300 text-sm">
{convertTimestamp(invoiceDetails.data.timestamp)}
</p>
)}
</div>
</div>
<div className="w-full flex items-center">
{invoiceDetails && (
<div className="w-1/2 p-8">
<h3 className="font-medium mb-2">Bill To:</h3>
<p className="text-sm mb-1">
{invoiceDetails.data.customerName}
</p>
<p className="text-sm mb-1">
{invoiceDetails.data.customerAddress}
</p>
<p className="text-sm mb-1">
{invoiceDetails.data.customerCity}
</p>
<p className="text-sm mb-1">
{invoiceDetails.data.customerEmail}
</p>
</div>
)}
{businessDetails && (
<div className="w-1/2 p-8">
<h3 className="font-medium mb-2">Bill From:</h3>
<p className="text-sm mb-1">
{businessDetails[0].data.businessName}
</p>
<p className="text-sm mb-1">
{businessDetails[0].data.businessAddress},
</p>
<p className="text-sm mb-1">
{businessDetails[0].data.businessCity}
</p>
</div>
)}
</div>
<div className=" p-8">
<table>
<thead>
<th>Item</th>
<th className="text-right text-sm">Cost</th>
<th className="text-right text-sm">Qty</th>
<th className="text-right text-sm">Price</th>
</thead>
<tbody>
{invoiceDetails &&
invoiceDetails.data.itemList.map((item) => (
<tr key={item.itemName}>
<td className="text-xs capitalize">{item.itemName}</td>
<td className="text-xs text-right">
{Number(item.itemCost).toLocaleString('en-US')}
</td>
<td className="text-xs text-right">
{Number(item.itemQuantity).toLocaleString('en-US')}
</td>
<td className="text-xs text-right">
{(
Number(item.itemQuantity) * Number(item.itemCost)
).toLocaleString('en-US')}
</td>
</tr>
))}
{invoiceDetails && (
<tr>
<td colSpan="3" className="text-right font-bold text-sm">
TOTAL AMOUNT
</td>
<td className="font-bold text-right uppercase text-sm">
{findGrandTotal(
invoiceDetails.data,
invoiceDetails.data.currency
)}
</td>
</tr>
)}
</tbody>
</table>
</div>
{businessDetails && (
<div className="w-full p-8">
<h3 className="font-semibold mb-2">Payment Details</h3>
<p className="text-sm mb-1 capitalize">
<span className="font-semibold">Account Name: </span>
{businessDetails[0].data.accountName}
</p>
<p className="text-sm mb-1">
<span className="font-semibold">Account Number: </span>
{businessDetails[0].data.accountNumber}
</p>
<p className="text-sm mb-1 capitalize">
<span className="font-semibold">Bank Name: </span>{' '}
{businessDetails[0].data.bankName}
</p>
</div>
)}
<footer className="px-8 py-4 bg-gray-200 w-full">
<p className="text-sm text-center">Thanks for the patronage!</p>
</footer>
</div>
</div>
</>
);
};
Issue: The problem arises when I attempt to print using the react-to-print library. Despite my efforts, I haven't been able to find a way to disable the print dialog box that appears each time I initiate printing.
What I've Tried: Investigated the react-to-print documentation for any specific configuration options related to the print dialog. Explored alternative libraries or methods for printing in React. Looked into browser-specific printing options but couldn't find a suitable solution.
I expect to be able to print the component without the print dialog box popping up, providing a seamless printing experience for users. If other library will provide this type of functionality then I can change library also
Upvotes: 5
Views: 722
Reputation: 32043
I maintain react-to-print
. Under the hood we call window.print
. Once we call that the printing process it out of our hands, and every browser will open the print dialog (some mobile browsers might open a Share dialog instead). There is no ability to customize this.
For react-to-print
specifically, if you wanted to do something custom, such as download the print directly, you could pass a custom print
property. From there you are given access to the underlying iframe with the content to print. You would have to convert that iframe into the format you want printed, such as a PDF, using a different library:
const handlePrint = useReactToPrint({
...,
print: async (iframe: HTMLIFrameElement) => {
// Use another library to convert the iframe to the format you want printed
// Use JS to download the generated file
},
...,
})
Upvotes: 2