In my code i need to compile html returned from another api from inside a javascript callback function.
The following is a simplified version of my code. I am using a factory method which recomplies any element using $compile and $rootScope.
The strange thing about this setup is that the compile function is making the data factory execute multiple times. What is the reason for this? And any suggestions or any flaws in this method of compiling dynamic html?
here is a plunker link http://plnkr.co/edit/D32kCS4BkslvpBsRtFoS
var app = angular.module('mainApp', []);
app.factory('CompileDirective', function($compile, $rootScope) {
function compileApp() {
$compile($("[ng-app='mainApp']"))($rootScope);
}
return {
compileApp: compileApp
};
});
app.factory('data', function() {
alert("run");
return "data";
});
app.directive('testDirective', function(data) {
return {
restrict: 'E',
templateUrl: 'tpl.html'
};
});
function addDirective() {
$('#container').append('<test-directive></test-directive>');
callback();
}
function callback() {
alert('callback called');
angular.injector(['ng', 'mainApp']).get("CompileDirective").compileApp();
}
<script data-require="[email protected]" data-semver="1.3.7" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.7/angular.js"></script>
<script data-require="jquery@*" data-semver="2.1.1" src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body ng-app="mainApp">
<script type="text/ng-template" id="tpl.html">
{{ "hello" + "world"}}
</script>
<h1>Hello Plunker!</h1>
<input type="button" value="Add Directive" onClick="addDirective()" />
<div id='container'>
<test-directive></test-directive>
</div>
</body>
personally I wouldnt put that in a factory but add a directive to compile the code or do it in the controller....
if I understood what you are trying to do correctly this is what I suggest:
for a static html you already have the ng-bind-html
directive... and if you need it to be dynamic just create a directive like this
angular.module('app',[]).directive('ngHtmlCompile',function ($compile) {
return function(scope, element, attrs) {
scope.$watch(
function(scope) {
// watch the 'compile' expression for changes
return scope.$eval(attrs.ngHtmlCompile);
},
function(value) {
// when the 'compile' expression changes
// assign it into the current DOM
element.html(value);
// compile the new DOM and link it to the current
// scope.
// NOTE: we only compile .childNodes so that
// we don't get into infinite loop compiling ourselves
$compile(element.contents())(scope);
}
);
};
});