Let's think about this for a moment
This exercise set steps up a level from Exercise Set 1 — you'll combine services, reactive form validation, the HTTP client, and RxJS operators (map, filter) that you learned in the Intermediate/Advanced chapters. Each task reflects patterns you'll commonly see in production apps, so this practice applies directly to building real-world projects. The tasks are ordered by increasing difficulty, so you can reuse an earlier task's solution in a later one.
Exercises
(1) Build a `CounterService` that holds state with a BehaviorSubject<number> and implement three methods — increment()/decrement()/reset() — then have two components share this single service and verify they stay in sync. (2) Build a SignupForm reactive form with Validators.email on the email field and Validators.minLength(6) on the password field — show error messages in the template when invalid. (3) Use HttpClient to fetch a user list from a public API (e.g., JSONPlaceholder), extract just the name fields into an array using the RxJS `map` operator, then use the `filter` operator to keep only names longer than 5 characters.
Code Example
// counter.service.ts
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable({ providedIn: 'root' })
export class CounterService {
private countSubject = new BehaviorSubject<number>(0);
count$ = this.countSubject.asObservable();
increment() { this.countSubject.next(this.countSubject.value + 1); }
decrement() { this.countSubject.next(this.countSubject.value - 1); }
reset() { this.countSubject.next(0); }
}
// user-list.component.ts (task 3 skeleton)
import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { map, filter } from 'rxjs/operators';
interface User { name: string; }
@Component({ selector: 'app-user-list', template: `<li *ngFor="let n of names$ | async">{{ n }}</li>` })
export class UserListComponent implements OnInit {
names$ = this.http.get<User[]>('https://jsonplaceholder.typicode.com/users').pipe(
map(users => users.map(u => u.name)),
map(names => names.filter(n => n.length > 5))
);
constructor(private http: HttpClient) {}
ngOnInit() {}
}When two components share a counter service, clicking increment in one instantly updates the other component's display too; on the signup form, invalid input immediately shows an error message; and the user list only keeps names longer than 5 characters.5-Minute Try-It
Within 5 minutes, extend task (1) by displaying the count$ Observable directly in the template with the async pipe, rewriting it so a manual subscribe() is completely unnecessary.
A Quick Word of Caution
Public demo APIs can be rate-limited, so calling them too frequently may return error responses — keep this in mind, and note that RxJS operator chains are usually kept in the service layer rather than in component logic.