Reputation: 86747
I'm having a single page application, but with different tabs.
Only for one tab I want to show a google charts
. I don't want to include and load the charts js file jsapi
directly, but only if the specific tab is accessed.
Therefore I have to add the js as follows dynamically:
var script = document.createElement('script');
script.src = '//http://www.google.com/jsapi?ext.js';
document.body.appendChild(script);
Problem: how can I detect when the js has been completely loaded, so that I can continue as follows?
if (whenJspaiLoaded()) {
google.load('visualization', '1', {packages: ['corechart']});
google.setOnLoadCallback(drawChart); //my custom function
}
Upvotes: 1
Views: 1372
Reputation: 2800
Give Angular Google Chart a try. It abstracts the chart management behind a directive so you just pass it an object with the data, options, and chart type and it does the rest. It doesn't add the script tag until the first time it loads the directive or you ask for the promise that returns when the library loads. If you really want to suppress library loading you're need to be sure the directive element isn't loaded in the background until you actually need it. So use ng-if instead of ng-show or put it in a different routed view.
Upvotes: 2
Reputation: 409
Here is my implementation
<style>
.preloader {
height:350px; background:url(images/719.gif) left no-repeat;
}
</style>
<div id="columnchart_material"><div class="preloader"> </div></div>
<script type="text/javascript"
src="https://www.google.com/jsapi?autoload={
'modules':[{
'name':'visualization',
'version':'1',
'packages':['corechart']
}]
}">
</script>
<script>
google.setOnLoadCallback(drawChart);
function drawChart() {
var chart = new google.visualization.LineChart(document.getElementById('columnchart_material'));
options.title='English'
options.series[1].lineWidth = 0;
chart.draw(data,options );
}
</script>
Codepen click here
Upvotes: 2
Reputation: 86747
As there seems to be no working solution on the net so far, I hope this will help someone in future. Key concept is to delay both the js
file loading and the charts component initialization with a callback
.
The service to load the js files:
app.service('gchart', ['$window', '$q', '$rootScope', function ($window, $q, $rootScope) {
var deferred = $q.defer();
//run when the jsapi is loaded
$window.callback = function () {
$window.google.load('visualization','1',{
packages: ['corechart'],
callback: function() {
//again having a callback to wait for the visualization to load
$rootScope.$apply(function() {
deferred.resolve();
});
}
});
}
// dynamically adding the js file on page access
var script = document.createElement('script');
script.src = '//www.google.com/jsapi?callback=callback';
document.body.appendChild(script);
return deferred.promise;
}]);
Usage as directive:
app.directive(.., ['gchart', function(.., gchart) {
return {
//...
link: function(scope, elm, attr) {
scope.init = function() {
var viz = new google.visualization.arrayToDataTable(data);
//add options, linechart, draw, whatever
};
// delay the creation until jsapi files loaded
loadGoogleChartAPI.then(function () {
scope.init();
}, function () {
//ignore
});
}
}
}
Upvotes: 0
Reputation: 1223
Async function with callback:
function async(u, c) {
var d = document, t = 'script',
o = d.createElement(t),
s = d.getElementsByTagName(t)[0];
o.src = '//' + u;
if (c) { o.addEventListener('load', function (e) { c(null, e); }, false); }
s.parentNode.insertBefore(o, s);
}
Usage:
async('www.google.com/jsapi?ext.js', function() {
google.load('visualization', '1', {packages: ['corechart']});
google.setOnLoadCallback(drawChart);
});
from : https://stackoverflow.com/a/12821561/3279156
Upvotes: -1