Financial application with amCharts on Angular
In a financial world you need pretty charts. Angular is a standard for 4 tier architecture with Single Page Application consuming microservices. For Angular there are amCharts.

Smart application should be interactive. We can attach click event handler to data series. We can retrieve from the event a reference to exact data item which triggered event emission.
series.slices.template.events.on("hit", function(event) {
let symbol = data[event.target.dataItem.index].symbol;
if (AppComponent.selectedModelProduct.has(symbol))
AppComponent.selectedModelProduct.delete(symbol);
else
AppComponent.selectedModelProduct.add(symbol);
});
We can wrap access to microservices providing data using Service component with static methods. For then we need static HttpClient:
import { HttpClientModule, HttpClient, HttpHandler, HttpXhrBackend, HttpHeaders, HttpResponse } from '@angular/common/http';
import { Injector} from '@angular/core';export class CustomerDataService {
private static injector = Injector.create({
providers: [
{ provide: HttpClient, deps: [HttpHandler] },
{ provide: HttpHandler, useValue: new HttpXhrBackend({ build: () => new XMLHttpRequest }) },
],
});
private static http: HttpClient = CustomerDataService.injector.get(HttpClient); ...
}
Then we can do:
public static getStockData(symbol: string, points: number) : Observable<any> {
let payload = CustomerDataService.http.get('https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol='+symbol+'&outputSize='+points+'&apikey='+CustomerDataService.API_KEY).pipe(
map(root => CustomerDataService.dailyStocksTransform(root["Time Series (Daily)"], symbol))
);
return payload;
}

HttpClient in Angular parses JSON transparently and we receive Object with properties. To perform mapping we need to use Object.defineProperty. Dynamic properties cannot be copied between objects with Object.assign or spread operator instanceC = {…instanceA, …instanceB}. These 2 patterns work only with default static properties.

In case we need execute many HTTP calls we can do then in parallel with rxjs. We gather Observables from HttpClient.get and merge all responses with
merge(...httpGets).pipe(mergeAll())
then get flat array via
merge(...httpGets).pipe(mergeAll()).pipe(toArray).subscribe((data: any[]) => { /* operate on data */ }


We can focus user on newly populated chart with:
document.getElementById('valueChart').scrollIntoView();
Any other nice tricks?
Yes, modern fonts:
constructor(private zone: NgZone, @Inject(DOCUMENT) private document: any, private renderer: Renderer) {}private addGoogleFont(name: string) {
const elem = this.renderer.createElement(this.document.head, 'link');
this.renderer.setElementProperty(elem, 'href', 'https://fonts.googleapis.com/css?family='+name.replace(' ','+'));
this.renderer.setElementProperty(elem, 'rel', 'stylesheet');
}private enableRwd() {
const elem = this.renderer.createElement(this.document.head, 'meta');
this.renderer.setElementProperty(elem, 'content', 'width=device-width, initial-scale=1');
this.renderer.setElementProperty(elem, 'name', 'viewport');
}ngAfterViewInit() {
this.enableRwd();
this.addGoogleFont('Archivo');
this.addGoogleFont('Lato');
this.addGoogleFont('Material Icons');
}
Yes, column layout:
<div class="row">
<div class="column">
<div id="chartPortfolioReal" style="width: 500px;"></div>
</div>
<div class="column">
<div id="chartPortfolioModel" style="width: 500px;"></div>
</div>
</div>* { box-sizing: border-box; }
.column { float: left; width: 50%; padding: 10px; }
.row:after { content: ""; display: table; clear: both; }
@media screen and (max-width: 800px) {
.column { width: 100%; }
}
Enjoy Angular and amCharts!