在Angular 2中打印Html模板(Angular 2中的ng-print)

时间:2016-12-29 11:58:08

标签: javascript angularjs angular

我想在角度2中打印HTML模板。我已经探讨了这个问题我在angularjs 1 Print Html Template in Angularjs 1

中得到了解决方案

任何建议都将不胜感激

11 个答案:

答案 0 :(得分:74)

我是如何在angular2中完成它的(它类似于 plunkered 解决方案)在您的HTML文件中:

<div id="print-section">
  // your html stuff that you want to print
</div>
<button (click)="print()">print</button>

并在您的TS文件中:

print(): void {
    let printContents, popupWin;
    printContents = document.getElementById('print-section').innerHTML;
    popupWin = window.open('', '_blank', 'top=0,left=0,height=100%,width=auto');
    popupWin.document.open();
    popupWin.document.write(`
      <html>
        <head>
          <title>Print tab</title>
          <style>
          //........Customized style.......
          </style>
        </head>
    <body onload="window.print();window.close()">${printContents}</body>
      </html>`
    );
    popupWin.document.close();
}

UPDATE:

您还可以快捷方式使用ngx-print库,以减少不一致的编码(混合JS和TS)以及更多开箱即用的可控和安全打印案例。

答案 1 :(得分:15)

如果有其他人遇到此问题,如果您已经放置了该页面,我建议使用媒体查询来设置您的打印页面。然后,您只需将打印功能附加到html按钮和组件调用window.print();

component.html:

<div class="doNotPrint">
    Header is here.
</div>

<div>
    all my beautiful print-related material is here.
</div>

<div class="doNotPrint">
    my footer is here.
    <button (click)="onPrint()">Print</button>
</div>

component.ts:

onPrint(){
    window.print();
}

component.css:

@media print{
  .doNotPrint{display:none !important;}
}

您也可以选择在媒体查询中添加您不希望打印的其他元素/部分。

您也可以更改打印查询中的文档边距和所有内容,这使其非常强大。网上有很多文章。这是一个看起来很全面的内容:https://www.sitepoint.com/create-a-customized-print-stylesheet-in-minutes/这也意味着您不必创建单独的脚本来创建“打印版本”&#39;页面或使用大量的JavaScript。

答案 2 :(得分:10)

你可以在角度2中做到这一点

ts文件中的

 export class Component{          
      constructor(){
      }
       printToCart(printSectionId: string){
        let popupWinindow
        let innerContents = document.getElementById(printSectionId).innerHTML;
        popupWinindow = window.open('', '_blank', 'width=600,height=700,scrollbars=no,menubar=no,toolbar=no,location=no,status=no,titlebar=no');
        popupWinindow.document.open();
        popupWinindow.document.write('<html><head><link rel="stylesheet" type="text/css" href="style.css" /></head><body onload="window.print()">' + innerContents + '</html>');
        popupWinindow.document.close();
  }

 }

in html

<div id="printSectionId" >
  <div>
    <h1>AngularJS Print html templates</h1>
    <form novalidate>
      First Name:
      <input type="text"  class="tb8">
      <br>
      <br> Last Name:
      <input type="text"  class="tb8">
      <br>
      <br>
      <button  class="button">Submit</button>
      <button (click)="printToCart('printSectionId')" class="button">Print</button>
    </form>
  </div>
  <div>
    <br/>
   </div>
</div>

答案 3 :(得分:3)

编辑:更新了摘录,以提供更通用的方法

只是对已接受答案的扩展,

要获取现有样式以保留目标组件的外观,您可以:

  1. 进行查询以从顶级文档中提取<style><link>元素

  2. 将其注入HTML字符串。

要获取HTML标签:

private getTagsHtml(tagName: keyof HTMLElementTagNameMap): string
{
    const htmlStr: string[] = [];
    const elements = document.getElementsByTagName(tagName);
    for (let idx = 0; idx < elements.length; idx++)
    {
        htmlStr.push(elements[idx].outerHTML);
    }

    return htmlStr.join('\r\n');
}

然后在现有代码段中:

const printContents = document.getElementById('print-section').innerHTML;
const stylesHtml = this.getTagsHtml('style');
const linksHtml = this.getTagsHtml('link');

const popupWin = window.open('', '_blank', 'top=0,left=0,height=100%,width=auto');
popupWin.document.open();
popupWin.document.write(`
    <html>
        <head>
            <title>Print tab</title>
            ${linksHtml}
            ${stylesHtml}
            ^^^^^^^^^^^^^ add them as usual to the head
        </head>
        <body onload="window.print(); window.close()">
            ${printContents}
        </body>
    </html>
    `
);
popupWin.document.close();

现在使用现有样式(Angular组件会为其本身创建预设样式)以及现有样式框架(例如Bootstrap,MaterialDesign,Bulma),它看起来应该像是现有屏幕的一小段

答案 4 :(得分:1)

Print service

import { Injectable } from '@angular/core';

@Injectable()
export class PrintingService {

public print(printEl: HTMLElement) {
    let printContainer: HTMLElement = document.querySelector('#print-container');

    if (!printContainer) {
      printContainer = document.createElement('div');
      printContainer.id = 'print-container';
    } 

    printContainer.innerHTML = '';

    let elementCopy = printEl.cloneNode(true);
    printContainer.appendChild(elementCopy);
    document.body.appendChild(printContainer);

    window.print();
  }
}

Сomponent that I want to print

@Component({
  selector: 'app-component',
  templateUrl: './component.component.html',
  styleUrls: ['./component.component.css'],
  encapsulation: ViewEncapsulation.None
})
export class MyComponent {
  @ViewChild('printEl') printEl: ElementRef;

  constructor(private printingService: PrintingService) {}

  public print(): void {
    this.printingService.print(this.printEl.nativeElement);
 }

}

Not the best choice, but works.

答案 5 :(得分:1)

我遇到了同样的问题,并找到了另一种解决方法。就我而言,它是相对较小的应用程序。

首先,用户将在需要打印的组件中单击一个按钮。这将设置一个可由应用程序组件访问的标志。像这样

.html文件

<button mat-button (click)="printMode()">Print Preview</button>

.ts文件

  printMode() {
    this.utilities.printMode = true;
  }

在应用程序组件的html中,我们隐藏了路由器出口以外的所有内容。像下面这样

<div class="container">       
  <app-header *ngIf="!utilities.printMode"></app-header>
  <mat-sidenav-container>
    <mat-sidenav *ngIf="=!utilities.printMode">
      <app-sidebar></app-sidebar>
    </mat-sidenav>
    <mat-sidenav-content>
      <router-outlet></router-outlet>
    </mat-sidenav-content>
  </mat-sidenav-container>
</div>

使用类似的ngIf条件,我们还可以调整组件的html模板以仅在printMode中显示或隐藏内容。这样,当单击打印预览时,用户将仅看到需要打印的内容。

我们现在可以使用以下代码简单地打印或返回正常模式

.html文件

<button mat-button class="doNotPrint" (click)="print()">Print</button>
<button mat-button class="doNotPrint" (click)="endPrint()">Close</button>

.ts文件

  print() {
    window.print();
  }

  endPrint() {
    this.utilities.printMode = false;
  } 

.css文件(这样就不会打印“打印”和“关闭”按钮)

@media print{
   .doNotPrint{display:none !important;}
 }

答案 6 :(得分:0)

我发现解决这个问题的最佳选择是在我的打印输出中使用单独的路线并将此路线加载到iframe中。

我的周围组件显示为标签页。

AndorCameraSDK

iframe只会加载在应用中呈现打印组件的打印路径。在此页面中,视图完全初始化后可能会触发打印。另一种方法可能是父组件上的打印按钮,它通过@Component({ template: '<iframe id="printpage" name="printpage" *ngIf="printSrc" [src]="printSrc"></iframe>', styleUrls: [ 'previewTab.scss' ] }) export class PreviewTabPage { printSrc: SafeUrl; constructor( private navParams: NavParams, private sanitizer: DomSanitizer, ) { // item to print is passed as url parameter const itemId = navParams.get('itemId'); // set print page source for iframe in template this.printSrc = this.sanitizer.bypassSecurityTrustResourceUrl(this.getAbsoluteUrl(itemId)); } getAbsoluteUrl(itemId: string): string { // some code to generate an absolute url for your item return itemUrl; } } 触发iframe上的打印。

window.frames["printpage"].print();

答案 7 :(得分:0)

Windows应用程序通常具有内置打印功能,但是对于Web应用程序,我会选择简单地生成PDF文件。

我发现的最简单的方法是使用PDFMake(www.pdfmake.org)生成PDf文件。然后,您可以为用户提供打开或下载生成的PDF文件的选择。

答案 8 :(得分:0)

将窗口分配给Typescript变量的最短解决方案,然后在其上调用print方法,如下所示

在模板文件中

<button ... (click)="window.print()" ...>Submit</button>

,并在打字稿文件中

window: any;
constructor() {
  this.window = window;
}

答案 9 :(得分:0)

使用库ngx-print

安装:

yarn add ngx-print
or
npm install ngx-print --save

更改模块:

import {NgxPrintModule} from 'ngx-print';
...
imports: [
    NgxPrintModule,
...

模板:

<div id="print-section">
  // print content
</div>
<button ngxPrint printSectionId="print-section">Print</button>

More details

答案 10 :(得分:0)

如果需要打印一些自定义HTML,可以使用以下方法:

ts:

    let control_Print;

    control_Print = document.getElementById('__printingFrame');

    let doc = control_Print.contentWindow.document;
    doc.open();
    doc.write("<div style='color:red;'>I WANT TO PRINT THIS, NOT THE CURRENT HTML</div>");
    doc.close();

    control_Print = control_Print.contentWindow;
    control_Print.focus();
    control_Print.print();

html:

<iframe title="Lets print" id="__printingFrame" style="width: 0; height: 0; border: 0"></iframe>