我有脚本块在局部视图上加载小部件,但如果我直接放在部分html页面上,我会收到以下错误:
“无法在'Document'上执行'write':无法写入 从异步加载的外部脚本转换为文档,除非 它被明确地打开了。“
示例脚本块是:
> <script type="text/javascript" defer="defer"
> src="http://svenskfotboll.se/widget.aspx?scr=table&ftid=57108&b1=%232f3841&f1=%23ffffff&b2=%23acbfda&f2=%23000000&b3=%23ffffff&f3=%23000000&b4=%23ececec&bo=%23dfdfdf&s=1"></script>
我将有多个小部件,所以我想要通过ng-repeat加载。请指教。
注意 我尝试显示静态方式为此我添加一个带有html / body标签的html页面并将其放在上面的脚本块然后通过iframe加载该页面然后它工作。但问题是在加载到iframe之前更新内容非常困难
答案 0 :(得分:1)
如果没有看到外部窗口小部件的某些内容,则很难准确诊断。我的第一印象是可能需要更改它才能返回一个文档,然后使用外部窗口小部件中的头函数名称在JS脚本块中分配该文档。有点像:
var someDoc = writeDoc();
其中writeDoc()
是小部件中的头函数,我假设它返回某种HTML文档。当然,脚本标签必须在您的声明之前。或者,根据您的ng-repeat
要求,您可以使用以下内容:
ng-repeat="{{writeDoc()}}"
在列表块或甚至是一个选择块中(虽然我不推荐这样的东西),取决于文档占用多少空间。
希望有所帮助。
-C§
答案 1 :(得分:1)
特别是指令的链接属性是这样的:
link: function (scope, ele, attrs) {
scope.$watch(attrs.dynamic, function(html) {
ele.html(html);
$compile(ele.contents())(scope);
});
}
有关详细信息,请参阅answer to this question,它提供了一个plunker演示。
希望这会有所帮助。
修改强> 我想写更多回应@VíťaPlšek - angular.cz的答案。 我曾经做过更动态的事情,就是在部分加载javacsript!
曾几何时,我根据angularjs做了一页的应用程序。每个菜单功能都是使用ajax动态加载的部分功能。当然,每个菜单功能都是一个单独的角度控制器。为了使代码更易于管理,我没有将所有控制器的代码合并到一个文件中,而是从index.html一次性加载它们。相反,我让每个部分使用自定义指令指定自己的控制器的js代码并执行延迟加载。
因此,单页应用程序的主页面使用自定义指令来包含动态加载的部分:
<body>
...
<dynamic-partial src={{selected_partial_url}}>
</dynamic-partial>
...
</body>
,而每个部分都存储在一个单独的html文件中。它的内容是这样的:
<lazy-load-script src="js/controllers/dynamic-controller1.js" >
</lazy-load-script>
<div ng-controller="DynamicController1">
...
</div>
现在,有一个问题:如果我们一次编译部分文件,则会出现错误,指出DynamicController1
未定义。是真的。我们必须首先加载dynamic-controller1.js
,然后在js文件加载完成后编译部分<div ng-controller="DynamicController1"></div>
。
所以指令DynamicPartial
的代码是这样的:
"use strict";
angular.module('MyApp')
.directive('DynamicPartial', [ "$compile", function( $compile ) {
return {
restrict: 'E',
scope: {
src: '@'
},
link: function (scope, element, attr) {
console.log( "Linking web-terminal. src = " + scope.src );
scope.onLazyLoadDone = function(){
// compile the other html elements in the partial, and put them in <dynamic-partial> element.
element.html( $compile( scope.other_elements_html )(scope) );
}
attr.$observe( 'src', function( value ){ // fetch new partial as soon as 'src' attribute changes:
console.log( "'src' attribute changed. Fetching new partial: " + value );
if( "" == scope.src ) {
element.addClass("ng-hide");
return;
}
else
element.removeClass("ng-hide");
$.ajax({
dataType: 'text',
timeout: 5000,
url: scope.src
})
.done(function (data) {
console.log( "Successfully fetched terminal file, length = " + data.length);
// compile the <lazy-load-script> tag first:
var lazy_load_element = $('<div/>').append( $(data)).find( "lazy-load-script, [lazy-load-script]" );
if( lazy_load_element.length > 0 ) { // lazy-load-script element found:
// Here we pragmatically set the "on-loaded" attribute for the <lazy-load-script> element found in the loaded partial, so that we can get called when the javascript file specified by <lazy-load-script> element finishes loading.
lazy_load_element.attr("on-loaded", "onLazyLoadDone()");
$compile($('<div/>').append(lazy_load_element).html())(scope);
}
// Save the remaining DOM elements in the partial, which will be compiled after the lazy-load is done.
scope.other_elements_html = $('<div/>').append( $(data).filter(':not([lazy-load],lazy-load)')).html();
if( 0 == lazy_load_element.length )
scope.onLazyLoadDone();
})
.fail(function (jqXHR, textStatus, errorThrown) {
console.error("Failed fetching menu from server: " + errorThrown.message);
});
});
if( undefined == scope.src || 'not defined' == scope.src ) {
return;
}
}
};
}]);
<lazy-load-script>
的代码如下。关键是使用onLoaded
范围属性来指定对父控制器的回调。
"use strict";
angular.module('SyncreonApp')
.directive('lazyLoad', [ "$ocLazyLoad", function( $ocLazyLoad ) {
return {
restrict: 'EA',
scope: {
src: '@',
onLoaded: '&'
},
link: function (scope, element, attr) {
//console.log( "Linking lazyLoadScript, url to load = " + scope.src );
if( undefined != scope.src && '' != scope.src ){
$ocLazyLoad.load( scope.$parent.$parent.getBasePath() + scope.src )
.then(function () {
//Javascript lazy load done, calling back to parent controller, so that parent will continue with compiling other parts of the partial.
scope.onLoaded();
});
}
else
console.error( "Illegal src attribute in directive lazyLoad");
}
};
}]);
答案 2 :(得分:0)
问题的根本原因是浏览器在页面初始化后不会加载javascript。这里描述了它 - Execute write on doc: It isn't possible to write into a document from an asynchronously-loaded external script unless it is explicitly opened.
但是......
需要在模板中加载javascript听起来很奇怪。 Angular是SPA应用程序的框架。它们应该像服务器的外部应用程序一样工作,并与某种API进行通信。
为什么小部件包含javascript?当我访问你的链接时,我可以看到它是简单的HTML。如果是,那么您可以使用ng-include指令 - https://docs.angularjs.org/api/ng/directive/ngInclude
ng-include="'path-to-template/tamplate-name.html'"
如果小部件包含一些非角度的javascript,我建议小部件应该重写为普通指令,也可以与服务器通信。