I have two html pages, snippet1.html
& snippet2.html
. I want use them inside my directive. Because I'm going to add multiple template by using single directive.
I tried this thing with by adding html templates inside <script>
tag & gave type="text/ng-template"
to them like Below.
<script type="text/ng-template" id="snippet1.html">
<div>Here is Snippet one</div>
</script>
<script type="text/ng-template" id="snippet2.html">
<div>Here is Snippet two</div>
</script>
And then I use $templateCache.get('snippet1.html')
. This implementation is working Fine.
But in my case I need to load them from html itself, so I decided to load template by ajax and make $http
cache: $templateCache
Working JSFiddle
Run Block
myApp.run(['$templateCache','$http', function($templateCache, $http){
$http.get('snippet1.html',{ cache : $templateCache });
$http.get('snippet2.html',{ cache : $templateCache });
}]);
But inside my controller $templateCache.get('snippet1.html')
is undefined.
My question is, Why it is working while i declared template inside <script>' tag & Why it don't work when I html inside
$templateCachewhile making
$http` ajax call?
Plunkr With Problem
Can anyone help me out with this issue? Or I'm missing anything in code.
Help would greatly appreciated. Thanks.
This is an interesting issue, and I can offer an interesting workaround and my thoughts on what is going on. I think a better solution may exist, but finding such solutions also proved to be a challenge. Nonetheless, I think the main issue is simply your console.log($templateCache.get('snippet1.html'))
is returning undefined
because of the race condition with your $http.get
's not resolving first.
Examining the api for $templateCache, I couldn't find any sort of helpful way of knowing when templates resolve requested via ajax. To see the simple issue, run this in your directive to see some basic information about what is currently stored in your $templateCache
console.log($templateCache.info())
With the result of
Object {id: "templates", size: 0}
For observing the core of the issue, run the same JS in the directive, but with a timeout as such
setTimeout(function() {
console.log($templateCache.info())
}, 1000);
With the result of
Object {id: "templates", size: 2}
Interesting, so they're in there... but getting a handle on them is now the challenge. I crafted the following workaround to at least give us something for now. Inject $q
and $rootScope
into your .run
function as such
myApp.run(['$templateCache', '$http', '$q', '$rootScope', function($templateCache, $http, $q, $rootScope){
$q.all([
$http.get('snippet1.html',{ cache : $templateCache }),
$http.get('snippet2.html',{ cache : $templateCache })
]).then(function(resp){
$rootScope.templateCache = resp
})
}]
);
Examining this, you'll notice I place an arbitrary var
on our $rootScope
as such $rootScope.templateCache
for the purpose of placing a $watch
on it in our directive. Then in our directive, let's call into our $templateCache
when we then know there is a value on $rootScope.templateCache
, indicating the $q
service has resolved our promises as such
link: function(scope, element, attrs) {
scope.$parent.$parent.$watch('templateCache', function(n, o) {
if(n) {
element.append($compile($templateCache.get('snippet1.html')[1])(scope));
}
});
}
And hey look! Our template directive is correctly rendered. The hacky looking scope.$parent.$parent
is because in this directive, we have isolated our scope
and now need to climb some ladders to get the value defined on $rootScope
.
Do I hope we can find a cleaner more consise way? Of course! But, hopefully this identifies why this is happening and a possible approach to get up and running for now. Working plunker provided below.
Here is a completely different approach to solve this which involves manual bootstrapping
var providers = {};
var $injector = angular.injector(['ng']);
var myApp = angular.module('myApp', []);
$injector.invoke(function($http, $q, $templateCache, $document) {
$q.all([
$http.get('snippet1.html',{ cache : $templateCache }),
$http.get('snippet2.html',{ cache : $templateCache })
]).then(function(resp){
providers.cacheProvider = $templateCache;
angular.bootstrap($document, ['myApp']);
});
});
myApp
.controller('test',function() {
})
.directive('myTemplate', function ($templateCache, $compile) {
return {
restrict: 'EA',
scope: {
snippets: '='
},
link: function(scope, element, attrs) {
element.append($compile(providers.cacheProvider.get('snippet1.html')[1])(scope));
}
};
});
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