0

New window doesn't recognize the app (see ) component won't be recognized

new-window.component.ts

@Component({
  selector: 'app-new-window',
  template: `
    <h1>New Window Component</h1>
  `,
})
export class NewWindowComponent {
  // component logic
}

open-window.component.ts

@Component({
  selector: 'app-open-window',
  template: `
    <button (click)="openNewWindow()">Open New Window</button>
  `,
})
export class OpenWindowComponent {
 private newWindow: Window | null = null;

  openNewWindow() {
    // Open a new browser window
    this.newWindow = window.open('', '_blank');

    if (this.newWindow) {
      this.newWindow.document.open();
      this.newWindow.document.write('<app-root></app-root>');
      this.newWindow.document.close();
    }
  }

  ngOnDestroy() {
    // Close the new window when the component is destroyed
    if (this.newWindow) {
      this.newWindow.close();
    }
  }
}

How can I pass the new component in the new window and display the content of it ("New Window Component")

Stefan
  • 50
  • 1
  • 10

1 Answers1

0

Found the solution:

Following component will serve as a container. new-window-container.component.ts

@Component({
  selector: 'app-new-window-container',
  template: '',
})
export class NewWindowContainerComponent {
}

new-window.service.ts

@Injectable({
  providedIn: 'root',
})
export class NewWindowService {
  constructor(
    private componentFactoryResolver: ComponentFactoryResolver,
    private appRef: ApplicationRef,
    private injector: Injector
  ) {}

  openNewWindow(component: any): Window | null {
    const newWindow = window.open('', '_blank');
    if (!newWindow) {
      return null;
    }

    const componentFactory = this.componentFactoryResolver.resolveComponentFactory(component);
    const componentRef = componentFactory.create(this.injector);

    this.appRef.attachView(componentRef.hostView);

    const newWindowContainerElement = newWindow.document.createElement('app-new-window-container');
    newWindow.document.body.appendChild(newWindowContainerElement);

    const componentRootNode = (componentRef.hostView as EmbeddedViewRef<any>).rootNodes[0] as HTMLElement;
    newWindowContainerElement.appendChild(componentRootNode);

    return newWindow;
  }
}

Use the NewWindowService in a component where you want to trigger the opening of the new window.

app.component.ts:

@Component({
  selector: 'app-root',
  template: `
    <button (click)="openNewWindow()">Open New Window</button>
  `,
})
export class AppComponent {
  constructor(private newWindowService: NewWindowService) {}

  openNewWindow() {
    this.newWindowService.openNewWindow(NewWindowComponent);
  }
}

With the component factory, you can create a component instance using

componentFactory.create(this.injector)

. The Injector is responsible for providing the necessary dependencies for the component.

The ApplicationRef is used to attach the component to the application's view tree using

appRef.attachView(componentRef.hostView)

. This step is crucial for change detection and rendering.

Stefan
  • 50
  • 1
  • 10