Giter Site home page Giter Site logo

gregnb / react-to-print Goto Github PK

View Code? Open in Web Editor NEW
1.9K 10.0 214.0 2.16 MB

Print React components in the browser. Supports Chrome, Safari, Firefox and EDGE

License: MIT License

JavaScript 11.27% TypeScript 88.52% Shell 0.20%
reactjs react javascript

react-to-print's Introduction

react-to-print logo

ReactToPrint - Print React components in the browser

NPM Downloads npm version

So you've created a React component and would love to give end users the ability to print out the contents of that component. This package aims to solve that by popping up a print window with CSS styles copied over as well.

Demo

Run react-to-print

Install

npm install --save react-to-print

API

<ReactToPrint />

The component accepts the following props:

Name Type Description
bodyClass? string One or more class names to pass to the print window, separated by spaces
content? function A function that returns a component reference value. The content of this reference value is then used for print. Alternatively, pass the content directly to the callback returned by useReactToPrint
copyStyles? boolean Copy all <style> and <link type="stylesheet" /> tags from <head> inside the parent window into the print window. (default: true)
documentTitle? string Set the title for printing when saving as a file
fonts? { family: string, source: string; weight?: string; style?: string; }[] You may optionally provide a list of fonts which will be loaded into the printing iframe. This is useful if you are using custom fonts
onAfterPrint? function Callback function that triggers after the print dialog is closed regardless of if the user selected to print or cancel
onBeforeGetContent? function Callback function that triggers before the library gathers the page's content. Either returns void or a Promise. This can be used to change the content on the page before printing
onBeforePrint? function Callback function that triggers before print. Either returns void or a Promise. Note: this function is run immediately prior to printing, but after the page's content has been gathered. To modify content before printing, use onBeforeGetContent instead
onPrintError? function Callback function (signature: function(errorLocation: 'onBeforePrint' | 'onBeforeGetContent' | 'print', error: Error)) that will be called if there is a printing error serious enough that printing cannot continue. Currently limited to Promise rejections in onBeforeGetContent, onBeforePrint, and print. Use this to attempt to print again. errorLocation will tell you in which callback the Promise was rejected
pageStyle? string or function We set some basic styles to help improve page printing. Use this to override them and provide your own. If given as a function it must return a string
print? function If passed, this function will be used instead of window.print to print the content. This function is passed the HTMLIFrameElement which is the iframe used internally to gather content for printing. When finished, this function must return a Promise. Use this to print in non-browser environments such as Electron
removeAfterPrint? boolean Remove the print iframe after action. Defaults to false
suppressErrors? boolean When passed, prevents console logging of errors
trigger? function A function that returns a React Component or Element. Note: under the hood, we inject a custom onClick prop into the returned Component/Element. As such, do not provide an onClick prop to the root node returned by trigger, as it will be overwritten
nonce? string Set the nonce attribute for whitelisting script and style -elements for CSP (content security policy)

PrintContextConsumer

If you need extra control over printing and don't want to specify trigger directly, PrintContextConsumer allows you to gain direct access to the handlePrint method which triggers the print action. Requires React >=16.3.0. See the examples below for usage.

useReactToPrint

For functional components, use the useReactToPrint hook, which accepts an object with the same configuration props as <ReactToPrint /> and returns a handlePrint function which when called will trigger the print action. Requires React >=16.8.0. See the examples below for usage. Additionally, for-fine tuned control, the handlePrint callback can accept an optional content prop which will can be used instead of passing a content prop to the hook itself.

Compatibility

react-to-print should be compatible with most major browsers. We also do our best to support IE11.

Mobile Browsers in WebView

While printing on mobile browsers should work, printing within a WebView (when your page is opened by another app such as Facebook or Slack, but not by the full browser itself) is known to not work on many if not all WebViews. Some don't make the correct API available. Others make it available but cause printing to no-op when in WebView.

We are actively researching resolutions to this issue, but it likely requires changes by Google/Chromium and Apple/WebKit. See #384 for more information. If you know of a way we can solve this, your help would be greatly appreciated.

Known Incompatible Browsers

Examples

Run react-to-print

// Using a class component, everything works without issue
export class ComponentToPrint extends React.PureComponent {
  render() {
    return (
      <div>My cool content here!</div>
    );
  }
}

// Using a functional component, you must wrap it in React.forwardRef, and then forward the ref to
// the node you want to be the root of the print (usually the outer most node in the ComponentToPrint)
// https://reactjs.org/docs/refs-and-the-dom.html#refs-and-function-components
export const ComponentToPrint = React.forwardRef((props, ref) => {
  return (
    <div ref={ref}>My cool content here!</div>
  );
});

Calling from class components

import React from 'react';
import ReactToPrint from 'react-to-print';

import { ComponentToPrint } from './ComponentToPrint';

class Example extends React.PureComponent {
  render() {
    return (
      <div>
        <ReactToPrint
          trigger={() => {
            // NOTE: could just as easily return <SomeComponent />. Do NOT pass an `onClick` prop
            // to the root node of the returned component as it will be overwritten.
            return <a href="#">Print this out!</a>;
          }}
          content={() => this.componentRef}
        />
        <ComponentToPrint ref={el => (this.componentRef = el)} />
      </div>
    );
  }
}

Calling from class components with PrintContextConsumer

import React from 'react';
import ReactToPrint, { PrintContextConsumer } from 'react-to-print';

import { ComponentToPrint } from './ComponentToPrint';

class Example extends React.PureComponent {
  render() {
    return (
      <div>
        <ReactToPrint content={() => this.componentRef}>
          <PrintContextConsumer>
            {({ handlePrint }) => (
              <button onClick={handlePrint}>Print this out!</button>
            )}
          </PrintContextConsumer>
        </ReactToPrint>
        <ComponentToPrint ref={el => (this.componentRef = el)} />
      </div>
    );
  }
}

Calling from functional components with useReactToPrint

import React, { useRef } from 'react';
import { useReactToPrint } from 'react-to-print';

import { ComponentToPrint } from './ComponentToPrint';

const Example = () => {
  const componentRef = useRef();
  const handlePrint = useReactToPrint({
    content: () => componentRef.current,
  });

  return (
    <div>
      <ComponentToPrint ref={componentRef} />
      <button onClick={handlePrint}>Print this out!</button>
    </div>
  );
};

Calling from functional components with useReactToPrint using content passed to handlePrint()

import React, { useRef } from 'react';
import { useReactToPrint } from 'react-to-print';

export const AnotherExample = () => {
  const contentToPrint = useRef(null);
  const handlePrint = useReactToPrint({
    documentTitle: "Print This Document",
    onBeforePrint: () => console.log("before printing..."),
    onAfterPrint: () => console.log("after printing..."),
    removeAfterPrint: true,
  });

  return (
    <>
      <div ref={contentToPrint}>Hello Again</div>
      <button onClick={() => {
        handlePrint(null, () => contentToPrint.current);
      }}>
        PRINT
      </button>
    </>
  )
}

Note (401): In TypeScript, if you encounter componentRef.current error such as: Type 'undefined' is not assignable to type 'ReactInstance | null'., add null inside the useRef():

const componentRef = useRef(null);

Known Issues

  • onAfterPrint may fire immediately (before the print dialog is closed) on newer versions of Safari where window.print does not block

Common Pitfalls

  • documentTitle will not work if react-to-print is running within an iframe. If react-to-print is running within an iframe and your script has access to the parent document, you may be able to manually set and then restore the parent document's title during the print. This can be done by leveraging the onBeforeGetContent and onAfterPrint props.

  • When printing, only styles that directly target the printed nodes will be applied, since the parent nodes will not exist in the DOM used for the print. For example, in the code below, if the <p> tag is the root of the ComponentToPrint then the red styling will not be applied. Be sure to target all printed content directly and not from unprinted parents.

    <div className="parent">
      <p>Hello</p>
    </div>
    div.parent p { color:red; }
  • The connect method from react-redux returns a functional component that cannot be assigned a reference to be used within the content props' callback in react-to-print. To use a component wrapped in connect within content create an intermediate class component that simply renders your component wrapped in connect. See 280 for more.

  • Using a custom component as the return for the trigger props is possible, just ensure you pass along the onClick prop. See 248 for an example.

  • When rendering multiple components to print, for example, if you have a list of charts and want each chart to have its own print icon, ideally you will wrap each component to print + print button in its own component, and just render a list of those components. However, if you cannot do that for some reason, in your .map ensure that each component gets a unique ref value passed to it, otherwise printing any of the components will always print the last component. See 323 for more.

FAQ

Can react-to-print be used to download a PDF without using the Print Preview window?

No. We aren't able to print a PDF as we lose control once the print preview window opens. However, it should be very easy to use react-to-print to take the information you need an pass it to a library that can generate a PDF.

const handlePrint = useReactToPrint({
  ...,
  print: async (printIframe: HTMLIframeElement) => {
    // Do whatever you want here, including asynchronous work
    await generateAndSavePDF(printIframe);
  },
});

For examples of how others have done this, see #484

Can the ComponentToPrint be a functional component?

Yes, but only if you wrap it with React.forwardRef. react-to-print relies on refs to grab the underlying DOM representation of the component, and functional components cannot take refs by default.

Why does onAfterPrint fire even if the user cancels printing

onAfterPrint fires when the print dialog closes, regardless of why it closes. This is the behavior of the onafterprint browser event.

Why does react-to-print skip <link rel="stylesheet" href=""> tags

<link>s with empty href attributes are invalid HTML. In addition, they can cause all sorts of undesirable behavior. For example, many browsers - including modern ones, when presented with <link href=""> will attempt to load the current page. Some even attempt to load the current page's parent directory.

Note: related to the above, img tags with empty src attributes are also invalid, and we may not attempt to load them.

How do you make ComponentToPrint show only while printing

If you've created a component that is intended only for printing and should not render in the parent component, wrap that component in a div with style set to { display: "none" }, like so:

<div style={{ display: "none" }}><ComponentToPrint ref={componentRef} /></div>

This will hide ComponentToPrint but keep it in the DOM so that it can be copied for printing.

Setting state in onBeforeGetContent

Recall that setting state is asynchronous. As such, you need to pass a Promise and wait for the state to update.

const [isPrinting, setIsPrinting] = useState(false);
const printRef = useRef(null);

// We store the resolve Promise being used in `onBeforeGetContent` here
const promiseResolveRef = useRef(null);

// We watch for the state to change here, and for the Promise resolve to be available
useEffect(() => {
  if (isPrinting && promiseResolveRef.current) {
    // Resolves the Promise, letting `react-to-print` know that the DOM updates are completed
    promiseResolveRef.current();
  }
}, [isPrinting]);

const handlePrint = useReactToPrint({
  content: () => printRef.current,
  onBeforeGetContent: () => {
    return new Promise((resolve) => {
      promiseResolveRef.current = resolve;
      setIsPrinting(true);
    });
  },
  onAfterPrint: () => {
    // Reset the Promise resolve so we can print again
    promiseResolveRef.current = null;
    setIsPrinting(false);
  }
});

Note: for Class components, just pass the resolve to the callback for this.setState: this.setState({ isPrinting: false }, resolve)

Changing print settings in the print dialog

Unfortunately there is no standard browser API for interacting with the print dialog. All react-to-print is able to do is open the dialog and give it the desired content to print. We cannot modify settings such as the default paper size, if the user has background graphics selected or not, etc.

Printing video elements

react-to-print tries to wait for video elements to load before printing but a large part of this is up to the browser. Further, the image displayed will usually be the first frame of the video, which might not be what you expect to show. To ensure the proper image is displayed in the print we highly recommend setting the poster attribute of the video, which allows specifying an image to be a placeholder for the video until the video loads.

Electron

react-to-print can be used for printing in Electron, but you will need to provide your own print method since Electron does not natively support the window.print method. Please see this answer on StackOverflow for how to do this.

There is a fully-working example of how to use react-to-print with Electron available here.

link elements not displaying styles properly

Some frameworks such as Ruby on Rails will set media="screen" on <link> elements that don't have screen set. This can cause styles to appear incorrectly when printing. To fix, explicitly set media="screen" on your <link> elements. For <link> elements meant to apply only when printing, set media="print".

Helpful Style Tips

Set the page orientation

While you should be able to place these styles anywhere, sometimes the browser doesn't always pick them up. To force orientation of the page you can include the following in the component being printed:

<style type="text/css" media="print">{"\
  @page {\ size: landscape;\ }\
"}</style>

Set the page size

The default page size is usually A4. Most browsers do not allow JavaScript or CSS to set the page size. For the browsers that do, it is usually done using the CSS page size property. Check caniuse to see if the browsers you develop against support this.

@media print {
  @page {
    size: 50mm 150mm;
  }
}

Set custom margin to the page (29)

To set custom margin to the page,

First, create a function to return the page margin,

const getPageMargins = () => {
  return `@page { margin: ${marginTop} ${marginRight} ${marginBottom} ${marginLeft} !important; }`;
};

Now, within the JSX call this function within the style tags,

<style>{getPageMargins()}</style>

PS: This style tag should be inside the component that is being passed in as the content ref.

Set landscape printing (240)

In the component that is passed in as the content ref, add the following:

@media print {
  @page { size: landscape; }
}

Printing elements that are not displayed (159)

Instead of using { display: 'none'; }, try using { overflow: hidden; height: 0; }

Using the pageStyle prop

The pageStyle prop should be a CSS string. For example: ".divider { break-after: always; }"

Getting a blank page when printing

Many have found setting the following CSS helpful. See #26 for more.

@media print {
  html, body {
    height: 100vh; /* Use 100% here to support printing more than a single page*/
    margin: 0 !important;
    padding: 0 !important;
    overflow: hidden;
  }
}

When you've set the removeAfterPrint prop to true

If you are getting a blank page while setting removeAfterPrint to true, try setting it to false. This will tell the browser not to remove the iframe that we use to print, which it may be doing by mistake, especially on mobile browsers.

Styles incorrect in print dialog when using grid system

We often (#327, #343, #382) see issues reported where the developer is using Bootstrap or a similar grid system, and everything works great until the user goes to print and suddenly it seems the styles are off. We've found that often the issue is the grid library uses the smallest sized columns during printing, such as the xs size on Bootstrap's grid, a size developers often don't plan for. The simplest solution is to ensure your grid will adapt to this size appropriately, though this may not be acceptable since you may want the large view to print rather than the smaller view. Another solution is to override the grid column definition. Some newer versions of libraries have specific tools for dealing with printing, for example, Bootstrap 4's Display property.

Page Breaks

What to know:

Pattern for Page-Breaking Dynamic Content

Define a page-break class to apply to elements which could be sensibly split into a page.

<div className="print-container" style={{ margin: "0", padding: "0" }}>
  {listOfContent.map(yourContent => (
    <>
      <div className="page-break" />
      <div>{yourContent}</div>
    </>
  )}
</div>

In your styles, define your @media print styles, which should include setting your preference for CSS page-break- (see w3's reference for options) to auto, and ensuring that your page-break element does not affect non-print styles.

@media all {
  .page-break {
    display: none;
  }
}

@media print {
  html, body {
    height: initial !important;
    overflow: initial !important;
    -webkit-print-color-adjust: exact;
  }
}

@media print {
  .page-break {
    margin-top: 1rem;
    display: block;
    page-break-before: auto;
  }
}

@page {
  size: auto;
  margin: 20mm;
}

Troubleshooting Page Breaks

If your content rendered as print media does not automatically break multi-page content into multiple pages, the issue may be

  • Style incompatibilities with print media rendering
  • A need to assign CSS page-break- properties to define how your document should behave when printed

Common Page Break Pitfalls

  • A style of overflow: scroll, when rendered to print, will result in cut off content instead of page breaks to include the content
  • A style of position: absolute, when rendered to print, may result in reformatted, rotated, or re-scaled content, causing unintended affects to print page layout and page breaks
  • Using flex may interfere with page breaks, try using display: block

Handling Scrolling (603)

Edit react-to-print (Handling Scrolling)

If you need to print the content of a scrolling container, you may encounter the following issues:

To solve these problems, you need to modify the properties of the scrolling container when printing. You can pass a function to the print property, which will be called when printing. In this function, you can use the DOM API to query the scrolling container that needs to be modified, and then modify its properties to control the scroll position.

const customToPrint = (printWindow) => {
  const printContent = printWindow.contentDocument || printWindow.contentWindow?.document;
  const printedScrollContainer = printContent.querySelector('.scroll-container');

  const originScrollContainer = document.querySelector('.scroll-container');

  // Set the scroll position of the printed container to match the origin container
  printedScrollContainer.scrollTop = originScrollContainer.scrollTop;

  // You can also set the `overflow` and `height` properties of the printed container to show all content.
  // printedScrollContainer.style.overflow = "visible";
  // printedScrollContainer.style.height = "fit-content";

  printWindow.contentWindow.print();
}

const handlePrint = useReactToPrint({
  // ...
  print: customToPrint,
});

Simple Show All Content

In addition to the methods in the above example, you can also simply add a CSS class name to the scrolling container when printing to show all content.

Set the container to overflow: visible; height: fit-content when printing, cancel the scrolling behavior when the content overflows, and make the height adapt to the content.

@media print {
  .scroll-container {
    overflow: visible;
    height: fit-content;
  }
}

Note:

  • If the styles do not take effect, you can try using the !important modifier.
  • The styles provided in the above instructions are for reference only. Complex situations may require more styles to achieve the desired result.

Running locally

NOTE: The library is tested and built locally using Node >= 20.

react-to-print's People

Contributors

a-sync avatar arcturus5404 avatar aviklai avatar cmckni3 avatar dependabot[bot] avatar devuxer avatar eleonora-guidi avatar erikssource avatar fabb avatar gregnb avatar hbrannan avatar hisamafahri avatar hsusanoo avatar idanhaviv avatar isocroft avatar joeldenning avatar joshuakgoldberg avatar luckrnx09 avatar matthewherbst avatar mikesha avatar mjoyce91 avatar nikhils4 avatar omgbrown avatar sdshooter avatar sergeyshmakov avatar siaikin avatar sudeepsidhu avatar vtsybulin avatar wonsu avatar zb2oby avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-to-print's Issues

Color styles not showing in the print window.

Trigger:

renderPrintSSDetails = () => {
    return (
        <div>
            <ReactToPrint
                trigger={() => <li className="listMenuItem">Print SS Details</li>}
                content={() => this.componentRef}
                closeAfterPrint = {false}
            />
        </div>
    );
}

Content:

import React, { Component } from 'react';
import styled from 'styled-components';
import {Row, Col} from 'react-bootstrap';

const Bod = styled.div`
  *{
    text-align: center;
    font-size: 12px;
  }
`

class SSDetails extends Component {

renderBody = () => {
   return (<Bod>
      <Row className = "bg-dark">
        <Col xsOffset = {5} xs = {2}>
          <img className="logo" src='https://www.hattorihanzoshears.com/images/hanzo-dark-h.png' alt="Hattori Hanzo Shears"/>
        </Col>
      </Row>
      <br/>
      <Row>
        <Col xsOffset = {5} xs = {4} >
          <img alt = "logos" src="https://hattorihanzoshears.com/images/sslogoTop.png" width="100" className="img-responsive" />
        </Col>
      </Row>
      <br/>
      <Row>
        <Col
          xs = {12}
        >
        <Row>
          <Col
            xsOffset = {1}
            xs = {10}
          >
            <Row>
              <Col xs = {12}>

              </Col>
            </Row>
            <br/>
            <Row>
              </Col xs = {12}>

              </Col>
            </Row>
            <br/>
            <Row>
              </Col xs = {12}>

              </Col>
            </Row>
            <br/>
            <Row>
              <Col xs = {12}>

              </Col>
            </Row>
            <br/>
            <Row>
              <Col xs = {12}>
             
              </Col>
            </Row>
            <br/>
            <Row>
              <Col xs = {12}>
    
              </Col>
            </Row>
            <br/>
            <Ro/w>
              </Col xs = {12}>
           
              </Co/l>
            </Ro/w>
            </br/>
            <Row>
              <Col xs = {12}>
              
              </Col>
            </Row>
            <br/>
          </Col>
        </Row>
        </Col>
      </Row>
      <br/>
      <Row className = "head text-center">
        <Col xs = {12}>
          <Row>
            <Col xs = {12}>
              Powered by
            </Col>
          </Row>
          <br/>
          <Row>
            <Col xs = {12}>
              <img height = {30} src="https://www.hattorihanzoshears.com/images/hanzo-logo.png" alt = ""/>
            </Col>
          </Row>
          <br/>
          <Row>
            <Col xs = {12}>
              3941 Park Drive, Suite 20-446
            </Col>
          </Row>
          <Row>
            <Col xs = {12}>
              El Dorado Hills, CA 95762
            </Col>
          </Row>
        </Col>
      </Row>
    </Bod>);
  }

  render () {
    return (
      <React.Fragment>
        {this.renderBody()}
      </React.Fragment>
    )
  }
}

export default SSDetails;

My main problem is that no matter what I do it will not allow me to give the print view color styles, of any sort. No text color and no background color.

Fails to load print window when a malformed(?) link is on page

@gregnb
I hit this error because I have a browser extension that adds the following css to every page of mine:

<link type="text/css" id="dark-mode" rel="stylesheet" href="">

Here's a codesandbox where I manually add that css to the sandbox page and as you can see it fails to load the print window: : https://codesandbox.io/s/4jn3y155z7

I've tracked down what's happening:
Ideally the link's onload or onerror would be triggered which would call markLoaded (https://github.com/gregnb/react-to-print/blob/master/src/index.js#L152):

            newHeadEl.onload = markLoaded.bind(null, 'link');
            newHeadEl.onerror = markLoaded.bind(null, 'link');

Unfortunately neither onload or onerror is being called and thus markLoaded is never triggered. I'm not quite sure why onload/onerror isn't working in this case. Probably because the link doesn't actually link to an href? Messing around with the link

Any thoughts on how to safeguard against elements causing this to occur?

Maybe the link logic should be disabled by default until this is fixed?

Thanks!

Unable to print child components

<div style={{ textAlign: "left" }}>
       <p style={{ textTransform: "uppercase" }}>Name: {patient.get('firstName') + " " + 
         patient.get('middleName') + patient.get('lastName')}</p>
        <p>ID: {patient.get('id')}</p>
        <p>Time:{(new Date(parseInt(queueItem.get('time')))).toLocaleDateString()}</p>
        <p>Ticket 2453:</p>
         <p>There are patient(s) ahead of you</p>
         <QRCode size={100} value={434} />
         <Footer />
</div>

The components QRCode and Footer doesnt appear in the print.

Can't Load all print settings

<div> <div className="text-center"> <ReactToPrint copystyles={true} trigger={() => <a href="#">Print this out!</a>} content={() => this.componentRef} pageStyles="@page { size: landscape; }" /> </div> <PrintPage ref={el => (this.componentRef = el)} /> </div>
print

No trigger if CTRL+P clicked

Hey,

I'm working with React in TS, I wrote my own type definitions, everything works as expected on normal trigger of a button, but I can't get the component to trigger when CTRL+P is pushed.

What am I missing or is this a missing feature?

Can't print table on Google Chrome

when i click button to print data in data in tbody can't display on print mode but show in non-print mode

Google Chrome
Version 69.0.3497.100 (Official Build) (64-bit)

How to print as the page open?

Hallo,
Than you for sharing, I found the lib really usefull!

I would like to let the printing process start as the page open, but I do not know how to set the trigger function.
Do you think is there a way to manage this?

Thank you
Marta

Sometimes a printable area is sent to print before styles have loaded.

It happens when copyStyles set to true. I have an idea how to fix it. I'll try it when I have a free time and I'll make a merge request.
I think loading styles should be "promisified". When all styles is loaded, then target.print() should be called. Sorry for my English, I hope you understand what I mean :)

pageStyle - size not works?

I add pageStyle prop to my PrintComponent but it doesn't work with specific size like "A4 portrait" or "A4 landscape".

class Example extends React.Component {
  render() {
    return (
      <div>
        <ReactToPrint
          trigger={() => <a href="#">Print this out!</a>}
          content={() => this.componentRef}
        />
        <PrintComponent
          ref={el => (this.componentRef = el)}
          pageStyle="@page { size: A4 portrait;}"
        />
      </div>
    );
  }
}

export default Example;

Scale on print

Hello @gregnb !
Can I pass a scale to resize my print ?

Something like this


     <ReactToPrint
                trigger={() => (
                  <Menu.Item
                    icon='print'
                    name='Imprimir'
                    active={false}
                    onClick={() => { }}
                    scale={0.6}
                  />
                )}
                content={() => this._print}
                pageStyle=''
              />

cant't print as i add loading style

<!DOCTYPE html>
<html>

<head>
    <title>๐Ÿš—</title>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link href="./index.less" ; rel="stylesheet">
</head>
<style>
    .spinner {
        width: 100px;
        height: 100px;

        position: relative;
        margin: auto;
    }

    .double-bounce1,
    .double-bounce2 {
        width: 100%;
        height: 100%;
        border-radius: 50%;
        background-color:#a90e16;
        opacity: 0.6;
        position: absolute;
        top: 0;
        left: 0;

        -webkit-animation: sk-bounce 2.0s infinite ease-in-out;
        animation: sk-bounce 2.0s infinite ease-in-out;
    }

    .double-bounce2 {
        -webkit-animation-delay: -1.0s;
        animation-delay: -1.0s;
    }

    @-webkit-keyframes sk-bounce {
        0%,
        100% {
            -webkit-transform: scale(0.0)
        }
        50% {
            -webkit-transform: scale(1.0)
        }
    }

    @keyframes sk-bounce {
        0%,
        100% {
            transform: scale(0.0);
            -webkit-transform: scale(0.0);
        }
        50% {
            transform: scale(1.0);
            -webkit-transform: scale(1.0);
        }
    }
</style>

<body>
    <div id="app">
        <div style='position:relative;min-height:100vh;background-color:#2c3e50'>
            <div class="spinner" style='position:absolute;top:0;left:0;right:0;bottom:0;margin:auto'>
                <div class="double-bounce1"></div>
                <div class="double-bounce2"></div>
            </div>
        </div>
    </div>
    <script src="./src/app.js"></script>
</body>

</html>

if the code <div id="app">...</div> ,the inner is empty, the component of print is running ok.
ps: my app component is appended in the element which id is 'app'.

add onBeforePrint callback

I don't know if it is in the scope of this library, but I think it could be very nice to have such callback. For example, I have some collection of data and. For each item I have a button "Print Invoice". It would be very nice to update "Printable" component data instead of render it for each item.

Something like this:

static propTypes = {
/** Copy styles over into print window. default: true /
copyStyles: PropTypes.bool,
/
* Trigger action used to open browser print /
trigger: PropTypes.func.isRequired,
/
* Content to be printed /
content: PropTypes.func.isRequired,
/
* if you need to do something with the data for printable component
right before the print */
onBeforePrint: PropTypes.func,
};

static defaultProps = {
copyStyles: true,
onBeforePrint: () => {},
};

...

handlePrint = () => {

const {
  content,
  copyStyles,
  onBeforePrint,
} = this.props;

onBeforePrint();

let printWindow = window.open("", "Print", "status=no, toolbar=no, scrollbars=yes", "false");

...

}

I haven't checked it yet and I'm not sure if it's necessary for this library.

Sorry for every day comments here :) I have a project where I'll need to print a lot of data and while I researched print-connected libraries for React, I've found your library potentially the most useful for this project.

Print with check box checked

I have been using this library and found an issue not sure if some one has noticed it or if i am missing something to print checkbox. but it seems when the print command executed it removed the checked sign out of checkbox.

page with checkbox
screen shot 2018-11-01 at 6 19 24 pm

Actual Print preview
screen shot 2018-11-01 at 6 19 38 pm

Low quality images upon saving PDF

Images are high quality and working fine until I view them in the print pdf.

images here

Here is the ReactToPrint section of my code:


          <MyVotes
            ref={el => (this.componentRef = el)}
            pressed={this.state.pressed}
            legislatures={legislatures}
            stateName={stateName}
          />
          <p className="hintText text-muted" style={{ textAlign: "center" }}>
            Learn more{" "}
            <Link
              style={{ textDecoration: "underline", color: "inherit" }}
              className="active"
              to="/About"
            >
              here.
            </Link>
          </p>
          <div id="ShareSection">
            {this.state.pressed.length === 0 ? (
              <br />
            ) : (
              <div lg="12" style={{ margin: 0, textAlign: "center" }}>
                <ReactToPrint
                  trigger={() => (
                    <TiPrinter className="printButton" size={22} color="#333" />
                  )}
                  content={() => this.componentRef}
                  debug={true}
                />

Unable to render in IE11 using React 15

Hi there,

Thanks for the library, very useful!

While doing some browser testing, I was unable to render the react-to-print component in IE11. I saw there was a similar issue (#41) that appeared to be resolved in 2.0.0-alpha-3 (the version I'm using). I am using react 15 in my project (package specifies react ^16.2), but I don't see anything specific in the code that would require use of react 16. Copying the code into my codebase as opposed to importing from the node package, fixes the problem, but just posting in case others have run into this issue.

Not working on Edge.

Hello @gregnb ,

Really I like the library and its working fine on chrome but not working on Microsoft Edge and also in safari new window is getting open but not initializing the print.

Can you please look into that.

Thanks

Only runs window.print if img tag is present

The browser's print dialog does not seem to trigger unless an img tag is present. It can even be an img tag with no actual image (e.g. ) From the code, I can see that it assumes the content contains an image and then waits for the image(s) to load before firing window.print.

I can try my hand at a PR if needed.

Could React be moved to a peerDependency, allowing "official" React 15 support?

The package currently lists "react": "^16.2.0" in it's dependencies. Could this be relaxed to a peerDependency?

Further, as far as I can tell, there is nothing special about React 16.2.0 that this library uses. It does not use <Fragment> and it does not care about the setState callback.

Actually, as far as I can tell, this library doesn't even need React 16 at all, and should work fine with earlier versions of React, at least React 15. Do you know of any reason why React 16 would be required?

If not, would a PR removing the dependency on React and adding

"peerDependencies": {
  "react": "^15.0.0 || ^16.0.0"
}

be alright? This would mean users of other React versions would not need to ship an entirely different version of React to their users just for this package to work.

Print dialog is not displayed when using <img src="file.svg" />

Thanks for great tool. Just one thing that I found, when I was using

<img src="file.svg" />

then print dialog is not displayed. It just displays popup. I solved it for me by using direct <svg...

Another thing is when onBeforePrint callback is called and I call setState (to hide some elements) in this callback, it is not handled.
I had to do some hack:

Helper function

handlePrint = () => {
  if (this.printer && this.printer.firstChild) {
    this.setState({
      isPrinting: true,
    }, () => {
      this.printer.firstChild.click();
    });
  }
}

in Render

      <Button type="submit" onClick={this.handlePrint}>
        Print!
      </Button>
      <div
        ref={(printer) => { this.printer = printer; }}
      >
        <ReactToPrint
          onAfterPrint={this.printFinished}
          trigger={() => (<div />)}
          content={() => this.componentRef}
        />
      </div>

Print dialogue only open once in safari on Mac

Please help with following issue.

On safari, first time print dialogue opens up and everything works fine.
When trying to print again, A dialogue coming up asking to print or not(That is safari may be)
But after i click on "Print" then print dialogue is not showing up.

I also tried the same thing on the example provided in repo. same thing.

Please guide if you faced such issue or help fixing it.

Explained documentation needed

More examples and detailed documentation needed.
There are very few questions in stackoverflow. Because of that different kind of usage and examples needed.

Cannot print image

I have One html with avatar and use example to print but the avatar become blank
HTML:
image

Preview:
image

2.0.0-alpha-2 fails for IPhone+Safari/Chrome and Windows 10 + IE11

Thanks for the library, but in it's current state it doesn't seem like it's ready for widespread use. I guess the alpha version tag means you may already be aware there are issues.

Steps to reproduce:

  1. Try to print using the provided react-to-print test page: https://kmmw7l39y7.codesandbox.io/#

IPhone + Safari Results: Safari shows blank page in print preview
IPhone + Chrome Results: Nothing happens when button is clicked.
Windows + IE11 Results: 'Hung/Long running script pop up', no print preview.

Phone details:
IPhone (Latest) Plus, IOS 11.2.6

Windows Details:
Windows 10
IE11

Margin on top of printed page

First and foremost thank you very much for this repo, it's by far the easiest React printer to use/implement that I've tested.

I had one question though: when I print the same component multiple times (i.e. the same component several times within a div, and the ref is to the div), there is a small 8px margin on top of only the first printed component (each is printing to a different page by the way).

I read that setting the @media print body margin-top to 0 would fix it but so far that hasn't changed anything. (link: https://stackoverflow.com/questions/5024393/page-margins-for-printing-in-css).

Any suggestions?

Responsive design printed

Hi, I'm building a project using reactstrap/bootstrap and I have my inner components set to be full-width at certain browser widths <Col xs={12} sm={12} md={6} lg={6}>...

Unfortunately, react-to-print is choosing to print the components at full-width, which I do not want, since they fit nicely at half-width.

How do you compensate for responsive components? Can I request it print as if the browser were at max-width?

Controlling window properties (fullscreen, toolbar etc.)

Can we control all of the window parameters? I think this will be useful.
Actually I only need fullscreen property but controlling the other properties could be good.

https://github.com/gregnb/react-to-print/blob/f03aa02caf9a871b9cbf90e9a3c5d1a09fa4f144/src/index.js#L59

I think we could make an object property (windowParams) and override it.

class Example extends React.Component {
  render() {
    return (
      <div>
        <ReactToPrint
          windowParams={{
            fullscreen: 'yes',
          }}
          trigger={() => <a href="#">Print this out!</a>}
          content={() => this.componentRef}
        />
        <ComponentToPrint ref={el => (this.componentRef = el)} />
      </div>
    );
  }
}

And we could convert this object to string.
index.js

const windowParameters = {
  status: 'no',
  toolbar: 'no',
  scrollbar: 'yes',
  ...windowParams
}
//Need a good stringify algorithm or npm project
let printWindow = window.open("", "Print", windowParameters.stringifyProperly(), "false");

What do you think?

Icon fonts are not rendering the icons

I have a component rendering icons using fonts. When the print on that component is triggered, it doesn't load the fonts, all the other styles are there, but not the icons

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.