April 2025
In this tutorial, we’ll build a real-time stock price tracker using Angular’s new Signals API combined with WebSockets for live data feeds. This app will showcase how fine-grained reactivity in Angular 18 can help you efficiently update UI elements as data streams in, without costly change detection cycles.
Why Use Signals with WebSockets?
WebSockets push live data from the server to the client continuously. Angular’s Signals let us react to these updates granularly—only updating components or UI parts that really need it, resulting in snappy and performant apps.
Step 1: Setting Up the Angular Project
Create a new Angular 18 project:
ng new stock-tracker --routing --style=scss
cd stock-tracker
Install any needed dependencies for WebSocket support (we’ll use native WebSocket in this tutorial).
Step 2: Creating a StockService to Handle WebSocket Connections
We’ll create a service that connects to a WebSocket server sending stock price updates.
import { Injectable, signal } from '@angular/core';
interface StockPrice {
symbol: string;
price: number;
timestamp: number;
}
@Injectable({ providedIn: 'root' })
export class StockService {
private socket!: WebSocket;
// Signal to hold the latest prices mapped by symbol
public prices = signal<Record<string, StockPrice>>({});
connect(url: string) {
this.socket = new WebSocket(url);
this.socket.onmessage = (event) => {
const data: StockPrice = JSON.parse(event.data);
// Update the prices signal reactively
this.prices.update(currentPrices => ({
...currentPrices,
[data.symbol]: data
}));
};
this.socket.onerror = (error) => {
console.error('WebSocket error:', error);
};
}
disconnect() {
this.socket.close();
}
}
Step 3: Building the Stock List Component
This component subscribes to prices and renders a live-updating table.
import { Component, OnInit, OnDestroy } from '@angular/core';
import { StockService } from './stock.service';
@Component({
selector: 'app-stock-list',
template: `
<h2>Real-Time Stock Prices</h2>
<table>
<thead>
<tr><th>Symbol</th><th>Price</th><th>Last Updated</th></tr>
</thead>
<tbody>
<tr *ngFor="let stock of stockSymbols">
<td>{{stock}}</td>
<td>{{ prices()[stock]?.price | currency:'USD' }}</td>
<td>{{ prices()[stock]?.timestamp | date:'shortTime' }}</td>
</tr>
</tbody>
</table>
`
})
export class StockListComponent implements OnInit, OnDestroy {
prices = this.stockService.prices;
stockSymbols: string[] = ['AAPL', 'GOOGL', 'MSFT', 'TSLA'];
constructor(private stockService: StockService) {}
ngOnInit() {
this.stockService.connect('wss://example.com/stocks');
}
ngOnDestroy() {
this.stockService.disconnect();
}
}
Step 4: Running and Testing
Start your app:
ng serve
With the WebSocket server sending JSON updates like:
{ "symbol": "AAPL", "price": 172.35, "timestamp": 1680000000000 }
You’ll see the stock prices update live as data arrives.
Step 5: Bonus – Adding Filtering or Sorting
You can easily extend this example by adding reactive signals for filtering or sorting the stocks list, enhancing the UX without extra change detection overhead.
Summary
This tutorial demonstrated:
- How to use Angular’s Signals for reactive state management.
- Connecting to WebSocket streams for real-time data.
- Building a performant, live-updating stock tracker UI.
Angular 18’s fine-grained reactivity combined with WebSockets unlocks powerful patterns for building responsive real-time apps.