Managing User Preferences in an Angular Application
This challenge focuses on implementing a robust state management solution within an Angular application to manage user preferences. Effectively managing application state is crucial for creating dynamic and user-friendly interfaces, allowing components to access and modify shared data without direct dependencies.
Problem Description
You are tasked with building a simple Angular application that allows users to customize their theme (light/dark) and font size. This preference data needs to be accessible by multiple components and persist across route changes. You should implement a state management pattern to handle this shared data.
Key Requirements:
- Centralized State: Create a single source of truth for user preferences (theme and font size).
- State Updates: Implement a mechanism to update these preferences from a dedicated component.
- State Consumption: Allow other components to read and react to changes in user preferences.
- Persistence (within session): Preferences should persist as long as the application is open in the browser, even if the user navigates between different routes.
- Type Safety: Utilize TypeScript for all state-related logic and data structures.
Expected Behavior:
- A settings component should allow the user to select a theme (e.g., "light", "dark") and a font size (e.g., "small", "medium", "large").
- A display component should visually reflect the selected theme (e.g., by applying CSS classes to the
bodyor a main wrapper) and font size (e.g., by applying CSS classes to text elements). - When a user changes a preference in the settings component, the display component should update immediately without manual refreshes.
Edge Cases to Consider:
- Initial state: What should be the default theme and font size when the application first loads?
- Component lifecycle: How do components subscribe and unsubscribe from state changes to prevent memory leaks?
Examples
Example 1:
Input: User navigates to the application. Initial State: Theme = "light", Font Size = "medium"
Output: The application loads with a light theme and medium font size applied. A settings component shows "light" selected for theme and "medium" for font size. A display component shows content with default styling.
Explanation: The application initializes with default preferences.
Example 2:
Input:
- User changes the theme to "dark" in the settings component.
- User navigates from the home page to a profile page.
Output:
- The application immediately switches to a dark theme.
- The dark theme and the previously selected font size remain applied on the profile page.
Explanation: State changes are reflected globally, and the state is maintained across route transitions.
Constraints
- The state management solution should be implemented using Angular's built-in features or a lightweight, commonly used library (e.g., NgRx if you want to explore a more advanced pattern, but a simple service with RxJS observables is sufficient for this challenge).
- All TypeScript code should adhere to standard practices and be well-documented.
- The solution should be performant, avoiding unnecessary re-renders or subscriptions.
Notes
- Consider using an Angular service to hold and manage the application state.
- RxJS
BehaviorSubjectorSubjectcan be valuable tools for managing observable streams of state. - Think about how to update the DOM based on the state changes (e.g., using
Renderer2or binding to CSS classes). - For persistence within the session, consider using
localStorageorsessionStorageif you want the state to survive a page refresh, though the prompt only requires persistence across route changes.