How to print a React component at the click of a button?

How can I print only one component with the click of a button.

I know this solution:

window.frames["print_frame"].window.focus(); window.frames["print_frame"].window.print(); $('.print_frame').remove(); 

But React does not want to work with the frame.

Any solutions? Thanks.

+14
source share
7 answers

There are several solutions on the client. One of them with frames as you posted. You can use iframe though:

 var content = document.getElementById("divcontents"); var pri = document.getElementById("ifmcontentstoprint").contentWindow; pri.document.open(); pri.document.write(content.innerHTML); pri.document.close(); pri.focus(); pri.print(); 

It expects this html to exist

 <iframe id="ifmcontentstoprint" style="height: 0px; width: 0px; position: absolute"></iframe> 

Another solution is to use a multimedia selector, and in the styles media="print" hide everything that you do not want to print.

 <style type="text/css" media="print"> .no-print { display: none; } </style> 

The latter method requires some work on the server. You can send all HTML + CSS to the server and use one of the many components to create a document for printing, such as PDF. I tried the settings using PhantomJs.

+22
source

6/19/2017 This worked perfectly for me.

 import React, {Component} from 'react' class PrintThisComponent extends Component { componentDidMount() { console.log('PrintThisComponent mounted!') } render() { return ( <div> <button onClick={() => window.print()}>PRINT</button> <p>Click above button opens print preview with these words on page</p> </div> ) } } export default PrintThisComponent 
+10
source

If you want to print specific data that you already have access to, whether from the Store, AJAX or other sources, you can use my library to respond to printing.

https://github.com/captray/react-print

This greatly simplifies the creation of print patterns (provided that you already have a reaction dependency). You just need to tag your HTML accordingly.

This identifier should be added above in your actual DOM tree to exclude everything except “print mount” below.

 <div id="react-no-print"> 

This is where your print responsive component will mount and wrap the template you created:

 <div id="print-mount"></div> 

An example looks something like this:

 var PrintTemplate = require('react-print'); var ReactDOM = require('react-dom'); var React = require('react'); var MyTemplate = React.createClass({ render() { return ( <PrintTemplate> <p>Your custom</p> <span>print stuff goes</span> <h1>Here</h1> </PrintTemplate> ); } }); ReactDOM.render(<MyTemplate/>, document.getElementById('print-mount')); 

It is worth noting that you can create new ones or use existing child components inside your template, and everything should display well for printing.

+5
source

You will have @media print {} print using @media print {} in CSS, but simple code:

 export default class Component extends Component { print(){ window.print(); } render() { ... <span className="print" onClick={this.print}> PRINT </span> } } 

Hope this is helpful!

+4
source

I was looking for a simple package that would perform the same task and couldn’t find anything, so I created https://github.com/gregnb/react-to-print p>

You can use it like this:

  <ReactToPrint trigger={() => <a href="#">Print this out!</a>} content={() => this.componentRef} /> <ComponentToPrint ref={el => (this.componentRef = el)} /> 
+3
source

First I want to pay tribute to @ emil-ingerslev for the excellent answer. I tested this and it worked perfectly. However, there were two things that I wanted to improve.

  1. I did not like that <iframe id="ifmcontentstoprint" style="height: 0px; width: 0px; position: absolute"></iframe> already exists in the dom tree.
  2. I wanted to create a way to make it reusable.

I hope this makes others happy and saves a few minutes of life. Now go, take those extra minutes and do something nice for someone.

 function printPartOfPage(elementId, uniqueIframeId){ const content = document.getElementById(elementId) let pri if (document.getElementById(uniqueIframeId)) { pri = document.getElementById(uniqueIframeId).contentWindow } else { const iframe = document.createElement('iframe') iframe.setAttribute('title', uniqueIframeId) iframe.setAttribute('id', uniqueIframeId) iframe.setAttribute('style', 'height: 0px; width: 0px; position: absolute;') document.body.appendChild(iframe) pri = iframe.contentWindow } pri.document.open() pri.document.write(content.innerHTML) pri.document.close() pri.focus() pri.print() } 

EDIT 2019-7-23: after using this more, it has the disadvantage that it does not perfectly display the reacting components. This worked for me when the style was inline, but not when it was handled by styled components or some other situations. If I come up with a reliable method, I will update.

+1
source

Just sharing what worked in my case, as someone else, might prove useful. I have a modal, and I just wanted to print its text, which could consist of several pages on paper.

The other solutions I tried just printed one page and only what was on the screen. Emil made a decision that worked for me:

fooobar.com/questions/986853 / ...

This is how the component ended up looking. He prints everything in the body of the modal.

 import React, { Component } from 'react'; import { Button, Modal, ModalBody, ModalHeader } from 'reactstrap'; export default class TestPrint extends Component{ constructor(props) { super(props); this.state = { modal: false, data: [ 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test' ] } this.toggle = this.toggle.bind(this); this.print = this.print.bind(this); } print() { var content = document.getElementById('printarea'); var pri = document.getElementById('ifmcontentstoprint').contentWindow; pri.document.open(); pri.document.write(content.innerHTML); pri.document.close(); pri.focus(); pri.print(); } renderContent() { var i = 0; return this.state.data.map((d) => { return (<p key={d + i++}>{i} - {d}</p>) }); } toggle() { this.setState({ modal: !this.state.modal }) } render() { return ( <div> <Button style={ { 'position': 'fixed', 'top': '50%', 'left': '50%', 'transform': 'translate(-50%, -50%)' } } onClick={this.toggle} > Test Modal and Print </Button> <Modal size='lg' isOpen={this.state.modal} toggle={this.toggle} className='results-modal' > <ModalHeader toggle={this.toggle}> Test Printing </ModalHeader> <iframe id="ifmcontentstoprint" style={{ height: '0px', width: '0px', position: 'absolute' }}></iframe> <Button onClick={this.print}>Print</Button> <ModalBody id='printarea'> {this.renderContent()} </ModalBody> </Modal> </div> ) } } 

Note. However, I am having difficulty displaying styles in an iframe .

0
source

Source: https://habr.com/ru/post/986853/


All Articles