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

IT技术 javascript angularjs angular
2021-01-30 15:52:58

我想在 angular 2 中打印 HTML 模板。我对此进行了探索,我在 angularjs 1 中得到了解决方案 在 Angularjs 1 中打印 Html 模板

任何建议将不胜感激

6个回答

这就是我在 angular2 中所做的(它类似于那个笨拙的解决方案)在您的 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();
}

更新:

您还可以缩短路径并仅使用ngx-print库来减少不一致的编码(混合 JS 和 TS)和更多开箱即用的可控和安全打印案例。

@amit 实际上我没有想过。
2021-03-16 15:52:58
@selemmn 我花了很多时间试图弄清楚但没有成功。如果你找到了方法,我很想知道
2021-03-24 15:52:58
@selemmn 这有点难,因为它是一个复杂的 angular 2 项目,包含许多组件和许多样式...
2021-03-29 15:52:58
如果 printContents 出现在原始站点屏幕中,是否可以轻松包含样式?
2021-04-05 15:52:58
@amit 你能为你的问题提供一个plunker吗?
2021-04-09 15:52:58

万一其他人遇到这个问题,如果您已经布置了页面,我建议使用媒体查询来设置您的打印页面。然后您可以简单地将打印功能附加到您的 html 按钮并在您的组件中调用 window.print();

组件.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>

组件.ts:

onPrint(){
    window.print();
}

组件.css:

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

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

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

您还可以使用来自 css 的 :not() 选择器,因此,仅在将要打印的元素上使用一个类。示例:<div class="print_this"> 打印内容 </div> 然后在 css 文件上:@media print{ :not(.print_this){display:none;!important} }
2021-03-15 15:52:58
我试图打印一个有 50 列的表格,但在打印文档模板上它只显示 20 列,其余的都是隐藏的。你能帮我解决这个问题并在单行中显示整个表格的列吗?
2021-03-25 15:52:58
@Farasi78 确实有效,但不完全有效。我创建了一个指令来打印应用的潜水内容,但打印有点奇怪。顺便谢谢你的帮助,至少我进步了。
2021-04-05 15:52:58
@LucaEffeFederzoni 我相信无论您的层次结构如何,只要您适当地标记每个 div,它都可以工作。即在 DashboardComponent 中,将所有不应打印的内容标记为“不打印”,这可能会变得有点复杂,在这种情况下,您可能想要按照其他人的建议创建单个页面进行打印。如果您使用 Angular,为了避免重复 CSS,请将不打印规则放在您的 app.component.css 中,并将其添加到您需要的每个组件的 styleUrls 中。
2021-04-11 15:52:58
我如何使用它来打印子子 div 的内容?从层次上讲,我有这种情况:MainComponent > DashboardComponent > DivToPrint。这是一个路由器sockets链。我如何设置它以使用此@media 查询?
2021-04-13 15:52:58

你可以在 angular 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();
  }

 }

在 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>
你的答案需要一些更正,你非常接近。感谢您的快速回复,我赞成答案:)
2021-03-24 15:52:58
其实我没有测试就给出了这个答案,我会尽快更新
2021-03-27 15:52:58
@VikashDahiya 先生,我使用了上面的代码,但我在 line-window.open 中收到了 null 返回的 null..
2021-03-30 15:52:58
我已经更新了它,它对我有用。测试一下,如果需要进行更正
2021-04-10 15:52:58
如果我在 text 中输入任何文本,则不会打印
2021-04-13 15:52:58

编辑:更新了更通用的方法的片段

正如已接受答案的扩展一样,

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

  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)它应该看起来像现有屏幕的片段

打印服务

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();
  }
}

我要打印的组件

@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);
 }

}

不是最好的选择,但有效。

不要忘记添加 css @media 打印并使用显示和可见性使上述代码有效
2021-03-26 15:52:58
这不是要打印整个页面而不是突出该元素吗?
2021-03-28 15:52:58