MatthewHerbst / react-to-print

Print React components in the browser. Supports Chrome, Safari, Firefox and EDGE
MIT License
2.15k stars 220 forks source link

Version 3: How to Print Dynamic Content Without Rendering #756

Closed salememd closed 1 month ago

salememd commented 1 month ago

Hi,

In previous version we were able to add dynamic content by simple create html element as following

const handlePrint = useReactToPrint({
    content: () => {
        return printComponent(ref.current?.cloneNode(true), true)
    }
});

export const printComponent = (html?: any, isTable: boolean = false): ReactInstance => {
    const PrintElem = document.createElement('div');
    PrintElem.className = isTable ? "table_printing_content" : "printing_content"
    const header =
        `<b>${((current.profile?.firstname?.value ?? "") + " " + (current.profile?.lastname?.value ?? "")).trim() + " (" + (current.username?.value ?? "") + " - " + (current.organization?.name?.value ?? "") + ")"}</b>` +
        `<br><b>${formatDate(new Date())}</b>` +
        `<br><b>${window.location.href}</b>`
    PrintElem.innerHTML = header;
    PrintElem.appendChild(html);
    return PrintElem
}

How can we do the same thing in the new version?

Thanks,

MatthewHerbst commented 1 month ago

Hello. It seems your existing code returns the element itself to the function, rather than the ref to the element.

You should be able to accomplish this same workflow by using lazy print content loading (example).

export const LazyContent = () => {
  const reactToPrintContent = () => {
    return printComponent(ref.current?.cloneNode(true), true);
  };

  const handlePrint = useReactToPrint({});

  return (
    <div>
      <button onClick={() => handlePrint(reactToPrintContent)}>
        Print
      </button>
    </div>
  );
};

Please let me know if this works for you.

Your existing code is honestly a bit strange (I would not expect to see document.createElement calls within React code). Is there a reason you are doing it this way instead of rendering the component as standard JSX?

salememd commented 1 month ago

Thanks for your response. We're using document.createElement because we want to print dynamic content without actually rendering on the page,

I'll try the above code ASAP

Thanks

salememd commented 1 month ago

Thanks it worked!

MatthewHerbst commented 1 month ago

Glad you got it working! Please let me know if you encounter any other issues.

print dynamic content without actually rendering on the page

There are a few ways to do that without needing to call document.createElement:

For example, you could use a CSS media query so that the content only display when printing

    return (
        <div>
            <NormalContent />
            <div className="printContent">
                <PrintContent />
            </div>
        </div>
    );
    .printContent {
        display: none;

        @media print {
            display: block;
        }
    }

Alternatively, you could use the onBeforePrint and onAfterPrint callbacks from useReactToPrint to conditionally render DOM elements only while printing.