简体   繁体   中英

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.

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.

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

onPrint() {
  window.print();
}

component.html

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

component.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.

The styles in the component CSS will only apply to that individual component, which is why the parent component mat tabs are still showing.

As an alternative, you can add the styles into 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.

You can instead try using visibility in styles.css like so:

@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.

Here is a fork of the StackBlitz to demonstrate

A simple solution might be to display the div over the page content:

@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

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.

The following code requires jQuery to work.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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