Search code examples
htmlangularangular-components

Open an angular template reference in a new browser window


So here is the explanation of the problem I am facing. It might look very similar other already asked questions, but none of them answered my problem.

I want to open an angular template reference in a new browser window (with all the styles) and use that window to print the contents using system print dialog.

By template reference I mean a whole component or may be just a fraction of template of given component.

Please note that I do not want to do it by below methods:

  1. Opening a new route in a new browser window. (Why? this will cause all other things like common toolbar or help open up with the component. Also a new route will be required which is undesired.)
  2. Opening the content in a closable modal.

Solution

  • Ok, This is how I did it using ComponentFactoryResolver and Injector. Just inject these two dependencies in your component which wants to open other component (ReportComponent in this case) in new browser window.

    The constructor looks something like this in snippet below.

      constructor(
        private resolver: ComponentFactoryResolver,
        private injector: Injector
      ) {}
    

    . . .

    This method opens up the component in new browser window.

    public openPrintableReport(): void {
    
    // resolve and instantiate the component which you want to open in new window. 
    const componentFactory = this.resolver.resolveComponentFactory(ReportComponent);
    let component = componentFactory.create(this.injector);
    component.changeDetectorRef.detectChanges();
    
    // define external window
    this.externalWindow = window.open('', '', 'width=1000,height=1000,left=150,top=200');
    
    // copy all the styles to external window.
    document.querySelectorAll('style').forEach(htmlElement => {
      this.externalWindow.document.head.appendChild(htmlElement.cloneNode(true));
    });
    
    this.externalWindow.document.title = 'Printer Friendly Report';
    
    // attach the component to external window
    this.externalWindow.document.body.appendChild(component.location.nativeElement);
    }