The SettingsService manages application-wide settings using Angular signals with automatic persistence to localStorage.
Import
import { SettingsService } from '@jet/services/settings/settings.service';
import { Settings } from '@jet/interfaces/settings.interface';
Usage
Read Settings
import { inject, Component, Signal } from '@angular/core';
import { SettingsService } from '@jet/services/settings/settings.service';
import { Settings } from '@jet/interfaces/settings.interface';
export class AppComponent {
readonly #settingsService = inject(SettingsService);
readonly settings: Signal<Settings> = this.#settingsService.settings;
ngOnInit() {
// Read current settings
const currentSettings = this.settings();
console.log('Color scheme:', currentSettings.colorSchemeOption);
console.log('Language:', currentSettings.languageOption);
}
}
Update Settings
updateColorScheme(mode: 'light' | 'dark') {
this.#settingsService.updateSettings({
colorSchemeOption: {
mode,
variant: 'auto'
}
});
}
updateLanguage(code: string) {
this.#settingsService.updateSettings({
languageOption: {
code,
directionality: code === 'ar' ? 'rtl' : 'ltr'
}
});
}
Access Directionality
export class LayoutComponent {
readonly #settingsService = inject(SettingsService);
readonly directionality = this.#settingsService.directionality;
ngOnInit() {
// Computed signal for text direction
const direction = this.directionality();
console.log('Text direction:', direction); // 'ltr' or 'rtl'
}
}
Reactive Templates
<div [dir]="settingsService.directionality()">
<p>Current theme: {{ settings().colorSchemeOption.mode }}</p>
<p>Language: {{ settings().languageOption.code }}</p>
</div>
Properties
settings
Read-only signal containing the current application settings.
Reactive signal that emits when settings change
Source: /home/daytona/workspace/source/src/app/services/settings/settings.service.ts:51
public get settings(): Signal<Settings> {
return this.#settings.asReadonly();
}
Example:
const currentSettings = this.settingsService.settings();
// Use in computed signals
const isDarkMode = computed(() =>
this.settingsService.settings().colorSchemeOption.mode === 'dark'
);
// Use in effects
effect(() => {
const settings = this.settingsService.settings();
console.log('Settings changed:', settings);
});
directionality
Computed signal for the current text directionality (LTR/RTL).
Computed signal derived from language settings
Source: /home/daytona/workspace/source/src/app/services/settings/settings.service.ts:24
public readonly directionality: Signal<Settings['languageOption']['directionality']>;
// Computed as:
this.directionality = computed(() => this.#settings().languageOption.directionality);
Example:
// In component
const direction = this.settingsService.directionality();
// In template
<div [dir]="settingsService.directionality()">
<!-- Content automatically flips for RTL languages -->
</div>
// In CSS-in-JS
const styles = computed(() => ({
textAlign: this.settingsService.directionality() === 'rtl' ? 'right' : 'left'
}));
Methods
updateSettings
Updates application settings with partial updates and persists to localStorage.
partialSettings
Partial<Settings>
required
Object containing the settings to updatepartialSettings.colorSchemeOption
Color scheme configuration
partialSettings.languageOption
Language and directionality configuration
This method does not return a value. Settings are updated reactively.
Source: /home/daytona/workspace/source/src/app/services/settings/settings.service.ts:55
public updateSettings(partialSettings: Partial<Settings>): void {
this.#settings.update((settings) => ({ ...settings, ...partialSettings }));
}
Example:
// Update only color scheme
this.settingsService.updateSettings({
colorSchemeOption: { mode: 'dark', variant: 'auto' }
});
// Update only language
this.settingsService.updateSettings({
languageOption: { code: 'es', directionality: 'ltr' }
});
// Update multiple settings
this.settingsService.updateSettings({
colorSchemeOption: { mode: 'light', variant: 'custom' },
languageOption: { code: 'ar', directionality: 'rtl' }
});
Type Definitions
Settings Interface
export interface Settings {
colorSchemeOption: ColorSchemeOption;
languageOption: LanguageOption;
}
Source: /home/daytona/workspace/source/src/app/interfaces/settings.interface.ts:4
ColorSchemeOption
interface ColorSchemeOption {
mode: 'light' | 'dark' | 'auto';
variant?: string;
}
LanguageOption
interface LanguageOption {
code: string;
directionality: 'ltr' | 'rtl';
}
Features
Automatic Persistence
Settings are automatically saved to localStorage whenever they change:
effect(() => {
this.#loggerService.logEffectRun('settings');
const settings = this.#settings();
untracked(() =>
this.#storageService.setLocalStorageItem(LocalStorageKey.Settings, settings)
);
}, { debugName: 'settings' });
Default Settings
Settings are initialized with defaults merged with stored values:
const storedSettings = this.#storageService.getLocalStorageItem<Settings>(
LocalStorageKey.Settings
);
this.#settings = signal({ ...DEFAULT_SETTINGS, ...storedSettings });
Reactive Updates
All changes propagate immediately through Angular signals:
// Component automatically re-renders when settings change
@Component({
template: `<div>Current theme: {{ settings().colorSchemeOption.mode }}</div>`
})
export class ThemeComponent {
readonly settings = inject(SettingsService).settings;
}
Computed Values
The service exposes computed signals for derived values:
// Directionality is computed from language settings
this.directionality = computed(() =>
this.#settings().languageOption.directionality
);
Configuration
Default Settings
Define default settings in your constants:
// src/app/constants/default-settings.constant.ts
import { Settings } from '@jet/interfaces/settings.interface';
export const DEFAULT_SETTINGS: Settings = {
colorSchemeOption: {
mode: 'light',
variant: 'auto'
},
languageOption: {
code: 'en',
directionality: 'ltr'
}
};
Storage Key
Settings are stored using the Settings localStorage key:
enum LocalStorageKey {
Settings = 'settings'
}
Best Practices
- Use partial updates - Only update the settings that changed
- Leverage computed signals - Create derived values for complex logic
- Read reactively - Use signal reads in templates and effects
- Validate updates - Ensure valid values before calling
updateSettings()
- Type safety - Use TypeScript interfaces for all settings objects
Common Patterns
Theme Switcher Component
@Component({
selector: 'app-theme-switcher',
template: `
<button (click)="toggleTheme()">
{{ currentTheme() === 'dark' ? 'Light' : 'Dark' }} Mode
</button>
`
})
export class ThemeSwitcherComponent {
readonly #settingsService = inject(SettingsService);
readonly currentTheme = computed(() =>
this.#settingsService.settings().colorSchemeOption.mode
);
toggleTheme() {
const newMode = this.currentTheme() === 'dark' ? 'light' : 'dark';
this.#settingsService.updateSettings({
colorSchemeOption: { mode: newMode, variant: 'auto' }
});
}
}
Language Selector
export class LanguageSelectorComponent {
readonly #settingsService = inject(SettingsService);
readonly languages = [
{ code: 'en', name: 'English', dir: 'ltr' as const },
{ code: 'es', name: 'Español', dir: 'ltr' as const },
{ code: 'ar', name: 'العربية', dir: 'rtl' as const }
];
selectLanguage(code: string, directionality: 'ltr' | 'rtl') {
this.#settingsService.updateSettings({
languageOption: { code, directionality }
});
}
}
export class SettingsFormComponent implements OnInit {
readonly #settingsService = inject(SettingsService);
settingsForm = new FormGroup({
theme: new FormControl('light'),
language: new FormControl('en')
});
ngOnInit() {
const settings = this.#settingsService.settings();
this.settingsForm.patchValue({
theme: settings.colorSchemeOption.mode,
language: settings.languageOption.code
});
}
onSubmit() {
const { theme, language } = this.settingsForm.value;
this.#settingsService.updateSettings({
colorSchemeOption: { mode: theme, variant: 'auto' },
languageOption: {
code: language,
directionality: language === 'ar' ? 'rtl' : 'ltr'
}
});
}
}
Dependencies
The SettingsService depends on:
- LoggerService - For logging effect runs
- StorageService - For localStorage persistence