web-dev-qa-db-fra.com

Imprimer un modèle HTML sous Angular 2 (ng-print sous Angular 2)

Je veux imprimer le modèle HTML dans angular 2. Je l'avais expliquée à ce sujet. J'ai trouvé la solution dans angularjs 1 Print Html Template in Angularjs 1

Toute suggestion serait appréciée

41
Neeraj Rathod

C'est comme ça que je l'ai fait dans angular2 (c'est similaire à celle ) (dans la solution) Dans votre fichier HTML:

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

et dans votre fichier 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();
}

MISE À JOUR:

Vous pouvez également raccourcir le chemin et utiliser simplement la bibliothèque ngx-print pour un codage moins incohérent (mélange de JS et de TS) et davantage contrôlable et prêt à l'emploi, et cas d'impression sécurisée.

78
selem mn

Si quelqu'un d'autre rencontre ce problème, si vous avez déjà posé la page, je vous recommande d'utiliser des requêtes de support pour configurer votre page d'impression. Vous pouvez ensuite simplement attacher une fonction d'impression à votre bouton html et à votre appel de composant window.print ();

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

composant.ts:

onPrint(){
    window.print();
}

composant.css:

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

Vous pouvez éventuellement ajouter d'autres éléments/sections que vous ne souhaitez pas imprimer dans la requête multimédia.

Vous pouvez également modifier les marges du document et tous les éléments de la requête d'impression, ce qui la rend assez puissante. Il y a beaucoup d'articles en ligne. En voici un qui semble complet: https://www.sitepoint.com/create-a-customized-print-stylesheet-in-minutes/ Cela signifie également que vous n'avez pas besoin de créer un script pour créer une "version imprimée" de la page ou utiliser beaucoup de javascript.

18
Farasi78

vous pouvez faire comme ceci dans angular 2

dans son fichier

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

 }

en 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>
10
Vikash Dahiya

EDIT: mis à jour les extraits pour une approche plus générique

Juste comme une extension de la réponse acceptée,

Pour que les styles existants préservent l'aspect du composant ciblé, vous pouvez:

  1. effectuer une requête pour extraire les éléments <style> et <link> du document de niveau supérieur.

  2. l'injecter dans la chaîne HTML.

Pour récupérer une balise 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');
}

Puis dans l'extrait de code existant:

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

Maintenant, en utilisant les styles existants (les composants angulaires créent un style créé pour eux-mêmes), ainsi que les frameworks de style existants (par exemple, Bootstrap, MaterialDesign, Bulma), il devrait ressembler à un extrait de l'écran existant.

4

Service d'impression

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

Composant que je veux imprimer

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

}

Pas le meilleur choix, mais ça marche.

1
Kliment Ru

J'ai rencontré le même problème et j'ai trouvé un autre moyen de le faire. Cela a fonctionné dans mon cas car il s'agissait d'une application relativement petite.

Tout d'abord, l'utilisateur cliquera sur le composant à imprimer. Cela définira un indicateur auquel le composant de l'application peut accéder. Ainsi

fichier .html

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

fichier .ts

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

Dans le code HTML du composant de l'application, nous masquons tout sauf le routeur-prise. Quelque chose comme ci-dessous

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

Avec des configurations ngIf similaires, nous pouvons également ajuster le modèle HTML du composant pour afficher ou masquer uniquement les éléments en mode printMode. De sorte que l'utilisateur ne voit que ce qui doit être imprimé lorsque vous cliquez sur l'aperçu avant impression.

Nous pouvons maintenant simplement imprimer ou revenir en mode normal avec le code ci-dessous

fichier .html

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

fichier .ts

  print() {
    window.print();
  }

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

Fichier .css (pour que les boutons d'impression et de fermeture ne soient pas imprimés)

@media print{
   .doNotPrint{display:none !important;}
 }
1
Bharat Raj Saya

La meilleure option que j'ai trouvée pour résoudre ce problème sans me poser de problèmes de style consistait à utiliser un itinéraire séparé pour ma sortie imprimée et à charger cet itinéraire dans un iframe.

Mon composant environnant est affiché sous forme de page à onglet.

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

L'iframe charge simplement l'itinéraire d'impression qui restitue un composant d'impression dans l'application. Dans cette page, l’impression peut être déclenchée après l’initialisation complète de la vue. Une autre façon pourrait être un bouton d'impression sur le composant parent qui déclenche l'impression sur l'iframe par window.frames["printpage"].print();.

@Component({
  templateUrl: './print.html',
  styleUrls: [ 'print.scss' ]
})
export class PrintPage implements AfterViewInit {

  constructor() {}

  ngAfterViewInit() {
    // wait some time, so all images or other async data are loaded / rendered.
    // print could be triggered after button press in the parent component as well.
    setTimeout(() => {
      // print current iframe
      window.print();
    }, 2000);
  }

}
0
Dave Gööck

Utilisez la bibliothèque ngx-print .

Installation:

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

Changez votre module:

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

Modèle:

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

Plus de détails

0
progm

La solution la plus courte est d’affecter la fenêtre à une variable TypeScript, puis d’appeler la méthode d’impression, comme ci-dessous

dans un fichier modèle

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

et, dans un fichier TypeScript

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

Les applications Windows sont généralement livrées avec une fonctionnalité d'impression intégrée, mais pour une application Web, je choisirais simplement de générer un fichier PDF.

Le moyen le plus simple que j'ai trouvé est de générer un fichier PDf à l'aide de PDFMake (www.pdfmake.org). Vous pouvez ensuite offrir à l'utilisateur le choix d'ouvrir ou de télécharger le fichier PDF généré.

0
Edwin Teisman