0
votes

I have one application in angular 4. There are 4 tabs('tab1','tab2','tab3','tab4') on the screen. Each tab is associated with a angular component which is being loaded dynamically.

When user lands on the landing page, 'tab1' is displayed by default. There is menu control where we have a print button. On click of this print button, i have to print all the tabs.

Following is what I have done. Given 'id' to all the angular components which are loaded dynamically. used document.getElementByID('tab1').innerHtml to get innet html. concatenated all html for all the tabs.

Following is being call on print button click:- popupWin = window.open('', '_blank', 'width=' + screen.availWidth + ',height=' + screen.availHeight); popupWin.document.open(); popupWin.document.write(this.renderFullHtmlForPrintingReport(htmlStringToPrint)); [variable 'htmlStringToPrint' has all the html from all the tabs.]

popupWin.document.close();

Following is the method implementation for rending html for print:-

renderFullHtmlForPrintingReport(printContents: string): string {
    return `
    <html>
    <head>
      <title>Print tab</title>
      <link rel="stylesheet" href="assets/bootstrap.css">
      <link rel="stylesheet" href="assets/site.css">
    </head>
    <body><div style="padding-left:10px">${printContents}</div></body>
  </html>`
  //<body onload="window.print();window.close();"><div style="padding-left:10px">${printContents}</div></body>
  }

Code for tabs:-

 <tabset>
      <tab *ngFor="let tab of tabs; let i = index" [heading]="tab.title" [active]="tab.active" (select)="tab.active = true" (deselect)="tab.active = false"
        [disabled]="tab.disabled" [sClass]="tab.sClass" id="{{i}}">
        <br>
        <dyna [type]="tab.tabContent" [language]="language" ></ddyna>
      </tab>
    </tabset>

is an angular component in which a component is loaded dynamically.

Following is the method for creating tabs:-

public tabs: ITab[] = [
    { title: 'B', tabContent: BComponent, templateNum: 0, sClass: "show-class", active: true },
    { title: 'O', tabContent: OComponent, templateNum: 1, sClass: "show-class", active: false },
    { title: 'P', tabContent: PComponent, templateNum: 2, sClass: "show-class", active: false },
    { title: 'BR', tabContent: BrComponent, templateNum: 3, sClass: "show-class", active: false },
    { title: 'FR', tabContent: FrComponent, templateNum: 4, sClass: "show-class", active: false }
  ];

When print button is clicked, a new dialogue displays the html but the html is not having the binded control values from various controls. It seems like default template of the angular components is being displayed.

I can use the ViewChild and cache the html using a shared service but for every change on the page, I need to update the cache.

Any inputs for the solution would help.

best regards, AKing

1

1 Answers

0
votes

This depends on exactly how you're paginating your tabs -- if I assume you're using something like Angular Material, the not-displayed tabs aren't actually rendered until they need to be shown. Similarly, if you're using the Router and an outlet on each of the tabs, Angular will not create the template and binding until that outlet is active, i.e. needs to be shown.

Template and component bindings are not resolved until component creation. There's ways around this, but most aren't considered good practice. Angular also does a lot to separate the DOM API from your code, so a lot of times trying to get around this leads to unpredictable results.

It's hard to give a good solution to this without knowing how these tabs are being managed and rendered, but you could go through each tab on print, render its contents, separate them via CSS print media queries, and print. That wouldn't look too great to the user though, so another solution is to use a separate page entirely -- one that accepts some sort of parameter and renders each tab on a new page un-tabbed (all on one page), and then prints that page.

It wouldn't be too hard to implement -- just make a route to it that accepts the parameter and then put each tab component how you'd need it to be arranged. Updates to the components will automatically reflect on this new route.

You can also use directives to grab the Template of each tab, render it with inputs via the ComponentFactoryResolver, organize the content how you need it, and print that way. Vague explanation, I know, but without knowing more about your app, it's hard to give a good answer.