Reactive Statistics in Angular 19: Signals, Effects, and Smart Control Flow

Reactive Statistics in Angular 19: Signals, Effects, and Smart Control Flow Angular 19 brings us into a golden age of fine-grained reactivity with Signals, Effects, and a truly modern control flow syntax. In this guide, we’ll harness these tools to build a Reactive Statistics Analyzer that computes basic metrics (mean, variance, count) in real-time — just like a pro. You'll see how to combine: ✅ signal() and computed() for reactive data modeling ✅ effect() for reactive side-effects (auto-logging, syncing, etc.) ✅ Modern control flow with @for, @if, and @switch ✅ Angular 19's cleanest patterns using standalone components and injectable services src/ app/ statistics/ statistics.component.ts services/ statistics.service.ts Use Case: Live Statistical Analyzer Let’s build a calculator that: Accepts numerical input Dynamically updates count, mean, and variance Logs all statistical events reactively using effect() Step 1: The Statistics Service import { Injectable, signal, computed, effect } from '@angular/core'; @Injectable({ providedIn: 'root' }) export class StatisticsService { private values = signal([]); count = computed(() => this.values().length); mean = computed(() => { const vals = this.values(); return vals.length ? vals.reduce((a, b) => a + b, 0) / vals.length : 0; }); variance = computed(() => { const vals = this.values(); const mu = this.mean(); return vals.length ? vals.reduce((acc, x) => acc + Math.pow(x - mu, 2), 0) / vals.length : 0; }); constructor() { effect(() => { console.log(`Count: ${this.count()}, Mean: ${this.mean().toFixed(2)}, Variance: ${this.variance().toFixed(2)}`); }); } add(value: number) { this.values.update(v => [...v, value]); } reset() { this.values.set([]); } get data() { return this.values; } } Step 2: UI Component with Control Flow import { Component } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { StatisticsService } from '../services/statistics.service'; import { CommonModule } from '@angular/common'; @Component({ selector: 'app-statistics', standalone: true, imports: [FormsModule, CommonModule], template: ` Reactive Stats Analyzer Add Reset @if (stats.count() > 0) { Count: {{ stats.count() }} Mean: {{ stats.mean().toFixed(2) }} Variance: {{ stats.variance().toFixed(2) }} } @else { No data yet — add some numbers! } History {{ val }} ` }) export class StatisticsComponent { input = 0; constructor(public stats: StatisticsService){ } submit(){ this.stats.add(this.input); this.input = 0; } reset() { this.stats.reset(); } } Summary Concept Implementation Reactive data signal([]) Derived data computed() Logging effect() for automated tracking Template flow @if, @for used for clean control flow

May 2, 2025 - 00:58
 0
Reactive Statistics in Angular 19: Signals, Effects, and Smart Control Flow

ReactiveStatisticsinAngular19

Reactive Statistics in Angular 19: Signals, Effects, and Smart Control Flow

Angular 19 brings us into a golden age of fine-grained reactivity with Signals, Effects, and a truly modern control flow syntax. In this guide, we’ll harness these tools to build a Reactive Statistics Analyzer that computes basic metrics (mean, variance, count) in real-time — just like a pro.

You'll see how to combine:

  • signal() and computed() for reactive data modeling
  • effect() for reactive side-effects (auto-logging, syncing, etc.)
  • ✅ Modern control flow with @for, @if, and @switch
  • ✅ Angular 19's cleanest patterns using standalone components and injectable services
src/
  app/
    statistics/
       statistics.component.ts   
    services/
       statistics.service.ts

Use Case: Live Statistical Analyzer

Let’s build a calculator that:

  • Accepts numerical input
  • Dynamically updates count, mean, and variance
  • Logs all statistical events reactively using effect()

Step 1: The Statistics Service

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

@Injectable({ providedIn: 'root' })
export class StatisticsService {
  private values = signal<number[]>([]);

  count = computed(() => this.values().length);

  mean = computed(() => {
    const vals = this.values();
    return vals.length ? vals.reduce((a, b) => a + b, 0) / vals.length : 0;
  });

  variance = computed(() => {
    const vals = this.values();
    const mu = this.mean();
    return vals.length
      ? vals.reduce((acc, x) => acc + Math.pow(x - mu, 2), 0) / vals.length
      : 0;
  });

  constructor() {
    effect(() => {
      console.log(`Count: ${this.count()}, Mean: ${this.mean().toFixed(2)}, Variance: ${this.variance().toFixed(2)}`);
    });
  }

  add(value: number) {
    this.values.update(v => [...v, value]);
  }

  reset() {
    this.values.set([]);
  }

  get data() {
    return this.values;
  }
}

Step 2: UI Component with Control Flow

import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { StatisticsService } from '../services/statistics.service';
import { CommonModule } from '@angular/common';

@Component({
  selector: 'app-statistics',
  standalone: true,
  imports: [FormsModule, CommonModule],
  template: `
  

Reactive Stats Analyzer

@if (stats.count() > 0) {

Count: {{ stats.count() }}

Mean: {{ stats.mean().toFixed(2) }}

Variance: {{ stats.variance().toFixed(2) }}

} @else {

No data yet — add some numbers! }

History

  • {{ val }}
`
}) export class StatisticsComponent { input = 0; constructor(public stats: StatisticsService){ } submit(){ this.stats.add(this.input); this.input = 0; } reset() { this.stats.reset(); } }

Summary

Concept Implementation
Reactive data signal([])
Derived data computed()
Logging effect() for automated tracking
Template flow @if, @for used for clean control flow