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

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()
andcomputed()
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 |