Reputation: 1343
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();
}
});
Upvotes: 0
Views: 738
Reputation: 48968
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
Upvotes: 1
Reputation: 8411
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.
Upvotes: 2