角度<app-root>如何在 ?(索引.html)



我为我的角度应用程序制作了一个主题模块,允许用户在亮/暗模式之间切换。它使用了一个服务、指令和单独的模块,除了在<app-root></app-root>中尝试使用direct之外,它工作得很好,这是必要的,因为否则主题不会应用于整个DOM。

theme.service.ts:

import { Injectable, Inject, EventEmitter } from '@angular/core';
import { THEMES, ACTIVE_THEME, Theme } from './themes/symbols';
@Injectable()
export class ThemeService {
themeChange = new EventEmitter<Theme>();
constructor(
@Inject(THEMES) public themes: Theme[],
@Inject(ACTIVE_THEME) public theme: string
) {
}
getTheme(name: string) {
const theme = this.themes.find(t => t.name === name);
if (!theme) {
throw new Error(`Theme not found: '${name}'`);
}
return theme;
}
getActiveTheme() {
return this.getTheme(this.theme);
}
getProperty(propName: string) {
return this.getActiveTheme().properties[propName];
}
setTheme(name: string) {
this.theme = name;
this.themeChange.emit( this.getActiveTheme());
}
registerTheme(theme: Theme) {
this.themes.push(theme);
}
updateTheme(name: string, properties: { [key: string]: string; }) {
const theme = this.getTheme(name);
theme.properties = {
...theme.properties,
...properties
};
if (name === this.theme) {
this.themeChange.emit(theme);
}
}
}

theme.directive.ts

import { Directive, OnInit, OnDestroy, ElementRef } from '@angular/core';
import { ThemeService } from './theme.service';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { Theme } from './themes/symbols';
@Directive({
selector: '[theme]'
})
export class ThemeDirective implements OnInit, OnDestroy {
private _destroy$ = new Subject();
constructor(
private _elementRef: ElementRef,
private _themeService: ThemeService
) {}
ngOnInit() {
const active = this._themeService.getActiveTheme();
if (active) {
this.updateTheme(active);
}
this._themeService.themeChange
.pipe(takeUntil(this._destroy$))
.subscribe((theme: Theme) => this.updateTheme(theme));
}
ngOnDestroy() {
this._destroy$.next();
this._destroy$.complete();
}
updateTheme(theme: Theme) {
// project properties onto the element
for (const key in theme.properties) {
this._elementRef.nativeElement.style.setProperty(key, theme.properties[key]);
}
// remove old theme
for (const name of this._themeService.theme) {
this._elementRef.nativeElement.classList.remove(`${name}-theme`);
}
// alias element with theme name
this._elementRef.nativeElement.classList.add(`${theme.name}-theme`);
}
}

theme.module.ts

import { NgModule, ModuleWithProviders, InjectionToken } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ThemeService } from './theme.service';
import { ThemeDirective } from './theme.directive';
import { THEMES, ACTIVE_THEME, ThemeOptions } from './themes/symbols';
@NgModule({
imports: [CommonModule],
providers: [ThemeService],
declarations: [ThemeDirective],
exports: [ThemeDirective]
})
export class ThemeModule {
static forRoot(options: ThemeOptions): ModuleWithProviders<ThemeModule> {
return {
ngModule: ThemeModule,
providers: [
{
provide: THEMES,
useValue: options.themes
},
{
provide: ACTIVE_THEME,
useValue: options.active
}
]
};
}
}

然后我在app.module:的导入中声明

ThemeModule.forRoot({
themes: [lightTheme, darkTheme],
active: 'light'
})

我现在可以在app.component.html中使用此指令了:

<body theme>
<app-nav-menu (toggleTheme)="toggleTheme()"></app-nav-menu>
<div class="container parent-container">
<router-outlet></router-outlet>
</div>
</body>

然而,我不能在index.html中使用它,因为它希望将此指令应用于应用程序根标记或html标记本身,以便主题影响整个DOM。

知道如何实现我的目标吗?任何帮助都将不胜感激。

在theme.directive.ts上尝试更新此函数

updateTheme(theme: Theme) {
// project properties onto the element
for (const key in theme.properties) {
// Comment this line
// this._elementRef.nativeElement.style.setProperty(key, theme.properties[key]);
// add this line  
this._elementRef.nativeElement.ownerDocument.body.style.setProperty(key, theme.properties[key]);
}
// remove old theme
for (const name of this._themeService.theme) {
this._elementRef.nativeElement.ownerDocument.body.classList.remove(`${name}-theme`);
}
// alias element with theme name
this._elementRef.nativeElement.ownerDocument.body.classList.add(`${theme.name}-theme`);
}

相关内容

最新更新