When using templateUrl
with a dynamic path, AngularJS sometimes fails to load the template. This can lead to 404 errors or blank content in the directive.
1. Understanding the Problem
Problem Example
app.directive("dynamicDirective", function() {
return {
restrict: "E",
templateUrl: "/templates/" + someDynamicValue + ".html"
};
});
Error:
GET http://localhost/templates/undefined.html 404 (Not Found)
Reason:
someDynamicValue
is undefined at runtime.- AngularJS does not evaluate expressions in
templateUrl
. - Relative paths may be incorrect when dynamically assigning URLs.
2. Solutions to Fix the Issue
Solution 1: Use function()
for templateUrl
Instead of directly setting templateUrl
, use a function to dynamically return the correct path.
app.directive("dynamicDirective", function() {
return {
restrict: "E",
templateUrl: function(elem, attrs) {
return "/templates/" + attrs.templateName + ".html";
}
};
});
<dynamic-directive template-name="header"></dynamic-directive>
Now, the directive will correctly load /templates/header.html
.
Solution 2: Use $attrs
in link
or controller
Another way is to set templateUrl
inside the controller or link function.
app.directive("dynamicDirective", function() {
return {
restrict: "E",
link: function(scope, element, attrs) {
scope.templateUrl = "/templates/" + attrs.templateName + ".html";
},
template: "<div ng-include='templateUrl'></div>"
};
});
<dynamic-directive template-name="footer"></dynamic-directive>
This method ensures ng-include
dynamically loads the template.
Solution 3: Use $sce.trustAsResourceUrl()
for Security
If AngularJS blocks the template as unsafe content, trust the URL using $sce
.
app.directive("dynamicDirective", function($sce) {
return {
restrict: "E",
templateUrl: function(elem, attrs) {
return $sce.trustAsResourceUrl("/templates/" + attrs.templateName + ".html");
}
};
});
This prevents AngularJS from blocking external URLs.
Solution 4: Use a Service to Fetch the Path
For more complex logic, use a service to determine the correct template path.
app.factory("templateService", function() {
return {
getTemplatePath: function(name) {
return "/templates/" + name + ".html";
}
};
});
app.directive("dynamicDirective", function(templateService) {
return {
restrict: "E",
templateUrl: function(elem, attrs) {
return templateService.getTemplatePath(attrs.templateName);
}
};
});
This centralizes template logic, making it reusable.
Solution 5: Check Network Requests in DevTools
If templates still fail to load, check Google Chrome DevTools (F12 → Network Tab):
- Verify the correct URL is requested.
- Ensure the file exists in the correct directory.
- Look for CORS errors when fetching from another domain.