浏览器子窗口中的角度组件

Shr*_*key 14 browser components childwindow angular angular6

从Angular应用程序中可以创建浏览器的子窗口并在其中显示一些预定义的角度组件.

澄清:我不是在寻找模态对话解决方案.

Row*_*Arg 8

我之前登陆过这篇文章,所以如果有人仍然试图在不运行新应用程序的情况下在不同的窗口上呈现动态加载的组件,我就是这样做的:

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');
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 这是很久以前的事了,但是你们尝试过这样的方法来解决样式问题: `document.querySelectorAll('link, style').forEach((htmlElement) =&gt; { if (this.windowReference) { ​this.windowReference .document.head.appendChild(htmlElement.cloneNode(true)); } });` 这样您就可以将样式附加到窗口中,并且它们应该加载。 (2认同)

Bub*_*rap 6

这是我为自己找到的,并且正是您所需要的。

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

可以在新的子窗口中显示您的自定义 angular 组件,并且任何 angular 服务也将注入到子窗口中显示的任何组件中。

它定义了一个 new WindowComponent,其中包含一个门户主机。此门户主机附加到子窗口的主体。这意味着附加到门户主机的任何门户都将呈现到子窗口的主体。向门户主机传递componentFactoryResolverapplicationRefinjector,大概是为了它可以初始化您的自定义角度组件并在子窗口内注入所需的服务。

const host = new DomPortalHost(
    this.externalWindow.document.body,
    this.componentFactoryResolver,
    this.applicationRef,
    this.injector
);
Run Code Online (Sandbox Code Playgroud)

在 的模板中WindowComponent,它使用*cdkPortal. 在门户内部,它使用ng-content.

<ng-container *cdkPortal>
  <ng-content></ng-content>
</ng-container>
Run Code Online (Sandbox Code Playgroud)

无论何时WindowComponent创建,它都会打开一个子窗口,并将其门户附加到门户主机。当WindowComponent被销毁时,它将关闭子窗口。

  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()
  }
Run Code Online (Sandbox Code Playgroud)

这意味着在应用程序组件中,您可以使用*ngIf窗口组件上的指令简单地切换弹出窗口,并在模板中嵌套要显示的任何内容。

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

使用@angular/cdk 包,您还可以修改此示例以通过使用 aComponentPortal而不是使用装饰器检索 aCdkPortal以编程方式创建子窗口@ViewChild。通过检索对门户主机的引用,您甚至可以以编程方式将子窗口的内容替换为不同的组件。将门户附加到门户主机时,您还可以获得ComponentRef实例化组件的 ,允许您通过代码与其交互。

  • 这看起来是一个非常干净和好的解决方案,但我遇到了以下问题: 1. 新窗口中没有应用任何 CSS 样式。甚至不是应用程序范围内的风格的东西。2. 如果我在新浏览器弹出窗口中打开模块化弹出窗口,则该模块化弹出窗口将在原始浏览器窗口中打开。我使用 MatDialog 作为模块化弹出窗口。任何对此的帮助将不胜感激。 (3认同)
  • 我尝试了您的解决方案,但是当我关闭弹出窗口并再次单击“打开我”时,它没有显示? (3认同)

Nic*_*icu 5

如果您正在使用window.open子窗口以显示该窗口应加载的website使用角度的角组件,这意味着您将在自己的应用中为该页面专门创建一个子路由,然后打开自己的应用以使用该特定路由。如果你选择了这个解决方案要知道你的应用程序的大小,如果你当你打开一个新窗口的应用程序中使用异步路由所以这个解决方案正常工作,你会下载angular+ other core libs 你正在使用和+ js for that specific route

另一个选择是,在您的服务器中创建一个仅包含该内容的Angular应用程序,并且在同一服务器上有两个应用程序以不同的URL进行服务,在这种情况下,您需要创建一个仅包含特定内容的新Angular应用程序


Pra*_*lge 1

您可以尝试为不同的窗口命名。这将打开具有指定名称的每个新窗口。

window.open('url', 'window 1', '');
window.open('url', 'window 2', '');
Run Code Online (Sandbox Code Playgroud)