Reputation: 51
I'm struggling to create an angular2 component that would call google chart api and display a google-chart (https://developers.google.com/chart/interactive/docs/quick_start). This usually leads to unexplained mistakes or just the browser loading forever.
EDIT : full updated test files added below
See also in plnkr here.
To be more specific, these are the test files I use to identify the point where things start to go wrong :
index.html
<html>
<head>
<title>Angular 2 QuickStart</title>
<script src="https://code.angularjs.org/tools/system.js"></script>
<script src="https://code.angularjs.org/tools/typescript.js"></script>
<script src="https://code.angularjs.org/2.0.0-alpha.46/angular2.dev.js"> </script>
<!--Load the AJAX API-->
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script>
System.config({
transpiler: 'typescript',
typescriptOptions: { emitDecoratorMetadata: true }
});
System.import('./app.ts');
</script>
</head>
<body>
<my-app>loading...</my-app>
</body>
</html>
And then, app.ts
import {bootstrap, Component} from 'angular2/angular2';
@Component({
selector: 'my-app',
template:`
<h1>Demo component my-app</h1>
<div id="cc" (click)="test($event)">Click me</div>
`
})
class AppComponent {
constructor() {
console.log("Constructor was called");
}
test(event) {
console.log("Event :",event);
console.log("Test :", google);
console.log("Document object by id",document.getElementById("cc"));
// Callback that creates and populates a data table,
// instantiates the pie chart, passes in the data and
// draws it.
function drawChart() {
console.log("Callback is entered ");
// Create the data table.
var data = new google.visualization.DataTable();
data.addColumn('string', 'Topping');
data.addColumn('number', 'Slices');
data.addRows([
['Mushrooms', 3],
['Onions', 1],
['Olives', 1],
['Zucchini', 1],
['Pepperoni', 2]
]);
// Set chart options
var options = {'title':'How Much Pizza I Ate Last Night',
'width':400,
'height':300};
// Instantiate and draw our chart, passing in some options.
var chart = new google.visualization.PieChart(document.getElementById('cc'));
chart.draw(data, options);
}
console.log("Google object : ", google);
console.log("Now, loading visualization api");
// Load the Visualization API and the piechart package.
google.load('visualization', '1.0', {'packages':['corechart']});
console.log("Now, setting callback");
// Set a callback to run when the Google Visualization API is loaded.
google.setOnLoadCallback(drawChart);
console.log("Callback was set");
}
}
bootstrap(AppComponent);
And this is what console shows, when I click :
Constructor was called
app.ts:18 Event : MouseEvent {isTrusted: true}
app.ts:19 Test : Object {loader: Object}
app.ts:20 Document object by id <div id="cc">Click me</div>
app.ts:53 Google object : Object {loader: Object}
app.ts:54 Now, loading visualization api
app.ts:57 Now, setting callback
app.ts:60 Callback was set
Clearly, the callback is never entered into ?!
Anyone can help me sort out this issue ? Many thanks !
Upvotes: 2
Views: 6458
Reputation: 51
Finally, solved it by using a chart component to call a chart directive. The setter of that directive triggers the drawing. No further need to directly capture/manage drawing events.
Load google script from the top index.html file
<script type="text/javascript" src="https://www.google.com/jsapi">
</script>
<script type="text/javascript">
google.load('visualization', '1.0', {
'packages': ['corechart']
});
</script>
Create a "chart" directive to draw google chart (chart.directive.ts)
/**
* This directive will draw a chart from the array of records provided
*
* Note : the relevant jsapi scripts should be already available
* globally in the window.google object (see index.html)
**/
import {Directive, ElementRef, Input} from "angular2/core";
import {CORE_DIRECTIVES } from "angular2/common";
@Directive({
selector: "chart",
})
export class ChartDirective {
el: HTMLElement;
w: any; // To store the window, without generating errors in typescript on window.google
private _content: any[] = [];
// Setter for content will trigger drawing (or refreshing)
@Input()
set content(c: any[]) {
console.log("Setting content ...");
this._content = c;
this.draw();
}
get content() { return this._content; }
// Constructor inject a ref to the element
constructor(elementRef: ElementRef) {
console.log("Constructing chart directive");
this.w = window;
this.el = elementRef.nativeElement; // You cannot use elementRef directly !
// console.log("Native HTML :", this.el);
if (!this.w.google) { console.error("Hey ! It seems the needed google script was not loaded ?"); };
}
// Do the actual drawing
draw() {
// Create the data table.
let data = new this.w.google.visualization.DataTable();
data.addColumn("date", "Quand");
data.addColumn("number", "KG");
let rows = [];
for (let c in this._content) {
let d: Date = new Date(this._content[c].quand);
let k: number = +(this._content[c].kg); // Plus sign to force conversion sting -> number
// Only take into account records after the 'notBefore date'
if (d >= this._nbd) rows.push([d, k]);
}
data.addRows(rows);
// Create options
let options: any = {
// "width": 600,
"height": 300,
"curveType": "function"
};
// Instantiate and draw our chart, passing in some options.
(new this.w.google.visualization.LineChart(this.el))
.draw(data, options);
}
}
Use the directive in a chart component (chart.component) ...
import {Component } from "angular2/core";
import {CORE_DIRECTIVES } from "angular2/common";
import {MyModel} from "./mymodel.service.ts";
import {ChartDirective} from "./chart.directive.ts";
@Component({
selector: "chartPage",
templateUrl: "/components/chart.template.html",
directives: [CORE_DIRECTIVES, ChartDirective]
})
export class ChartComponent {
}
// Injecting my data model into chart component ...
constructor(private model: MyModel) {
console.log("Constructing chart component");
};
}
... using the following template for the chart
<chart [content]="model.content" ></chart>
Upvotes: 2
Reputation: 1156
I was having the same problem when trying to implement google charts into ionic2. Iam not sure what the problem is exactly, but it seems that
google.load('visualization', '1.0', {'packages':['corechart']});
takes too long to load and
google.setOnLoadCallback(drawChart);
is never executed. You can bypass this by adding the callback directly to the google.load() like this:
google.load('visualization', '1.0', {'packages':['corechart'], callback: drawChart});
Worked for me! and the charts are loading as desired. All credit for this solution goes to @davidkonrad:
https://stackoverflow.com/a/31040694
Hope it works!
Upvotes: 0