Angular component in a Browser's child window

試著忘記壹切 提交于 2019-11-30 14:43:41

问题


From an Angular application is there any way that I can create a Browser's child window and show some predefined angular component in it.

Clarification : I am not looking for a Modal dialog solution.


回答1:


In case you are using window.open for the child window in order to show an angular component that window should load a website which uses angular this means you eighter create in your own app a child route special for that page and you open your own app to that specific route. If you chose this solution be aware of the size of your app this solution works fine if you use async routing so when you open the app on a new window you will download angular + other core libs which you are using and + js for that specific route.

Another option is that in your server you create another angular app with only that content and you have 2 apps on the same server served at different url's in that case you need to create a new angular app which contains only that specific content




回答2:


This is what i have found for myself, and does exactly what you need.

https://stackblitz.com/edit/angular-open-window

It is possible to show your custom angular components in the new child window, and any angular services will also be injected in any component that is shown in the child window.

It defines a new WindowComponent, which contains a portal host. This portal host is attached to the body of the child window. This means that any portals attached to the portal host will be rendered to the body of the child window. To the portal host is passes the componentFactoryResolver, the applicationRef and the injector, presumably so that it can initialize your custom angular components and inject the required services inside the child window.

const host = new DomPortalHost(
    this.externalWindow.document.body,
    this.componentFactoryResolver,
    this.applicationRef,
    this.injector
);

In the template of the WindowComponent, it defines a portal using *cdkPortal. Inside the portal, it projects the window component's content, as defined by the parent of the window content, using ng-content.

<ng-container *cdkPortal>
  <ng-content></ng-content>
</ng-container>

Whenever the WindowComponent is created, it will open a child window, and attach its portal to the portal host. When the WindowComponent is destroyed, it will close the child window.

  ngOnInit(){
    // STEP 4: create an external window
    this.externalWindow = window.open('', '', 'width=600,height=400,left=200,top=200');

    // STEP 5: create a PortalHost with the body of the new window document    
    const host = ...

    // STEP 6: Attach the portal
    host.attach(this.portal);
  }

  ngOnDestroy(){
    // STEP 7: close the window when this component destroyed
    this.externalWindow.close()
  }

This means that in the application component you can simply toggle the popup using the *ngIf directive on your window component, and nest any content you want to show in the template.

<window *ngIf="showPortal">
  <h2>Hello world from another window!!</h2>
  <button (click)="this.showPortal = false">Close me!</button>
</window>

Using the @angular/cdk package you could also modify this example to create a child window programmatically, by using a ComponentPortal instead of retrieving a CdkPortal with the @ViewChild decorator. By retrieving a reference to the portal host, you can even programmatically replace content of the child window with a different component. When attaching a portal to a portal host, you can also get a ComponentRef for your instantiated component, allowing you to interact with it from code.




回答3:


I landed in this post before, so in case someone still trying to render a component dynamically loaded on a differrent windows without running a new app, this is how I did it:

    export class ChildLoaderComponent implements OnInit, AfterViewInit {
      constructor(private r: ComponentFactoryResolver, private viewContainerRef: ViewContainerRef) {}
    public windowReference: any;
      ngAfterViewInit() {
        setTimeout(() => {
        //create the component dynamically
        const factory = this.r.resolveComponentFactory(AChildComponent);
        const comp: ComponentRef<AChildComponent> = 
        this.viewContainerRef.createComponent(factory);
        //in case you also need to inject an input to the child, 
        //like the windows reference 
        comp.instance.someInputField = this.windowReference.document.body;
        //add you freshly baked component on the windows
        this.windowReference.document.body.appendChild(comp.location.nativeElement);
      });
    }

    ngOnInit() {
      //create the windows and save the reference       
      this.windowReference = window.open('', '_blank', 'toolbar=0,width=800,height=400');
    }
   }



回答4:


Create lazy load component (as url) and put your url in

window.open('url', 'window name', 'settings')



回答5:


You can do that using a link with the target="_blank" attribute

example.component.html

<a [routerLink]="['/route-to-your-component']" target="_blank">
  Open the component in a new tab
</a>



回答6:


You can try giving names to your different windows. This will open each new window with the specified name.

window.open('url', 'window 1', '');
window.open('url', 'window 2', '');


来源:https://stackoverflow.com/questions/53646015/angular-component-in-a-browsers-child-window

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!