I am developing a Certificate Management System where after all the processes have been done, the user may print a certificate.
I am struggling to implement such that upon clicking the print button, a new tab will open containing the ready to print HTML certificate so that the user will only CTRL + P to have the certificate printed.
How do i render my react certificate ponent in a new window? Such that i would only pass the props which are the data to be put into the certificate e.g., name, date etc.. like <Certificate name={john} />
I have tried implementing the npm react-new-window but it does not work with
<Button onclick={() => {
<NewWindow>
<CertificateComponent>
</NewWindow>
}}
>
PRINT BUTTON
</Button>
I have looked into react portals but most use cases are for Modals, which is where my "PRINT" button is rendered.
Sorry for the bad english/explanation. Thank you!
I am developing a Certificate Management System where after all the processes have been done, the user may print a certificate.
I am struggling to implement such that upon clicking the print button, a new tab will open containing the ready to print HTML certificate so that the user will only CTRL + P to have the certificate printed.
How do i render my react certificate ponent in a new window? Such that i would only pass the props which are the data to be put into the certificate e.g., name, date etc.. like <Certificate name={john} />
I have tried implementing the npm react-new-window but it does not work with
<Button onclick={() => {
<NewWindow>
<CertificateComponent>
</NewWindow>
}}
>
PRINT BUTTON
</Button>
I have looked into react portals but most use cases are for Modals, which is where my "PRINT" button is rendered.
Sorry for the bad english/explanation. Thank you!
Share Improve this question asked Jul 21, 2021 at 6:37 A SA S 431 silver badge8 bronze badges 3- 1 Have you looked this link: stackoverflow./questions/47574490/… – Majid M. Commented Jul 21, 2021 at 6:45
- Have you tried this solution? stackoverflow./a/64391469/4831770 – Munei Nengwenani Commented Jul 21, 2021 at 6:48
- 1 @MajidMohammadi Yes, but this question was asked 3 and a half years ago, i assume that there might be a newer or more efficient way to work around this problem. Thank you still! – A S Commented Jul 21, 2021 at 6:51
4 Answers
Reset to default 2New Solution based on CreatePortal
import React, { useEffect, useCallback, useMemo, useState } from "react";
import { render, createPortal } from "react-dom";
const App = () => {
const [isOpen, setOpenState] = useState(false);
const open = useCallback(() => setOpenState(true));
const close = useCallback(() => setOpenState(false));
return (
<div>
<h1>Portals in React</h1>
<button onClick={open}>Open</button>
<button onClick={close}>Close</button>
{isOpen && (
<NewWindow close={close}>
Example <button onClick={close}>Close</button>
</NewWindow>
)}
</div>
);
};
const NewWindow = ({ children, close }) => {
const newWindow = useMemo(() =>
window.open(
"about:blank",
"newWin",
`width=400,height=300,left=${window.screen.availWidth / 2 -
200},top=${window.screen.availHeight / 2 - 150}`
)
);
newWindow.onbeforeunload = () => {
close();
};
useEffect(() => () => newWindow.close());
return createPortal(children, newWindow.document.body);
};
render(<App />, document.getElementById("root"));
This worked for me with React 18.
const secondaryWindow = window.open('', '_blank', 'width=600,height=400');
secondaryWindow.document.open();
secondaryWindow.document.write(`
<html>
<head>
<title>My Title</title>
</head>
<body>
<h2>My Header</h2>
<div id="scheduling-grid"></div>
</body>
</html>
`);
const secondaryRoot = secondaryWindow.document.getElementById('scheduling-grid');
const secondaryRootInstance = createRoot(secondaryRoot);
secondaryRootInstance.render(<RelevantComponent prop={prop} />)
There can be multiple approaches for this.
Approach 1:
Create a new route and map the certificateComponent
to it, make sure it doesn't have any authentication or any dependency to it.
Store the required data for certificateComponent
either in session storage or local storage.
When the user clicks on print button, redirect the user to this new route using window.open("http://localhost:port/newroute")
.
In certificateComponent
read the values stored in session/local storage and map it accordingly.
Approach 2:
Make the certificate ponent as an overlay which occupies the entire screen which shows up when the user click on print button. If any UI elements need to be hidden, you can do something as shown below:
printFn = function() {
// show the certificate ponent
// hide the ui elements not required
// window.print()
}
This worked for me
const myWindow: any = window.open('','', 'height: 500;width:500');
ReactDOM.render(<Yourponent prop={propValue} /> , myWindow.document.body);
myWindow.document.close();
myWindow.focus();
myWindow.print();
myWindow.close();