Search code examples
javascriptangularwebsockethighchartsreal-time

How to draw a highchart with websocket feeds?


This is an Angular-HighChart question. I am trying to feed data from a websocket to dynamically draw a line chart. Following are the code. HTML

<highcharts-chart 
  [Highcharts]="Highcharts_bt"
  [options]="chartOptions_bt"
  style="width: 100%; height: 400px; display: block;"
></highcharts-chart>

TS

import { Component, OnInit } from '@angular/core';
import * as Highcharts from 'highcharts';
import { webSocket } from 'rxjs/webSocket';
import { of, Subscription } from 'rxjs';
import { concatMap, delay } from 'rxjs/operators';

@Component({
  selector: 'app-crypto-realtime',
  templateUrl: './crypto-realtime.component.html',
  styleUrls: ['./crypto-realtime.component.css']
})
export class CryptoRealtimeComponent {
  title = 'Angular-RxJsWebSocket-HighCharts';
  rate_bt: any;

  //rate$: Subscription;
  Highcharts_bt: typeof Highcharts = Highcharts;

  chardata_bt: any[] = [];

  chartOptions_bt: any;

  subject_bt = webSocket('wss://ws.coincap.io/prices?assets=bitcoin');

  constructor() { 
    this.chartOptions_bt = {
      series: [{
        name: 'Bitcoin',
        data: this.chardata_bt,
        color: 'blue',
      }, ],
      chart: {
        type: "line",
        zoomType: 'x'
      },
      title: {
        text: "Price of BitCoin",
      },
    };
  }

  ngOnInit() {
    this.rate_bt = this.subject_bt.pipe(
      concatMap(item => of (item).pipe(delay(0)))
    ).subscribe(data => {
      this.rate_bt = data;
      let curr_rate = Number(this.rate_bt.bitcoin);
      this.chardata_bt.push(curr_rate);
    });
  }
}

The problem is, although this.chartOptions_bt.series[0].data is updating, the chart is not drawing, that is, no data point is posted onto the chart. What am I missing here?

I also added the redraw:

ngOnInit() {
    this.rate_bt = this.subject_bt.pipe(
      concatMap(item => of (item).pipe(delay(0)))
    ).subscribe(data => {
      this.rate_bt = data;
      let curr_rate = Number(this.rate_bt.bitcoin);
      this.chardata_bt.push(curr_rate);

      for (let i = 0; i < this.Highcharts_bt.charts.length; i ++) {
        let a_chart = this.Highcharts_bt.charts[i];
        if (a_chart) {
          a_chart.redraw();
        }
      }
    });
  }

Still, it does not change anything.


Solution

  • Using setData can resolve this matter.

    ngOnInit() {
        console.log(this.Highcharts_bt);
    
        this.rate_bt = this.subject_bt.pipe(
          concatMap(item => of (item).pipe(delay(0)))
        ).subscribe(data => {
          this.rate_bt = data;
          let curr_rate = Number(this.rate_bt.bitcoin);
          this.chardata_bt.push(curr_rate);
    
          let a_chart = this.Highcharts_bt.charts[0];
          if (a_chart) {
            a_chart.series[0].setData(this.chardata_bt, true);
          }
        });
    }
    

    This is also from Highcharts - redraw() vs. new Highcharts.chart