I have script block to load the widget on partial view but I am getting below error if i placed directly on partial html page:
"Failed to execute 'write' on 'Document': It isn't possible to write into a document from an asynchronously-loaded external script unless it is explicitly opened."
sample script block is :
> <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>
I will have multiple widget so i want something to load through ng-repeat. Please advise.
Note I tried to display static way for this I add a html page with html/body tag and placed that above script block inside then load that page through the iframe then it works. But the issue it's very hard the update the content before loading into the iframe
Without seeing some of the content of the external widget, this is hard to diagnose exactly. My first impression is that it may need to be altered to return a document, which you would then assign in a JS script block using the name of the header function within the external widget. Something along the lines of:
var someDoc = writeDoc();
Where writeDoc()
is the header function in the widget which returns, I assume, an HTML doc of some sort. The script tag must come before your declaration, of course. Alternatively, with your ng-repeat
requirement, you might use something like:
ng-repeat="{{writeDoc()}}"
In a list block or even a select block (although I wouldn't recommend something like that), depending on how much space the document takes up.
Hope that helps.
-C§
Particularly the directive's link property is like this:
link: function (scope, ele, attrs) {
scope.$watch(attrs.dynamic, function(html) {
ele.html(html);
$compile(ele.contents())(scope);
});
}
See the answer to this question for details, it has provided a plunker demo.
Hope this helps.
EDIT I would like write more in response to @Víťa Plšek - angular.cz's answer. I once did something even more dynamic, which is to load javacsript in the partial!
Once upon a time, I made a one-page application based on angularjs. Each menu function is a partial dynamically loaded using ajax. Naturally, each menu function is a separate angular controller. To make the codes easier to manage, I did not merge all controllers' codes in one file and load them all at once from index.html. Instead, I let each partial specify its own controller's js code using a custom directive and do lazy-load.
So the main page of the one-page application use a custom directive to contain dynamically loaded partial:
<body>
...
<dynamic-partial src={{selected_partial_url}}>
</dynamic-partial>
...
</body>
, while each partial is stored in a separate html file. Its contents are like this:
<lazy-load-script src="js/controllers/dynamic-controller1.js" >
</lazy-load-script>
<div ng-controller="DynamicController1">
...
</div>
Now, there is one issue: If we compile the partial file all at once, there will be an error saying DynamicController1
is not defined. It is true. We have to loaded dynamic-controller1.js
first, and then compile the part <div ng-controller="DynamicController1"></div>
after the js file has finished loading.
So the codes of directive DynamicPartial
are like this:
"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;
}
}
};
}]);
And the codes of <lazy-load-script>
are as follows. The crux is to use an onLoaded
scope attribute to specify a callback to parent controller.
"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");
}
};
}]);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With