2016-04-21 51 views
1

我有一个单页面应用程序,但具有不同的选项卡。 仅限一个标签我想显示google charts。我不想直接包含并加载图表js文件jsapi,但仅限于访问特定选项卡。如何使用angularjs延迟加载谷歌jsapi图表?

所以我必须添加JS为动态如下:

var script = document.createElement('script'); 
script.src = '//http://www.google.com/jsapi?ext.js'; 
document.body.appendChild(script); 

问题:如何检测时,JS已经完全加载,这样我就可以继续如下?

if (whenJspaiLoaded()) { 
    google.load('visualization', '1', {packages: ['corechart']}); 
    google.setOnLoadCallback(drawChart); //my custom function 
} 

回答

0

因为似乎是在网络上没有可行的解决方案至今,我希望这可以帮助某个人真实存在。关键概念是将js文件加载和图表组件初始化与callback延迟。

加载js文件的服务:

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

使用的指令:

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

异步函数的回调:

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

用法:

async('www.google.com/jsapi?ext.js', function() { 
    google.load('visualization', '1', {packages: ['corechart']}); 
    google.setOnLoadCallback(drawChart); 
}); 

来自:https://stackoverflow.com/a/12821561/3279156

+0

是'addEventListener'独立浏览器吗? IE,Chrome,FF,Opera? – membersound

+0

@membersound for IE你可以检查这个,http://stackoverflow.com/a/6927800/3279156更多关于兼容性检查:http://caniuse.com/#feat=addeventlistener – sreeramu

2

这是我实现

<style> 
    .preloader { 
     height:350px; background:url(images/719.gif) left no-repeat; 
    } 
    </style> 
    <div id="columnchart_material"><div class="preloader">&nbsp;</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

+0

你在哪里加载'jsapi'并初始化'corechart'模块?懒加载部分在哪里? – membersound

1

Angular Google Chart一试。它抽象指令背后的图表管理,因此您只需将它传递给一个包含数据,选项和图表类型的对象,剩下的就完成了。它不会在第一次加载指令之前添加脚本标记,或者您要求在加载库时返回的承诺。如果你真的想压制库加载,你需要确保指令元素不会在后台加载,除非你真的需要它。因此,使用ng-if而不是ng-show或将其放在不同的路由视图中。

+0

尽管这可能起作用,但它是一种附加依赖性。没有人知道将来会支持多久,所以我不想依赖它。 – membersound

+1

可以理解的是,我最近没有多少时间来处理它,只是在最后一周左右,其他人才有兴趣提出维护拉取请求,因为我没有时间写更新。尽管我仍然在这里,但我总是尽可能快地回答关于gitter的github问题和问题。 – nbering