How to generate a dynamic timeline graph using ChartJS alongside Firebase's real-time database

Working with angular 7 alongside the chart.js library has been quite interesting. I managed to create a line chart using data pulled from the firebase realtime database via the angularfire2 library.

The chart currently displays the number of messages sent per hour, but my goal is to have it update in real-time as new data comes in.

Below you'll find the code for the static version. Any advice on how to achieve real-time updating would be much appreciated.

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

And here's the .ts file:

@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()

  }

This is the service used:

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 structure of the data is as follows:

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

Answer №1

What we see happening here is that the function is only called once due to a promise being made. To solve this, an observer needs to be used. The observer will provide the value and any changes in the socket's value using the valueChanges option of firebase. Here is how you can modify your services:

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

In your ngOnInit method:

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()
  });

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Material Modules are causing issues with AOT compilation

I'm encountering multiple errors that all share a similar pattern: ERROR in ./node_modules/@angular/material/button/typings/index.ngfactory.js Module build failed: Error: Invalid name: "@angular/material/button" at ensureValidName (C:\path&b ...

MongoMemoryServer - Dealing with Unexpected Errors

Currently, I am conducting tests on a typescript express-mongoose app using jest, supertest, and mongo-memory-server. Interestingly, all the tests are passing successfully, but an error keeps popping up in every test involving mongo-memory-server. It see ...

The excessive repetition in Angular flex layout is becoming overwhelming

I discovered and started using the responsive API provided by angular flex layout. While most of the time it works as intended, there are instances where I find myself duplicating directives in the code. Here's a simplified example: <div> &l ...

Do I need to convert AngularJS to .ts for an Angular/AngularJS hybrid application?

Currently in the process of upgrading from AngularJS v1.25 to Angular 14 using the ng-Upgrade approach outlined on angular.io/guide/upgrade. Adding an extra challenge, our main page is built with ASP.NET MVC 5, and I am aiming to incorporate the Angular CL ...

Guide on generating a multi-select dropdown list using numbers in JavaScript or React.js

In my current project simulation, I am tasked with choosing an option that corresponds to a number (1, 2, 3, 4, 5, 6....). For example, selecting option number 3 will dynamically generate 3 input elements. ...

Pushing an object into an array that is a state object in React using Typescript, the proper way

I am working on maintaining an array of objects stored in a state object. Each time the Add button is clicked, I need to push a new object to this array and store it. However, I am facing issues with fetching proper values when trying to submit. Where cou ...

Having trouble converting customized tabs into Bootstrap navigation tabs?

Creating custom tabs with unique tab logic <!-- <lntds-tabs [selectedIndex]="selectedTabIndex" (selectedTabChange)="tabChanged($event)"> --> <!-- <lntds-tab class="custom-tab-group lntdstabsco ...

angular-universal | firestore-admin | code: 'app/invalid-authentication' | connection timeout

import * as admin from 'firebase-admin'; var serviceAccount = require('./keys/keyfile.json'); admin.initializeApp({ credential: admin.credential.cert(serviceAccount), databaseURL: "https://test.firebaseio.com" }); var registrationT ...

What is the best way to keep an item from list A after it has been moved to list B using PrimeNg's drag and drop feature?

I am facing an issue with the drag and drop feature in PrimeNg. I have a container that contains both a table and an unordered list. My goal is to be able to drag an element from the unordered list and drop it into the table, while still retaining the drag ...

Securing routes in Angular without relying on LocalStorage or Cookies by implementing an Auth Guard

Currently, I am working on implementing an authentication guard in Angular. Instead of the conventional method of checking local storage or cookies to verify user authentication, I am utilizing API endpoints that respond with 200 OK if a httponly cookie co ...

What steps can I take to improve my code and fix lint errors?

I've been working on creating test cases for a switch case scenario, and so far I have two test cases in place. However, I'm encountering a lint error that requests me to update or refactor the function in order to avoid duplicating code. Since m ...

Branching tests within a method in Angular

Recently, I've implemented a method in my TypeScript file that contains 3 different branches. Now, as I'm working with Angular and Jasmine, I find myself wondering - how can I effectively test all of these branches? getAges(ages: Ages) { if ...

Injecting a service into a base class in Angular, but not in the sub-class, then utilizing the parent service in the sub-

When working with Angular 7 and Typescript, I have a base class that relies on multiple services and has around 40 subclasses. Instead of adding these services to each subclass constructor and passing them to super(), I am looking for a more efficient wa ...

After compilation, what happens to the AngularJS typescript files?

After utilizing AngularJS and TypeScript in Visual Studio 2015, I successfully developed a web application. Is there a way to include the .js files generated during compilation automatically into the project? Will I need to remove the .ts files bef ...

Tips for sending an Object within a multipart/form-data request in Angular without the need for converting it to a string

To successfully pass the object in a "multipart/form-data" request for downstream application (Java Spring) to receive it as a List of custom class objects, I am working on handling metadata objects that contain only key and value pairs. Within the Angula ...

Differences between Angular's form builder and form control and form groupIn the

What are the benefits of using form control and form group instead of form builder? Upon visiting this link, I discovered: The FormBuilder simplifies creating instances of a FormControl, FormGroup, or FormArray by providing shorthand notation. It helps ...

Changing the visibility of a DOM element in Angular 2 by

I need assistance with an Angular project. I am looking to implement functionality similar to jQuery's toggle method: $( ".target" ).toggle(); Specifically, my objective is to hide the content of child elements when the parent element is clicked. Ho ...

Angular 2's updated router feature, routerCanReuse, provides improved functionality

I'm curious about the changes in the Angular 2 router, particularly the removal of the CanReuse interface. Is there another feature in the router that can achieve the same functionality of forcing a component reload? ...

Is a no-cache directive required in Angular index.html?

Is there a way to prevent index.html from caching and instead have it constantly reloaded? I would prefer not to have cache enabled. Any suggestions on how I can achieve this? Thank you! ...

Separating React props based on multiple Typescript interfaces

Is there a way to split the props object in React based on an Typescript interface that extends multiple other interfaces? Alternatively, I could duplicate the props and pass them to components that don't need them, but that would not be the most effi ...