Угловой компонент в дочернем окне браузера
Из приложения Angular есть какой-нибудь способ, которым я могу создать дочернее окно браузера и показать в нем некоторый предопределенный угловой компонент.
Пояснение: я не ищу модальное диалоговое решение.
5 ответов
Я попал в этот пост ранее, поэтому, если кто-то все еще пытается визуализировать компонент, динамически загружаемый в разных окнах без запуска нового приложения, я сделал это так:
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');
}
}
Это то, что я нашел для себя, и делает именно то, что вам нужно.
https://stackblitz.com/edit/angular-open-window
Можно показать свои пользовательские компоненты angular в новом дочернем окне, и любые службы angular также будут внедрены в любой компонент, который отображается в дочернем окне.
Он определяет новый WindowComponent
, который содержит узел портала. Этот хост портала прикреплен к телу дочернего окна. Это означает, что любые порталы, подключенные к хосту портала, будут отображаться в теле дочернего окна. Хосту портала передаетсяcomponentFactoryResolver
, то applicationRef
и injector
, предположительно, чтобы он мог инициализировать ваши пользовательские компоненты angular и внедрять необходимые службы внутри дочернего окна.
const host = new DomPortalHost(
this.externalWindow.document.body,
this.componentFactoryResolver,
this.applicationRef,
this.injector
);
В шаблоне WindowComponent
, он определяет портал, используя *cdkPortal
. Внутри портала он проецирует содержимое компонента окна, как определено родителем содержимого окна, используяng-content
.
<ng-container *cdkPortal>
<ng-content></ng-content>
</ng-container>
Когда бы 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()
}
Это означает, что в компоненте приложения вы можете просто переключать всплывающее окно с помощью *ngIf
в вашем оконном компоненте и вложите любой контент, который вы хотите показать в шаблоне.
<window *ngIf="showPortal">
<h2>Hello world from another window!!</h2>
<button (click)="this.showPortal = false">Close me!</button>
</window>
Используя пакет @angular/cdk, вы также можете изменить этот пример, чтобы программно создать дочернее окно, используя ComponentPortal
вместо получения CdkPortal
с @ViewChild
декоратор. Получив ссылку на хост портала, вы даже можете программно заменить содержимое дочернего окна другим компонентом. При подключении портала к хосту портала вы также можете получитьComponentRef
для вашего экземпляра компонента, позволяя вам взаимодействовать с ним из кода.
Если вы используете window.open
для дочернего окна, чтобы показать угловой компонент, это окно должно загрузить website
в котором используется angular, это означает, что вы можете создать в своем приложении дочерний маршрут, специально предназначенный для этой страницы, и открыть свое приложение для этого конкретного маршрута. Если вы выбрали это решение, знайте о размере вашего приложения, это решение работает нормально, если вы используете асинхронную маршрутизацию, поэтому при открытии приложения в новом окне вы загрузите angular
+ other core libs
который вы используете и + js for that specific route
,
Другой вариант заключается в том, что на вашем сервере вы создаете другое угловое приложение, содержащее только этот контент, и у вас есть 2 приложения на одном сервере, которые обслуживаются по разным URL-адресам. В этом случае вам нужно создать новое угловое приложение, которое содержит только этот конкретный контент.
Вы можете сделать это, используя ссылку с target="_blank"
атрибут
example.component.html
<a [routerLink]="['/route-to-your-component']" target="_blank">
Open the component in a new tab
</a>
Создайте ленивый компонент загрузки (как URL) и поместите ваш URL в
window.open('url', 'window name', 'settings')
Вы можете попробовать дать имена своим различным окнам. Это откроет каждое новое окно с указанным именем.
window.open('url', 'window 1', '');
window.open('url', 'window 2', '');