Search code examples
angulartypescriptfirebase-realtime-databasechart.jsangularfire2

Creating a real time line chart using chartjs and firebase realtime db


I am using angular 7 with chart.js library. I have created a line chart based on the data from firebase realtime database pulled using angularfire2 library.

The data shows number of messages sent per hour. This works fine. however, i want to update the chart in real time as data gets updated.

the below code is for static version. plz advise

 <div style="display: block;padding-top:30px">
                <canvas baseChart
                [chartType]="'line'"
                [datasets]="chartData"
                [colors]="colors"
                [labels]="chartLabels"
                [options]="chartOptions"
                [legend]="true">
                </canvas>
              </div>

for .ts

@ViewChild(BaseChartDirective, null)
  public chart: BaseChartDirective;

 chartOptions = {
    responsive: true,
    legend: {
      display: true
   },
   scales: {
    yAxes: [{
        ticks: {
            beginAtZero: true
        }
    }]
    }
  };


  chartData = [
    { data: [], label: 'Messages/hour'
  }
  ];

  colors = []
  chartLabels = [];

async ngOnInit() {

    let resp = await this.dataSvc.fetchHourlyMessages(this.core.orgName)

    for(let key of Object.keys(resp)){
      this.chartData[0].data.push(resp[key].messages)
      let hour = resp[key].hour
      this.chartLabels.push(hour)
    }
    this.chart.chart.update()

  }

the service is:

fetchHourlyMessages(orgName:string){

    return new Promise((resolve, reject) =>
    {
      this.db.list(orgName + '/stats/messages/hourly/', ref => ref.orderByChild("messages").limitToLast(12)).valueChanges().subscribe(
        (res) => {
                    resolve(res)},
        (err) => { 
                    console.log("hitting error:" + err); reject(err)
                }
      )
   })

  }

The data looks like below

/stats
    /messages
       /hourly
         /1pm
           messages: 3
           hour: 1pm
         /2pm
           messages: 4
           hour: 2pm


Solution

  • So what happen here is you only call this function once cause you made a promise. What you have to do is use an observer. An observer will return the value and the changed value of the socket with the valueChanges option of firebase. To do this you have to change your services:

    fetchHourlyMessages(orgName:string){
      return this.db.list(orgName + '/stats/messages/hourly/', ref => ref.orderByChild("messages").limitToLast(12))
    }
    

    And on your ngOnInit:

      this.dataSvc.fetchHourlyMessages(this.core.orgName).valueChanges().subscribe((resp: any) => {
    
        for(let key of Object.keys(resp)){
          this.chartData[0].data.push(resp[key].messages)
          let hour = resp[key].hour
          this.chartLabels.push(hour)
        }
        this.chart.chart.update()
      });