Angular Material 主题 - BODY 标签上的选择器

Angular Material Theme - Selector on BODY tag

我在 Angular 中开发了一个包含 Material 组件的应用程序。我正在使用 Material 主题为我的应用程序设置几个不同的主题(深色、浅色、彩色)。

我的主要组件 - app.component html 看起来像这样:

<div [ngClass]="appTheme">
  <router-outlet></router-outlet>
</div>

appTheme的值可以是'Light'、'Dark'或'Colorful'。根据这个不同的 @mixin 正在执行,这将为我的应用程序涂上不同的颜色(您可以在 official Material site 上阅读更多相关信息)。

我的问题是某些第 3 方组件和某些 Material 组件是浮动弹出窗口。这些弹出窗口附加到 BODY 标签。所以 html 看起来像这样:

<body>
  <app-root>
    <div class="dark">
     ...
    </div>
  </app-root>
  <some-3rd-party-component>
    ...
  </some-3rd-party-component>
</body>

如您所见,class dark 不会影响 some-3rd-party-component - 因为它不是子元素。

如何在 body 元素上设置 [ngClass]。这样我就可以控制第 3 方组件了??

无需像这样手动设置主题 class <div [ngClass]="appTheme">...</div>,您可以使用纯 js 以编程方式设置它。您只需要获取文档正文并将主题 class 添加到 classes 列表中:

setBodyClass() {
  // get html body element
  const bodyElement = document.body;

  if (bodyElement) {
    // remove existing class (needed if theme is being changed)
    bodyElement.classList.remove(activeClass);
    // add next theme class
    bodyElement.classList.add(nextClass);

    this.bodyClass = nextClass;
  }
}

这是该方法的 Stackblitz

此 SO 答案中提到了另一种方式(但未经 be 测试):Angular2 添加 class 到正文标签 。他们在这里使用 Angular 的文档注入器和渲染器来更改正文的 class。

另一种我用来在叠加层中设置各种不同 Angular Material 组件主题的方法是来自 @angular/cdk/overlay 的 OverlayContainer。类似于纯 js 方法,但不适用于既不在 matOverlayContainer 中也不在应用程序中的元素。

const matOverlayContainerClassList = this.overlayContainer.getContainerElement().classList;

matOverlayContainerClassList.remove(previousThemeName);
matOverlayContainerClassList.add(currentThemeName);