Show real-time data using Angular6 and GoogleChart

In my project, I am utilizing Angular Cli6, angularfire2, and Firebase to create a timeline using GoogleChart.

//GoogleChart.service

declare var google: any;

export class GoogleChartsBaseService 
{
  constructor() { google.charts.load('current', {'packages':["timeline"]}); }

   protected buildChart(data: any[], chartFunc: any, options: any) : void {
   var func = (chartFunc, options) => 
        {
        var datatable = google.visualization.arrayToDataTable(data);
        chartFunc().draw(datatable, options); 
        };   
   var callback = () => func(chartFunc, options);
   google.charts.setOnLoadCallback(callback);
   }
}

TimelineChart.service

import { GoogleChartsBaseService } from './google-charts-base.service';
import { Injectable } from '@angular/core';
import { GanttChartConfig } from './../models/GanttChartConfig.model';

declare var google: any;

@Injectable()
export class GoogleGanttChartService extends GoogleChartsBaseService {

  constructor() { super(); }

  public BuildPieChart(elementId: string, data: any[], config: GanttChartConfig) : void {  
    var chartFunc = () => { return new google.visualization.Timeline(document.getElementById(elementId)); };
    var options = {
            traitement: config.traitement,
                  datedebut: config.datedebut,
            datefin: config.datefin,

      };

    this.buildChart(data, chartFunc, options);
  }
}

Timeline.html

<div id="{{elementId}}" ></div>

Timeline.ts

import { Component, Input, OnInit } from '@angular/core';
import { GoogleGanttChartService } from './../../services/google-gantt-chart.service';
import { GanttChartConfig } from './../../models/GanttChartConfig.model';
declare var google: any;

@Component({
  selector: 'app-gantt',
  templateUrl: './gantt.component.html',
  styleUrls: ['./gantt.component.scss']
})
export class GanttComponent implements OnInit {

    @Input() data: any[];
    @Input() config: GanttChartConfig;
    @Input() elementId: string;

 constructor(private _ganttChartService: GoogleGanttChartService) {}

    ngOnInit(): void {
        this._ganttChartService.BuildPieChart(this.elementId, this.data, this.config);
    }
}

Here is the component code to display the graph :

Component.html

 <div class="full"><app-gantt [data]="data1" [config]="config1" [elementId]="elementId1"></app-gantt></div>

Component.ts

import { Component, OnInit, Inject } from '@angular/core';
import { Patient } from '../models/patient.model';
import { Diagnostic } from '../models/diagnostic.model';
import { ActivatedRoute, Router } from '@angular/router';
import { PatientsService } from '../services/patients.service';
import { DiagnosticsService } from '../services/diagnostics.service';
import { PPSsService } from '../services/ppss.service';
import { AngularFireDatabase, AngularFireList, AngularFireObject, AngularFireAction } from 'angularfire2/database';
import { Location } from '@angular/common';
import { Observable } from 'rxjs/Observable';
import { GanttChartConfig } from './../models/GanttChartConfig.model';
import { PPS } from '../models/pps.model';
import {MAT_MOMENT_DATE_FORMATS, MomentDateAdapter} from '@angular/material-moment-adapter';
import {DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE} from '@angular/material/core';
import {MatDialog, MatDialogRef, MAT_DIALOG_DATA,MatDatepickerModule, MatFormFieldModule,} from '@angular/material';
import { FormControl, FormControlName, FormBuilder, FormGroup, Validators, ReactiveFormsModule, FormsModule } from '@angular/forms';
import { startWith } from 'rxjs/operators/startWith';
import { map, filter, catchError, mergeMap } from 'rxjs/operators';

  @Component({
  selector: 'app-pps',
  templateUrl: './pps.component.html',
  styleUrls: ['./pps.component.scss']
})
export class PpsComponent implements OnInit {
 patientid: string;
 patientToDisplay;
 ppssToDisplay;
 data1: any[];
 config1: GanttChartConfig;
 elementId1: string;

constructor( 
    private route: ActivatedRoute, 
    private location: Location,
    private patientsService: PatientsService,
    private diagnosticsService: DiagnosticsService,
    private ppssService: PPSsService,
    private router: Router, 
    public dialog: MatDialog, 
    ){ }
  ngOnInit() {

   this.route.params.forEach((urlParameters) => {
   this.patientid = urlParameters['id'];});
   this.patientToDisplay = 
   this.patientsService.getSinglePatient(this.patientid);
   this.ppssToDisplay = this.ppssService.getPPSByPatientid(this.patientid);


   this.data1 = [[ 'traitement','start', 'end'],
   [ 'Chirurgie',  new Date(2017, 3, 29), new Date(2017, 3, 30)],
   [ 'Chimiothérapie', new Date(2017, 2, 4),  new Date(2018, 2, 4)],
   [ 'Radiothérapie',   new Date(2017, 2, 4),  new Date(2018, 2, 4)]; 

   this.config1 = new GanttChartConfig( '',new Date (),new Date ());
   this.elementId1 = 'myGanttChart';

I have successfully displayed the graph with the predefined data in my component

https://i.sstatic.net/3d5Ag.jpg

However, the actual data is stored in Firebase as shown below:

https://i.sstatic.net/Gwcl4.png

To retrieve and populate the chart with data from Firebase, I used an observable from angularfire2

DATA.Service.TS

getPPSByPatientid(Patientid: string){
return this.database.list('/ppss', ref => ref.orderByChild("Patientid").equalTo(Patientid)).valueChanges();
}

I attempted to retrieve the data in my component .ts but encountered issues where Console.log(this.data1) resulted in an array of undefined

let interestingFields = [ 'treatement','dateA', 'dateB'];
    this.ppssToDisplay.subscribe(obj => {
      this.data1 = [
        interestingFields,
        interestingFields.map(field => obj[field]),
      ];
    console.log(this.data1);
    });


Error:

    core.js:1598 ERROR Error: Uncaught (in promise): Error: Not an array Error: Not an array

I wanted to provide all the relevant code for better understanding. My question now is whether I should stick with the current approach or consider using a loop in the template to dynamically populate the chart?

Also, if anyone could lend me some advice on how to overcome this issue, it would be greatly appreciated!

Answer №1

It appears that you have successfully found the correct solution. However, there is a slight issue when transferring your data to data1.

In order for the retrieved data to align with the pattern of the data stored in memory, it is essential to iterate through it from the perspective of the retrieved data:

this.ppssToDisplay.subscribe(ppsList => {
  this.data1 = [
    interestingFields,
    ...ppsList.map(pps => interestingFields.map(field => pps[field]))
    ];
});

By following these steps, your problem should be resolved.

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

organize and identify a JSON data using sorting and matching techniques

Having a JSON structure as shown below: [ { "id": "1", "freq": "1", "value": "Tiruchengode", "label": "Tiruchengode" }, { "id": "2", "freq": "1", "value": "Coimbatore", "label": " ...

The messages are not displayed by a reusable component that performs error validation for Reactive Forms

As I develop a web application using Angular 8, I am looking to create a reusable component that specifically displays error messages for my FormControls in order to avoid duplicating this logic throughout multiple sections of the application. I have imple ...

Access the input field value with PHP and store it in a variable

I previously looked into this issue, but the solution provided in the accepted answer did not resolve it for me: How to get input field value using PHP Below is an excerpt from my result.php file: ... <th> <form name="form" action= ...

Utilizing Optional Generics in TypeScript

I have created a wrapper for making API calls to a Strapi server. export const api = { post: async<T extends unknown, K>(url: string, body: Partial<T>, jwt?: string): Promise<K> => { try { const result = await ...

Generating a new array based on the keys found in a collection of objects

My array structure is quite complex with multiple objects containing different properties. let arr = [ { id: 1, name: "tony", hatColor: "blue" }, { id: 2, name: "larry", hatColor: "red" }, { id: 3, name ...

JQuery hover effect for dynamically added elements

Currently, I am working on a webpage that will trigger an ajax call upon loading. The response data in JSON format will be processed and the elements will then be added to the DOM as shown below: $.ajax({ type: 'POST', url: "http://mysite.de ...

Eliminate the ArrayOfObjects by filtering out the items with a specific ID

Here is an array of objects I've named mycart[]: [{"id":"6","quantity":"20","price":1500,"title":"casual blue strip"}, {"id":"10","quantity":"2","price":1500,"title":"casual blue round neck"},{"id":"5","quantity":20,"price":150,"title":"casual ...

Effectively retrieving an observable value or transferring a reference

As a newcomer to Angular and Typescript, I am facing an issue with passing a reference into the subscribe function. In my code snippet below, I am attempting to assign the user value from the observable, but it seems like the function is not recognizing th ...

Saving form data with a tinymce textarea, radio button, and checkbox to the database

My form contains multiple textarea fields, radio buttons, checkboxes, and a select input. Initially, I was able to submit the form using PHP without any issues. However, when I integrated TinyMCE with one of the textareas, I had to introduce JavaScript to ...

Jest: Issue with spyOn test failing despite async function being executed

Having trouble setting up a spyOn for an async function within a submodule. This issue is throwing me off because I've successfully implemented similar tests in the past. Here's an overview of the code: In routes.js: const express = require(&apo ...

Personalized validation using Bootstrap V5

Currently, I am using the default Bootstrap V5 form validator and I am interested in finding a way to create a custom parameter that must be checked for the input to be considered valid. Specifically, I want users to input their license plate, which should ...

The router is unable to direct when an item is clicked

I am encountering an issue with my routing setup - when I click on an item in the list-item component, it does not successfully route to the detail-component. Here is a glimpse of my source code: product-list.component.html: <h1>Product List Compon ...

unable to use split method in node js during put operation

I am currently working on an update action within my Node.js project. When new data is inputted, I am experiencing a peculiar issue. When I input fresh data, the split method functions properly. However, if I input the same data again, the split method fa ...

I am facing an issue where the conversations entered by the user and those generated by the AI are not being stored in my Postgres database within my next.js application

Whenever a question is posed to the AI and a response is provided, the issue arises where the information is not getting saved in the database. Despite including console.log statements in the route.ts file indicating that messages from both the AI and th ...

obtain a promise from an asynchronous function within a synchronous function

My issue arises when attempting to verify user credentials. The promise returned from login() is not resolved yet, resulting in loginResult being Promise{}. I understand that I need to await the result somehow, but I am struggling to find a solution. Any ...

Is there a way to limit the keys of T to only number fields, where T[keyof T] is a number

I'm looking to restrict the field parameter within this function: function calculate<T>(source: T[], field: keyof T) { for(const item of source) { } } The goal is to ensure that item[field] will always be a number. Is there a way to ac ...

I attempted various methods but was unable to successfully call the webmethod in the code behind using jQuery Ajax and Knockout

I have attempted various solutions, such as enabling friendly URL resolution and utilizing web method with session enabled, but unfortunately, the issue remains unresolved. I kindly request your assistance in resolving this matter. Here is my HTML code for ...

Erase the contents of a div by clicking a button

I am currently working on a game project that utilizes drag-and-drop functionality, similar to Blockly and Scratch. One of the key features I am trying to implement is the ability to clear the contents of a target container by clicking a Reset button. Desp ...

Using Javascript's regular expressions to add double quotes around JSON values that are not already enclosed in quotes

Dealing with improperly formatted JSON values can be a challenge. The response I am working with is from a Java Servlet, specifically a hashmap, over which I have no control. Initially, it looked like this: { response={ type=000, products=[{id=1,name=prod ...