Bird
Raised Fist0
Angularframework~20 mins

Service-based state management in Angular - Practice Problems & Coding Challenges

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Challenge - 5 Problems
🎖️
Service State Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
component_behavior
intermediate
2:00remaining
How does Angular service state persist across components?

Consider an Angular service that holds a counter value. If two different components inject this service and update the counter, what will be the final counter value seen by both components?

Assume the service starts with counter = 0. Component A increments it by 1, then Component B increments it by 2.

Angular
export class CounterService {
  counter = 0;
  increment(value: number) {
    this.counter += value;
  }
}

// Component A calls: counterService.increment(1);
// Component B calls: counterService.increment(2);
AComponent A sees 1, Component B sees 2.
BBoth components see counter value 0 because services are recreated.
CBoth components see counter value 3.
DComponent A sees 2, Component B sees 3.
Attempts:
2 left
💡 Hint

Think about how Angular injects services by default and whether the service instance is shared.

📝 Syntax
intermediate
1:30remaining
Identify the correct way to inject a service in Angular standalone component

Which of the following is the correct syntax to inject a service named DataService into a standalone Angular component using the new Angular 17+ inject() function?

Aconst dataService = new DataService();
Bconst dataService = inject(DataService);
Cconstructor(private dataService: DataService) {}
Dconst dataService = useInject(DataService);
Attempts:
2 left
💡 Hint

Standalone components can use the inject() function instead of constructor injection.

state_output
advanced
2:30remaining
What is the output after updating service state asynchronously?

Given this Angular service and component code, what will be logged to the console?

export class MessageService {
  message = 'Hello';
  updateMessage(newMsg: string) {
    setTimeout(() => {
      this.message = newMsg;
    }, 1000);
  }
}

@Component({
  standalone: true,
  selector: 'app-msg',
  template: `{{msgService.message}}`
})
export class MsgComponent {
  constructor(public msgService: MessageService) {}
  ngOnInit() {
    this.msgService.updateMessage('Hi');
    console.log(this.msgService.message);
  }
}
ALogs 'Hello' immediately, template updates to 'Hi' after 1 second.
BLogs 'Hi' immediately, template shows 'Hi' immediately.
CLogs 'Hello' and template never updates.
DLogs 'Hi' immediately, template updates to 'Hello' after 1 second.
Attempts:
2 left
💡 Hint

Consider when the setTimeout callback runs compared to the console.log.

🔧 Debug
advanced
2:00remaining
Why does the Angular service state reset on navigation?

An Angular service holds user data but resets to initial state when navigating between routes. What is the most likely cause?

AAngular services always reset on route changes by design.
BThe service is provided in root, so it resets on navigation.
CThe component recreates the service manually on each navigation.
DThe service is provided in a lazy-loaded module, causing multiple instances.
Attempts:
2 left
💡 Hint

Think about how Angular creates service instances with lazy-loaded modules.

🧠 Conceptual
expert
3:00remaining
What is the main benefit of using service-based state management in Angular?

Why do Angular developers often use services to manage shared state instead of component inputs or outputs?

AServices provide a single source of truth and persistent state across components.
BServices automatically update the UI without change detection.
CServices force components to reload on every state change.
DServices prevent any state changes unless the app reloads.
Attempts:
2 left
💡 Hint

Consider how shared state should behave across multiple components.

Practice

(1/5)
1. What is the main benefit of using a service for state management in Angular?
easy
A. It allows sharing state easily across multiple components.
B. It automatically updates the UI without any coding.
C. It replaces the need for components entirely.
D. It makes the app run faster by skipping change detection.

Solution

  1. Step 1: Understand service role in Angular

    Services hold data and logic separate from components.
  2. Step 2: Recognize state sharing benefit

    Services can be injected into many components, sharing the same state instance.
  3. Final Answer:

    It allows sharing state easily across multiple components. -> Option A
  4. Quick Check:

    Service-based state management = shared state [OK]
Hint: Services share data across components easily [OK]
Common Mistakes:
  • Thinking services replace components
  • Believing services auto-update UI without code
  • Assuming services speed up app by skipping detection
2. Which decorator and property make an Angular service a singleton across the app?
easy
A. @NgModule({ providers: [] })
B. @Component({ selector: 'app-root' })
C. @Directive({ selector: '[appService]' })
D. @Injectable({ providedIn: 'root' })

Solution

  1. Step 1: Identify Angular service decorator

    @Injectable marks a class as a service for dependency injection.
  2. Step 2: Understand providedIn property

    Setting providedIn: 'root' makes the service a singleton app-wide.
  3. Final Answer:

    @Injectable({ providedIn: 'root' }) -> Option D
  4. Quick Check:

    Singleton service = @Injectable with providedIn root [OK]
Hint: Use @Injectable({ providedIn: 'root' }) for singleton services [OK]
Common Mistakes:
  • Confusing @Component with service decorator
  • Using @NgModule providers without providedIn
  • Mistaking @Directive for service declaration
3. Given this service code, what will the console log after calling increment() twice?
import { Injectable, signal } from '@angular/core';

@Injectable({ providedIn: 'root' })
export class CounterService {
  count = signal(0);

  increment() {
    this.count.update(c => c + 1);
  }
}

const service = new CounterService();
service.increment();
service.increment();
console.log(service.count());
medium
A. 1
B. 0
C. 2
D. undefined

Solution

  1. Step 1: Understand initial signal value

    The signal count starts at 0.
  2. Step 2: Apply two increments

    Each increment adds 1, so after two calls, count is 2.
  3. Final Answer:

    2 -> Option C
  4. Quick Check:

    0 + 1 + 1 = 2 [OK]
Hint: Each update adds 1; two calls add 2 total [OK]
Common Mistakes:
  • Forgetting to call the signal as a function to get value
  • Assuming count resets after each increment
  • Confusing update with set method
4. What is wrong with this Angular service code for state management?
import { Injectable, signal } from '@angular/core';

@Injectable()
export class DataService {
  data = signal([]);

  addItem(item: string) {
    this.data().push(item);
  }
}
medium
A. The service is missing providedIn: 'root' for singleton scope.
B. The signal value is mutated directly, which breaks reactivity.
C. The addItem method should return the updated array.
D. The signal should be initialized with null, not an empty array.

Solution

  1. Step 1: Check signal mutation method

    The code calls this.data() to get the array, then pushes directly.
  2. Step 2: Understand signal immutability

    Directly mutating the array breaks Angular's reactivity; must use update() or set() to replace value.
  3. Final Answer:

    The signal value is mutated directly, which breaks reactivity. -> Option B
  4. Quick Check:

    Mutate signal value immutably to keep reactivity [OK]
Hint: Never mutate signal value directly; use update or set [OK]
Common Mistakes:
  • Ignoring providedIn for singleton scope
  • Expecting addItem to return value
  • Thinking null is better initial value than []
5. You want to share a list of tasks across components using a service with Angular signals. Which approach correctly updates the tasks list immutably when adding a new task?
import { Injectable, signal } from '@angular/core';

@Injectable({ providedIn: 'root' })
export class TaskService {
  tasks = signal([]);

  addTask(newTask: string) {
    // Which line correctly updates tasks?
  }
}
hard
A. this.tasks.set([...this.tasks(), newTask]);
B. this.tasks = signal([...this.tasks(), newTask]);
C. this.tasks().push(newTask);
D. this.tasks.update(tasks => { tasks.push(newTask); return tasks; });

Solution

  1. Step 1: Understand immutable update with signals

    Signals require replacing the value immutably to trigger updates.
  2. Step 2: Analyze options for correct update

    this.tasks.set([...this.tasks(), newTask]); uses set() with a new array including the new task, which is correct.
  3. Final Answer:

    this.tasks.set([...this.tasks(), newTask]); -> Option A
  4. Quick Check:

    Immutable update with set() = correct pattern [OK]
Hint: Use set() with new array copy to update signals immutably [OK]
Common Mistakes:
  • Mutating array inside update without returning new array
  • Directly pushing to signal value
  • Reassigning signal variable instead of updating value