2016-04-21 85 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