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!