Issue
This question is based on an example from https://github.com/ParthibanRajalingam/demos
Only the initial values of the stock object are displayed using app.component.html:
<div class="card" *ngIf="stock$ | async; let stock">
<div class="textBox">
<div class="textContent">
<div class="h1">{{stock.name}}<div *ngIf="stock.increased"
style="color: green ; margin: 0 10px 0 10px; float: right;">▲</div>
<div *ngIf="!stock.increased" style="color: red ; margin: 0 10px 0 10px; float: right;">▼</div>
</div>
</div>
<div class="detail">Price: ${{stock.price}}
</div>
</div>
</div>
The app.component.ts uses BehaviorSubject and Observable from rxjs:
private webSocket: WebSocket;
private subscription: Subscription = Subscription.EMPTY;
public stock: Stock = new Stock();
public stockSubject: BehaviorSubject<Stock> = new BehaviorSubject<Stock>(this.stock);
public stock$: Observable<Stock> = this.stockSubject.asObservable();
this.webSocket = new WebSocket('ws://localhost:8080/stocks');
this.subscription = this.stock$.subscribe();
this.webSocket.onmessage = (event) => {
this.stock = JSON.parse(event.data.toString());
this.stockSubject.next(this.stock);
console.log(JSON.stringify(this.stock));
};
The Stock object has public attributes to avoid using the any type:
export class Stock {
name: string;
icon: string;
price: number;
increased: boolean;
constructor () {
this.name = 'Amazon';
this.icon = '';
this.price = 0;
this.increased = false;
}
}
The Angular application is a web service client that receives updated stock prices and calls next on the BehaviorSubject:
{"name":"Amazon","icon":"https://cdn.cdnlogo.com/logos/a/77/amazon-dark.svg","price":12.17,"increased":false}
{"name":"Amazon","icon":"https://cdn.cdnlogo.com/logos/a/77/amazon-dark.svg","price":12.72,"increased":true}
{"name":"Amazon","icon":"https://cdn.cdnlogo.com/logos/a/77/amazon-dark.svg","price":12.71,"increased":false}
What is missing to display the updated stock properties on the HTML page? The original example does not use Subjects or Observables and worked for the author.
Solution
Please find below working example for your reference!
import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import { BehaviorSubject, map, Observable, Subscription, interval } from 'rxjs';
import 'zone.js';
import { Stock } from './stock.model';
@Component({
selector: 'app-root',
standalone: true,
imports: [CommonModule],
template: `
<div class="card" *ngIf="stock$ | async as stockData">
<div class="textBox">
<div class="textContent">
<div class="h1">{{stockData.name}}<div *ngIf="stockData.increased"
style="color: green ; margin: 0 10px 0 10px; float: right;">▲</div>
<div *ngIf="!stockData.increased" style="color: red ; margin: 0 10px 0 10px; float: right;">▼</div>
</div>
</div>
<div class="detail">Price: $ {{stockData.price}} </div>
</div>
</div>
`,
})
export class App {
// private webSocket: WebSocket;
public stock: Stock = new Stock();
public stockSubject: BehaviorSubject<Stock> = new BehaviorSubject<Stock>(
this.stock
);
public stock$: Observable<Stock> = this.stockSubject.asObservable();
// this.webSocket = new WebSocket('ws://localhost:8080/stocks');
// this.subscription = this.stock$.subscribe();
ngOnInit() {
interval(1000)
.pipe(
map(() => ({
data: {
name: 'Amazon',
increased: Math.random() < 0.5,
price: Math.floor(Math.random() * 100) + 1,
},
}))
)
.subscribe(this.onmessage);
}
onmessage = (event: any) => {
this.stock = event.data;
this.stockSubject.next(this.stock);
};
}
bootstrapApplication(App);
Answered By - Naren Murali
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.