我正在尝试在 Web 组件内使用 Angular Material 组件。除了 cdk-overlays 的一种边缘情况外,一切正常。到目前为止,我已经成功地使用 _createContainer() 的重写将覆盖容器附加到 Shadowroot 内部的 div 中,以便应用样式。但是,如果我使用 *ngIf 隐藏父元素,然后将其切换回来,覆盖容器会出现在 DOM 中,但它及其包含的元素不可见。
我是否缺少某些内容,需要手动清除或切换某些内容才能使该行为正常工作?
代码基于此答案:将 MatDialog 弹出窗口添加到 Angular Root 而不是主体
@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 组件被销毁,它仍然会保留您在
_createContainer
中创建的缓存元素。
有 2 个修复
OverlayContainer
getContainerElement
,如下所示
override getContainerElement(): HTMLElement {
if (!this._containerElement || !this._containerElement.isConnected) {
this._createContainer();
}
return this._containerElement;
}