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