简体   繁体   中英

How can I use libraries included in <script> tags from a AngularJS Controller

I am trying to use the d3 library inside my controller. From what I researched, one of the way do that is to create a directive to append the script with the attributes needed. But I am still not able to get the reference I need to the d3 library...

This is my directive

angular.module('reportCtrl', [])

.directive('myCustomer', [function() {
    return {
        link: function(scope, element, attrs) {
            </script>
            angular.element('<script src="assets/lib/d3.js"></script>').append(element);
            angular.element('<script src="assets/lib/d3.promise.js"></script>').append(element);
        }
    }
}])

In my controller, I go to use the d3 reference. But I get undefined error...I almost need to wait for this script to load. But problem is that reportCtrl is inside another "mainController" and I cannot seem to rely on app's lifecycle consistently.

This is my controller...

.controller('reportController', function($scope, $http) {

    return $http.get('/api/admin/svc_spec_file_map')
    .success(dataset => {
        var container = d3.select('div.sheet').node();
}
});

这是正在发生的事情的流程...

First approach:

Define the script src in the index.html file. You can do this before the script src of the AngularJS mechanism - modules, controllers etc.

Then you can have access to the D3 variable in all of the scripts that are coming after it.

Second approach:

If the d3 library has an extension for AngularJS you can inject this as a dependent module. You better check this.

Third approach:

using webpack you can import the D3 direct/lazy loaded to the directive you need, but using dynamic import:

import('path/to/d3').then(d3 => {
  // do something with d3.default()
})

Key point

You should think of it a simple JS: if you define the D3 variable before initing the AngularJS framework, the D3 variable will be available in any of the AngularJS app.

It is bizarre that you are loading these scripts from a directive as directives can be added and removed from the DOM.

It would be wiser to load them from a service:

app.service('d3Loader', function($rootElement,$q) {
    var promise;
    this.load = function() {
        promise = promise || loadD3();
        return promise;
    };
    function loadD3 () {
        var defer = $q.defer();
        var d3url = "//unpkg.com/d3/dist/d3.js"; 
        var s = document.createElement("script");
        s.onload = function(ev) {
          defer.resolve(d3);
        };
        s.onerror = function(ev) {
          defer.reject(ev)
        };
        s.src=d3url;
        $rootElement[0].appendChild(s);
        return defer.promise;
    }
})

Usage:

d3Loader.load().then(function(d3) {
    console.log(d3);
});

The DEMO on PLNKR

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM