简体   繁体   English

如何在 Angular 中打印单个组件?

[英]How can I print a single component in Angular?

In a single angular component I wish have a print button which when the user clicks, will print a single div from my component's template.在单个角度组件中,我希望有一个打印按钮,当用户单击该按钮时,它将从我的组件模板中打印一个div

I know this answer works, I've tried it.我知道这个答案有效,我已经尝试过了。 But I do not like how I need to reapply all styles or rewrite all the styles in the <style> head tags.但我不喜欢我需要重新应用所有样式或重写<style>头标签中的所有样式。

I really like this answer but I can't get it to work.我真的很喜欢这个答案,但我无法让它发挥作用。 I think it might have something to do with how classes are renamed after the app has been served/built.我认为这可能与在服务/构建应用程序后如何重命名类有关。

This is how I've implemented the above answer but can't get it to work.这就是我实现上述答案但无法使其工作的方式。

component.ts组件.ts

onPrint() {
  window.print();
}

component.html组件.html

<div class="print">
  <button (click)="onPrint()">Print</button>
  all the stuffs I want to print
</div>

component.scss组件.scss

@media print {
  :not(.print) {
    display: none !important;
  }
}

How can I get the above answer to work resulting as little code as possible, and retaining the styles applied to the front-end?我怎样才能得到上述答案以尽可能少地工作,并保留应用于前端的样式?

I realize how similar the question is to this one but this question was asked almost two years ago and with regards to angular 2. Not quite sure how different it is with regards to angular 6.我意识到这个问题与这个问题有多么相似,但这个问题是在大约两年前提出的,关于角度 2。不太确定它与角度 6 有多大不同。

The styles in the component CSS will only apply to that individual component, which is why the parent component mat tabs are still showing.组件 CSS 中的样式仅适用于该单个组件,这就是仍显示父组件 mat 选项卡的原因。

As an alternative, you can add the styles into style.css / styles.scss .作为替代方案,您可以将样式添加到style.css / styles.scss中。 The problem with this is that the parent DOM elements (such as body ) will be set to display: none as well, so nothing will be visible.这样做的问题是父 DOM 元素(例如body )将被设置为display: none ,所以什么都不可见。

You can instead try using visibility in styles.css like so:您可以尝试在styles.css使用visibility ,如下所示:

@media print {
  :not(.printMe) {
    visibility: hidden;
  }
}

@media print {
  .printMe {
    visibility: visible
  }
}

Depending on your use case, this may help, although the hidden elements will still take up space on the page.根据您的用例,这可能会有所帮助,尽管hidden的元素仍会占用页面上的空间。

Here is a fork of the StackBlitz to demonstrate 这是 StackBlitz 的一个分支来演示

A simple solution might be to display the div over the page content:一个简单的解决方案可能是在页面内容上显示div

@media print {
 .print {
    position: fixed;

    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
  }
}

<div [AppendToPrint]="true">
</div>

each element have AppendToPrint directive will show in print window after call this function调用此函数后,每个具有 AppendToPrint 指令的元素将显示在打印窗口中

window.print();窗口.打印();

@Directive({
  selector: '[AppendToPrint]'
})
export class AppendToPrintDirective implements AfterViewInit {

  private elementIdToPrint: string = 'print';

  isPrinted: boolean = true;
  clone;

  @Input("AppendToPrint")
  set appendToPrint(value: boolean) {
    this.isPrinted = value;
  }


  constructor(private elRef: ElementRef) {
  }

  ngAfterViewInit(): void {
    
    this.cloneElement();

    if (document.getElementById(this.elementIdToPrint)) {

      document.getElementById(this.elementIdToPrint).appendChild(this.clone);
    }
  }
  
  cloneElement(): void {
    this.clone = this.elRef.nativeElement.cloneNode(true);
  }

  ngOnChanges() {
    if (this.isPrinted) {
      this.resetPrint();
    }
    else {
      this.cloneElement();
        document.getElementById(this.elementIdToPrint).innerHTML = '';
        document.getElementById(this.elementIdToPrint).appendChild(this.clone);
      }
  
  }

  //#region == private methods ==

  private resetPrint(): void {
    document.getElementById(this.elementIdToPrint).innerHTML = '';
    this.isPrinted = false;
  }

  ///#endregion
}

The only way that worked for me was to hide all elements aside from the one I am printing.对我有用的唯一方法是隐藏我正在打印的元素之外的所有元素。 Copying the HTML into a new window (and similar solutions) didn't work for me because of style issues.由于样式问题,将 HTML 复制到新窗口(和类似的解决方案)对我不起作用。

The following code requires jQuery to work.以下代码需要 jQuery 才能工作。

print(triggerElement): void
{
    const toShow = this.hideParentSiblings($('#print-section'));
    $(triggerElement).hide();

    window.print();

    for (const e of toShow)
    {
        e.show();
    }

    $(triggerElement).show();
}

hideParentSiblings(element): any[]
{
    let parent;
    const toShow = [];

    while ((parent = element.parent()).length)
    {
        const visible = parent.siblings().find(':visible');
        toShow.push(visible);
        visible.hide();
        element = parent;
    }

    return toShow;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM