Skip to content

Commit 7231edd

Browse files
fix(SSR): Fix SSR rendering issue
1 parent d02d76c commit 7231edd

File tree

2 files changed

+22
-11
lines changed

2 files changed

+22
-11
lines changed

projects/theme/src/lib/theme.provider.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { Provider, EnvironmentProviders, provideAppInitializer, inject } from '@angular/core';
1+
import { Provider, EnvironmentProviders, provideAppInitializer, inject, PLATFORM_ID } from '@angular/core';
2+
import { isPlatformBrowser } from '@angular/common';
23
import { ThemeService } from './theme.service';
34
import { THEME_CONFIG } from './theme.config';
45
import type { ThemeConfig } from './theme.types';
@@ -8,8 +9,14 @@ export function provideUiTheme(config?: ThemeConfig): (Provider | EnvironmentPro
89
...(config ? [{ provide: THEME_CONFIG, useValue: config }] : []),
910
...(config?.enableAutoInit !== false ? [
1011
provideAppInitializer(() => {
11-
const themeService = inject(ThemeService);
12-
themeService.initialize();
12+
const platformId = inject(PLATFORM_ID);
13+
14+
// Only initialize in browser environment
15+
if (isPlatformBrowser(platformId)) {
16+
const themeService = inject(ThemeService);
17+
themeService.initialize();
18+
}
19+
1320
return Promise.resolve();
1421
})
1522
] : [])

projects/theme/src/lib/theme.service.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ export class ThemeService implements OnDestroy {
3131
readonly theme = this.themeSignal.asReadonly();
3232
readonly systemTheme = this.systemThemeSignal.asReadonly();
3333
readonly resolvedTheme = computed(() => {
34+
// During SSR, always return a safe default
35+
if (!isPlatformBrowser(this.platformId)) {
36+
return 'light';
37+
}
38+
3439
if (this.config.forcedTheme && this.config.forcedTheme !== 'system') {
3540
return this.config.forcedTheme;
3641
}
@@ -61,13 +66,13 @@ export class ThemeService implements OnDestroy {
6166
if (isPlatformBrowser(this.platformId)) {
6267
this.setupManagers();
6368
this.loadInitialTheme();
69+
this.setupEffects();
6470
} else {
65-
// SSR fallback
71+
// SSR fallback - just set default values without DOM access
6672
this.themeSignal.set(this.config.defaultTheme);
6773
this.systemThemeSignal.set('light');
6874
}
6975

70-
this.setupEffects();
7176
this.isInitialized = true;
7277
} catch (error) {
7378
console.error('Failed to initialize ThemeService:', error);
@@ -179,23 +184,22 @@ export class ThemeService implements OnDestroy {
179184
}
180185
}
181186

182-
// Effects setup
187+
// Effects setup - only called in browser environment
183188
private setupEffects(): void {
189+
if (!isPlatformBrowser(this.platformId)) {
190+
return;
191+
}
184192
effect(() => {
185193
const resolvedTheme = this.resolvedTheme();
186-
187194
if (resolvedTheme !== this.lastAppliedTheme) {
188195
this.domManager.applyTheme(resolvedTheme, this.config);
189196
this.lastAppliedTheme = resolvedTheme;
190197
}
191198
});
192199

193-
// Storage effect
194200
effect(() => {
195201
const theme = this.themeSignal();
196-
if (isPlatformBrowser(this.platformId) &&
197-
!this.config.forcedTheme &&
198-
!this.isDestroyed) {
202+
if (!this.config.forcedTheme && !this.isDestroyed) {
199203
this.storageManager.saveTheme(this.config, theme);
200204
}
201205
});

0 commit comments

Comments
 (0)