Building a Professional Angular 19 App Using Signals and Services

In this article, we will build a professional-grade example using: ✅ Angular 19 ✅ Signals ✅ Dependency Injection (Services) ✅ Standalone Components Goal We will create: A service that manages a list of heroes using signal(). A component that displays and adds heroes via the service. Clean, reactive, and fully Angular 19-compliant code. Setting up the Service: HeroService import { Injectable, signal } from '@angular/core'; export interface Hero { id: number; name: string; } @Injectable({ providedIn: 'root' }) export class HeroService { private heroes = signal([ { id: 1, name: 'Goku' }, { id: 2, name: 'Vegeta' } ]); getHeroes() { return this.heroes; } addHero(hero: Hero) { this.heroes.update(prev => [...prev, hero]); } removeHero(id: number) { this.heroes.update(prev => prev.filter(h => h.id !== id)); } } Building the Component: HeroListComponent import { Component } from '@angular/core'; import { HeroService } from './hero.service'; import { CommonModule } from '@angular/common'; import { FormsModule } from '@angular/forms'; @Component({ selector: 'app-hero-list', standalone: true, template: ` Hero List {{ hero.name }} Remove Add Hero `, imports: [CommonModule, FormsModule] }) export class HeroListComponent { heroes = signal([]); newHeroName = ''; constructor(private heroService: HeroService) { this.heroes = this.heroService.getHeroes(); } add() { if (this.newHeroName.trim()) { const newHero = { id: Date.now(), name: this.newHeroName.trim() }; this.heroService.addHero(newHero); this.newHeroName = ''; } } remove(id: number) { this.heroService.removeHero(id); } } How It Works Layer Purpose Service (HeroService) Owns the signal, responsible for all state Component (HeroListComponent) Subscribes to the signal and reacts automatically Template Renders reactive values via heroes() call When you call addHero() or removeHero(), the signal updates and the component auto-renders without manual refresh. Key Best Practices Services manage signals, components consume them. No manual subscriptions needed. Keep services pure and encapsulated. Use standalone components for cleaner architecture. Final Thoughts Angular 19 is leading towards a lightweight, reactive, modular future. Using Signals and Services properly will make your apps: Faster More maintainable Highly scalable Use Signals for state, Services for management, and Standalone Components for architecture. Happy coding with Angular 19! ⚡

Apr 28, 2025 - 23:53
 0
Building a Professional Angular 19 App Using Signals and Services

UsingSignalsAndServices

In this article, we will build a professional-grade example using:

  • ✅ Angular 19
  • ✅ Signals
  • ✅ Dependency Injection (Services)
  • ✅ Standalone Components

Goal

We will create:

  • A service that manages a list of heroes using signal().
  • A component that displays and adds heroes via the service.
  • Clean, reactive, and fully Angular 19-compliant code.

Setting up the Service: HeroService

import { Injectable, signal } from '@angular/core';

export interface Hero {
  id: number;
  name: string;
}

@Injectable({ providedIn: 'root' })
export class HeroService {
  private heroes = signal<Hero[]>([
    { id: 1, name: 'Goku' },
    { id: 2, name: 'Vegeta' }
  ]);

  getHeroes() {
    return this.heroes;
  }

  addHero(hero: Hero) {
    this.heroes.update(prev => [...prev, hero]);
  }

  removeHero(id: number) {
    this.heroes.update(prev => prev.filter(h => h.id !== id));
  }
}

Building the Component: HeroListComponent

import { Component } from '@angular/core';
import { HeroService } from './hero.service';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';

@Component({
  selector: 'app-hero-list',
  standalone: true,
  template: `
    

Hero List

  • {{ hero.name }}
`
, imports: [CommonModule, FormsModule] }) export class HeroListComponent { heroes = signal<Hero[]>([]); newHeroName = ''; constructor(private heroService: HeroService) { this.heroes = this.heroService.getHeroes(); } add() { if (this.newHeroName.trim()) { const newHero = { id: Date.now(), name: this.newHeroName.trim() }; this.heroService.addHero(newHero); this.newHeroName = ''; } } remove(id: number) { this.heroService.removeHero(id); } }

How It Works

Layer Purpose
Service (HeroService) Owns the signal, responsible for all state
Component (HeroListComponent) Subscribes to the signal and reacts automatically
Template Renders reactive values via heroes() call

When you call addHero() or removeHero(), the signal updates and the component auto-renders without manual refresh.

Key Best Practices

  • Services manage signals, components consume them.
  • No manual subscriptions needed.
  • Keep services pure and encapsulated.
  • Use standalone components for cleaner architecture.

Final Thoughts

Angular 19 is leading towards a lightweight, reactive, modular future. Using Signals and Services properly will make your apps:

  • Faster
  • More maintainable
  • Highly scalable

Use Signals for state, Services for management, and Standalone Components for architecture.

Happy coding with Angular 19! ⚡