Я пытаюсь использовать библиотеку d3 внутри своего контроллера. Из того, что я исследовал, один из способов сделать это — создать директиву для добавления скрипта с необходимыми атрибутами. Но я все еще не могу получить нужную мне ссылку на библиотеку d3...
Это моя директива
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);
}
}
}])
В моем контроллере я использую ссылку d3. Но я получаю неопределенную ошибку... Мне почти нужно дождаться загрузки этого скрипта. Но проблема в том, что reportCtrl находится внутри другого «mainController», и я не могу последовательно полагаться на жизненный цикл приложения.
Это мой контроллер...
.controller('reportController', function($scope, $http) {
return $http.get('/api/admin/svc_spec_file_map')
.success(dataset => {
var container = d3.select('div.sheet').node();
}
});
Странно, что вы загружаете эти скрипты из директивы, поскольку директивы можно добавлять и удалять из DOM.
Разумнее будет загрузить их из сервиса:
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;
}
})
Применение:
d3Loader.load().then(function(d3) {
console.info(d3);
});
Спасибо, но у меня это сработало только один раз. Впоследствии выполнения d3 все еще не определены :( не знаю почему. Это мой контроллер app.controller('reportController', function(d3Loader, $scope, $http) { d3Loader.load().then(function() { console.info(d3); }); })
Обновлен ответ, чтобы создать обещание $q
и удалить зависимость jQuery.
Первый подход:
Определите сценарий src в файле index.html
. Вы можете сделать это перед скриптом src механизма AngularJS — модулей, контроллеров и т. д.
После этого вы сможете получить доступ к переменной D3 во всех сценариях, следующих за ней.
Второй подход:
Если в библиотеке d3 есть расширение для AngularJS, вы можете внедрить его как зависимый модуль. Лучше проверь это.
Третий подход:
используя webpack, вы можете импортировать D3 direct/lazy, загруженный в нужную вам директиву, но используя динамический импорт:
import('path/to/d3').then(d3 => {
// do something with d3.default()
})
Ключевой момент
Вы должны думать об этом как о простом JS: если вы определите переменную D3 перед запуском фреймворка AngularJS, переменная D3 будет доступна в любом приложении AngularJS.
это никогда не сработает. сценарии выполняются при загрузке страницы, прежде чем контроллер сможет запустить и добавить сценарии в HTML. Вам нужно будет фактически вручную выполнить любые сценарии, которые вы загружаете таким образом; Найдите «ленивую загрузку»; должно быть множество статей и примеров того, как это сделать.