Thuta Learning
ExercisesWeb Developmentintermediate

Exercise Set 2: Services, Forms & RxJS

Relax. We'll talk through this in plain words — no textbook voice.

What you'll walk away with

  • Practice Exercise Set 2: Services, Forms & RxJS yourself
  • Reinforce the skills you've already learned through practice
  • Get comfortable finding bugs, fixing them, and checking your own work

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

typescript
// 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() {}
}
You should see
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.

Easy traps

  • Getting an error from injecting HttpClient without importing HttpClientModule into app.module.ts
  • Checking a reactive form's FormControl valid/invalid state without considering touched/dirty conditions, so error messages show up immediately on every page load and hurt UX

Now Try It Yourself

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.

You'll know it worked when: 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.

Exercise Set 2: Services, Forms & RxJS | Thuta Learning