【问题标题】:<mat-select> not appending <mat-options> to cdk-overlay-container<mat-select> 不将 <mat-options> 附加到 cdk-overlay-container
【发布时间】:2020-12-07 22:12:10
【问题描述】:

我遇到了一个奇怪的问题,即 mat-select 停止打开。

我将使用该应用程序,然后 mat-selects 将打开并让我选择一个选项。那我稍后再回来,它不会再打开了。它的发生非常随机,而且非常不可预测。

我注意到,当我单击该元素时,它仍会附加 aria-owns 属性并将选项(见下文)添加到该属性,但它不再将选项添加到 cdk - 覆盖容器。

我在控制台中没有任何浏览器错误。

编辑

我一直在看 Chrome 开发工具中的性能监视器,CPU 使用率总是很低,JS 堆大小从未真正增加。

它也发生在我们所有的 mat-select 上,甚至在不同的页面上。

Mat-Select 代码

<mat-select [value]="column.source" class="bg-neutral-2 padding-2 line-height-4 border-radius-3 box-xs" placeholder="- select -" (selectionChange)="onColumnChange($event.value, columnIndex)">
    <mat-option class="font-size-1" value="ignore" *ngIf="column.source">- ignore -</mat-option>
    <mat-option class="font-size-1" *ngFor="let source of sortedSourceColumns" [value]="source.value" >{{source.name}}</mat-option>
</mat-select>

点击元素

当我单击元素时,它会将 mat 选项附加到 mat-select aria-owns 属性,但不会将选项添加到 cdk 覆盖容器中。

垫选择

<mat-select _ngcontent-c5="" class="bg-neutral-2 padding-2 line-height-4 border-radius-3 box-xs mat-select ng-tns-c7-6 mat-select-empty" placeholder="- select -" role="listbox" id="mat-select-4" tabindex="0" aria-label="- select -" aria-required="false" aria-disabled="false" aria-invalid="false" aria-multiselectable="false" aria-owns="mat-option-21 mat-option-22 mat-option-23 mat-option-24 mat-option-25 mat-option-26 mat-option-27 mat-option-28 mat-option-29 mat-option-30 mat-option-31 mat-option-32 mat-option-33 mat-option-34 mat-option-35 mat-option-36 mat-option-37" aria-activedescendant="mat-option-21"><div class="mat-select-trigger" aria-hidden="true" cdk-overlay-origin=""><div class="mat-select-value"><!----><span class="mat-select-placeholder ng-tns-c7-6 ng-star-inserted">- select -</span><!----></div><div class="mat-select-arrow-wrapper"><div class="mat-select-arrow"></div></div></div><!----></mat-select>

cdk-overlay-container

<div class="cdk-overlay-container"></div>

有什么想法可能导致这种情况吗?

依赖关系

    "@angular/animations": "~7.0.0",
    "@angular/cdk": "^7.0.4",
    "@angular/common": "~7.0.0",
    "@angular/compiler": "~7.0.0",
    "@angular/core": "~7.0.0",
    "@angular/forms": "~7.0.0",
    "@angular/http": "~7.0.0",
    "@angular/material": "~7.0.4",
    "@angular/platform-browser": "~7.0.0",
    "@angular/platform-browser-dynamic": "~7.0.0",
    "@angular/router": "~7.0.0",

【问题讨论】:

    标签: angular angular-material


    【解决方案1】:

    对于遇到此问题的其他任何人,在我的情况下,它最终成为使用 single-spa 在同一页面上运行 Angular 应用程序并且两个应用程序都使用 Angular Material 的问题。

    Angular Material 使用 cdk-overlay 附加选项,并且由于有多个应用程序,应用程序会混淆将选项添加到哪个覆盖层。

    我通过添加一个自定义类来修复它,以使用以下代码清理我的每个微前端中的覆盖:

    microfrontend-overlay-container.ts

    import { OverlayContainer } from '@angular/cdk/overlay';
    
    @Injectable()
    export class MicrofrontendOverlayContainer extends OverlayContainer {
      protected _createContainer(): void {
        const containerClass = 'cdk-overlay-container';
        const previousContainers = this._document.getElementsByClassName(containerClass);
    
        // If there is already a container (can happen in a Microfrontend scenario with
        // multiple self-contained Angular apps on the same website), reuse that. But
        // clean it up because it could be created while transitioning from server
        // to client (Angular Universal) and may be stale. Remove any additional containers.
        for (let i = 0; i < previousContainers.length; i++) {
          while (i === 0 && previousContainers[i].firstChild) {
            previousContainers[i].removeChild(previousContainers[i].firstChild);
          }
    
          if (i > 0 && !!previousContainers[i].parentNode) {
            previousContainers[i].parentNode.removeChild(previousContainers[i]);
          }
        }
    
        if (previousContainers.length > 0) {
          this._containerElement = previousContainers[0] as HTMLElement;
          return;
        }
    
        const container = this._document.createElement('div');
        container.classList.add(containerClass);
        this._document.body.appendChild(container);
        this._containerElement = container;
      }
    }
    

    app.module.ts

    将此添加到提供程序数组中:

    { provide: OverlayContainer, useClass: MicrofrontendOverlayContainer }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-14
      • 1970-01-01
      • 2020-07-11
      相关资源
      最近更新 更多