AngularJS: Как сделать angular нагрузку script внутри ng-include?
Привет, я создаю веб-страницу с angular. Проблема в том, что есть что-то уже построенное без angular, и я должен включить их также
Проблема в этом.
У меня есть что-то вроде этого в моем main.html:
<ngInclude src="partial.html">
</ngInclude>
И у моего partial.html есть что-то вроде этого
<h2> heading 1 <h2>
<script type="text/javascript" src="static/js/partial.js">
</script>
И мои partial.js не имеют ничего общего с angularjs. nginclude работает, и я могу видеть html, но я не вижу, что загружаемый файл javascript вообще загружается. Я знаю, как использовать firebug/chrome-dev-tool, но я даже не вижу, как выполняется запрос сети. Что я делаю неправильно?
I knwo angular имеет особое значение для тега script. Могу ли я переопределить его?
Ответы
Ответ 1
Принятый ответ не будет работать с версией 1.2.0-rc1 + (Github).
Здесь быстрое исправление, созданное endorama:
/*global angular */
(function (ng) {
'use strict';
var app = ng.module('ngLoadScript', []);
app.directive('script', function() {
return {
restrict: 'E',
scope: false,
link: function(scope, elem, attr) {
if (attr.type === 'text/javascript-lazy') {
var code = elem.text();
var f = new Function(code);
f();
}
}
};
});
}(angular));
Просто добавьте этот файл, загрузите модуль ngLoadScript
в качестве зависимости от приложения и используйте type="text/javascript-lazy"
как тип для script, который будет лениво загружаться в частичном:
<script type="text/javascript-lazy">
console.log("It works!");
</script>
Ответ 2
Короткий ответ: AngularJS ( "jqlite" ) не поддерживает это. Включите jQuery на своей странице (до включения Angular), и он должен работать. См. https://groups.google.com/d/topic/angular/H4haaMePJU0/discussion
Ответ 3
Я попытался использовать неемзи, но для меня это не сработало с использованием 1.2.0-rc.3. Тег script будет вставлен в DOM, но путь javascript не будет загружен. Я подозреваю, что это связано с тем, что javascript, который я пытался загрузить, был из другого домена/протокола.
Поэтому я применил другой подход, и именно это я придумал, используя в качестве примера карты Google (Gist)
angular.module('testApp', []).
directive('lazyLoad', ['$window', '$q', function ($window, $q) {
function load_script() {
var s = document.createElement('script'); // use global document since Angular $document is weak
s.src = 'https://maps.googleapis.com/maps/api/js?sensor=false&callback=initialize';
document.body.appendChild(s);
}
function lazyLoadApi(key) {
var deferred = $q.defer();
$window.initialize = function () {
deferred.resolve();
};
// thanks to Emil Stenström: http://friendlybit.com/js/lazy-loading-asyncronous-javascript/
if ($window.attachEvent) {
$window.attachEvent('onload', load_script);
} else {
$window.addEventListener('load', load_script, false);
}
return deferred.promise;
}
return {
restrict: 'E',
link: function (scope, element, attrs) { // function content is optional
// in this example, it shows how and when the promises are resolved
if ($window.google && $window.google.maps) {
console.log('gmaps already loaded');
} else {
lazyLoadApi().then(function () {
console.log('promise resolved');
if ($window.google && $window.google.maps) {
console.log('gmaps loaded');
} else {
console.log('gmaps not loaded');
}
}, function () {
console.log('promise rejected');
});
}
}
};
}]);
Я надеюсь, что это будет полезно для кого-то.
Ответ 4
Это больше не будет работать с 1.2.0-rc1. Подробнее см. этот вопрос, в котором я опубликовал комментарий, описывающий быстрое обходное решение. Я также расскажу об этом здесь:
// Quick fix : replace the script tag you want to load by a <div load-script></div>.
// Then write a loadScript directive that creates your script tag and appends it to your div.
// Took me one minute.
// This means that in your view, instead of :
<script src="/path/to/my/file.js"></script>
// You'll have :
<div ng-load-script></div>
// And then write a directive like :
angular.module('myModule', []).directive('loadScript', [function() {
return function(scope, element, attrs) {
angular.element('<script src="/path/to/my/file.js"></script>').appendTo(element);
}
}]);
Не лучшее решение когда-либо, но эй, не помещайте теги script в последующие представления. В моем случае я должен сделать это, чтобы использовать Facebook/Twitter/и т.д. виджеты.
Ответ 5
ocLazyLoad позволяет лениво загружать скрипты в шаблонах/представлениях через маршрутизаторы (например, ui-router). Вот sniplet
$stateProvider.state('parent', {
url: "/",
resolve: {
loadMyService: ['$ocLazyLoad', function($ocLazyLoad) {
return $ocLazyLoad.load('js/ServiceTest.js');
}]
}
})
.state('parent.child', {
resolve: {
test: ['loadMyService', '$ServiceTest', function(loadMyService, $ServiceTest) {
// you can use your service
$ServiceTest.doSomething();
}]
}
});
Ответ 6
Я использовал этот метод для динамического загрузки файла script (внутри контроллера).
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = "https://maps.googleapis.com/maps/api/js";
document.body.appendChild(script);
Ответ 7
Чтобы динамически загружать recaptcha из ui-view
, я использую следующий метод:
В application.js
:
.directive('script', function($parse, $rootScope, $compile) {
return {
restrict: 'E',
terminal: true,
link: function(scope, element, attr) {
if (attr.ngSrc) {
var domElem = '<script src="'+attr.ngSrc+'" async defer></script>';
$(element).append($compile(domElem)(scope));
}
}
};
});
В myPartial.client.view.html
:
<script type="application/javascript" ng-src="http://www.google.com/recaptcha/api.js?render=explicit&onload=vcRecaptchaApiLoaded"></script>
Ответ 8
К сожалению, все ответы в этом сообщении не сработали для меня. Я продолжал получать следующую ошибку.
Не удалось выполнить 'write' в 'Document': невозможно написать в документ из асинхронно загруженного внешнего script, если только он явно открыт.
Я узнал, что это происходит, если вы используете некоторые сторонние виджеты (востребованные в моем случае), которые также вызывают дополнительные внешние файлы JavaScript и пытаются вставить HTML. Глядя на консоль и код JavaScript, я заметил несколько строк:
document.write("<script type='text/javascript' "..."'></script>");
Я использовал сторонние файлы JavaScript (htmlParser.js и postscribe.js) из: https://github.com/krux/postscribe. Это решило проблему в этом сообщении и зафиксировало вышеуказанную ошибку одновременно.
(Это был быстрый и грязный путь в сжатые сроки, который у меня есть сейчас. Мне неудобно использовать стороннюю библиотеку JavaScript. Надеюсь, кто-то может придумать более чистый и лучший способ.)
Ответ 9
Я попытался использовать Google reCAPTCHA явно. Вот пример:
// put somewhere in your index.html
<script type="text/javascript">
var onloadCallback = function() {
grecaptcha.render('your-recaptcha-element', {
'sitekey' : '6Ldcfv8SAAAAAB1DwJTM6T7qcJhVqhqtss_HzS3z'
});
};
//link function of Angularjs directive
link: function (scope, element, attrs) {
...
var domElem = '<script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit" async defer></script>';
$('#your-recaptcha-element').append($compile(domElem)(scope));
}