在 ShadowDOM 中使用 CDK 覆盖容器
Using CDK Overlay Container in ShadowDOM
我正在尝试在 Web 组件中使用 Angular Material 组件。除了 cdk-overlays 的一种边缘情况外,一切正常。到目前为止,我已经成功地使用 _createContainer() 的覆盖将覆盖容器附加到 shadowroot 内的 div 以便应用样式。但是,如果我用 *ngIf 隐藏父元素,然后将其切换回来,覆盖容器会出现在 DOM 中,但它及其包含的元素不可见。
是否有我遗漏的地方需要手动清除或切换某些东西才能使该行为正常工作?
代码基于此答案:
@Injectable({ providedIn: "root" })
export class AppOverlayContainer extends OverlayContainer implements OnDestroy {
constructor(@Inject(DOCUMENT) _document: any) {
super(_document);
}
ngOnDestroy() {
super.ngOnDestroy();
}
getRootElement(): Element {
return this._document
.querySelector("web-component-tag")
.shadowRoot.querySelector("#angular-app-root");
}
createContainer(): void {
this._createContainer();
}
protected _createContainer(): void {
super._createContainer();
this._appendToRootComponent();
}
private _appendToRootComponent(): void {
if (!this._containerElement) {
return;
}
const rootElement = this.getRootElement();
const parent = rootElement || this._document.body;
parent.appendChild(this._containerElement);
}
}
HTML
<ng-container *ngIf="toggleWidget$ | async">
<app-conversations
id="angular-app-root"
[toggleWidget$]="toggleWidget$"
[contextTitle]="contexttitle"
[contexts]="contexts"
[preloadConversations]="subscribeonload"
[widgetIdentifier]="uniqueId"
></app-conversations>
</ng-container>
<ng-container
*ngIf="(toggleWidget$ | async) === false && !overridelaunchbutton"
>
<button
mat-fab
class="message-button"
color="primary"
(click)="toggleWidget$.next(true)"
>
<mat-icon svgIcon="message"></mat-icon>
<div class="unread-pip" *ngIf="hasUnreadMessages">
{{ unreadMessageCount }}
</div>
</button>
</ng-container>
<ng-container *ngIf="overridelaunchbutton">
<button
mat-icon-button
[ngClass]="launchbuttonclass"
[color]="launchbuttoncolor"
(click)="toggleWidget$.next(true)"
>
<mat-icon svgIcon="{{ launchbuttonicon }}"></mat-icon>
<div class="unread-pip" *ngIf="hasUnreadMessages">
{{ unreadMessageCount }}
</div>
</button>
</ng-container>
除了覆盖容器被 *ngIf 包装时会发生奇怪的行为之外,我从未找到根源。当 *ngIf 第一次显示时,切换为不可见然后再次显示,这会导致容器内呈现的内容出现问题。将它移出 *ngIf 解决了我的问题。
我正在尝试在 Web 组件中使用 Angular Material 组件。除了 cdk-overlays 的一种边缘情况外,一切正常。到目前为止,我已经成功地使用 _createContainer() 的覆盖将覆盖容器附加到 shadowroot 内的 div 以便应用样式。但是,如果我用 *ngIf 隐藏父元素,然后将其切换回来,覆盖容器会出现在 DOM 中,但它及其包含的元素不可见。
是否有我遗漏的地方需要手动清除或切换某些东西才能使该行为正常工作?
代码基于此答案:
@Injectable({ providedIn: "root" })
export class AppOverlayContainer extends OverlayContainer implements OnDestroy {
constructor(@Inject(DOCUMENT) _document: any) {
super(_document);
}
ngOnDestroy() {
super.ngOnDestroy();
}
getRootElement(): Element {
return this._document
.querySelector("web-component-tag")
.shadowRoot.querySelector("#angular-app-root");
}
createContainer(): void {
this._createContainer();
}
protected _createContainer(): void {
super._createContainer();
this._appendToRootComponent();
}
private _appendToRootComponent(): void {
if (!this._containerElement) {
return;
}
const rootElement = this.getRootElement();
const parent = rootElement || this._document.body;
parent.appendChild(this._containerElement);
}
}
HTML
<ng-container *ngIf="toggleWidget$ | async">
<app-conversations
id="angular-app-root"
[toggleWidget$]="toggleWidget$"
[contextTitle]="contexttitle"
[contexts]="contexts"
[preloadConversations]="subscribeonload"
[widgetIdentifier]="uniqueId"
></app-conversations>
</ng-container>
<ng-container
*ngIf="(toggleWidget$ | async) === false && !overridelaunchbutton"
>
<button
mat-fab
class="message-button"
color="primary"
(click)="toggleWidget$.next(true)"
>
<mat-icon svgIcon="message"></mat-icon>
<div class="unread-pip" *ngIf="hasUnreadMessages">
{{ unreadMessageCount }}
</div>
</button>
</ng-container>
<ng-container *ngIf="overridelaunchbutton">
<button
mat-icon-button
[ngClass]="launchbuttonclass"
[color]="launchbuttoncolor"
(click)="toggleWidget$.next(true)"
>
<mat-icon svgIcon="{{ launchbuttonicon }}"></mat-icon>
<div class="unread-pip" *ngIf="hasUnreadMessages">
{{ unreadMessageCount }}
</div>
</button>
</ng-container>
除了覆盖容器被 *ngIf 包装时会发生奇怪的行为之外,我从未找到根源。当 *ngIf 第一次显示时,切换为不可见然后再次显示,这会导致容器内呈现的内容出现问题。将它移出 *ngIf 解决了我的问题。