Building Smarter Directives #2
My last post talked about conditionally loading templates using ng-include
.
I spent a good amount of time using this, but found it to be problematic because it was causing my HTML to become bloated. Instead of adding to the div soup, I set out to find a better way.
This leads to nested divs:
<div ng-include="contentUrl"></div>
Renders something like this:
<div ng-include="contentUrl">
<div> This is the template </div>
</div>
As it turned out, there are options! First, I found out that in 1.1.4, Angular added the ability to use a function as the templateUrl
. In your directive definition object, you can have the following:
angular.module('myApp', [])
.directive('example', function() {
return {
templateUrl: function(tElement, tAttrs) {
// Template can be chosen here
// Try something like this
return tAttrs.example.toLowerCase() + '.html';
}
};
});
Then use it like this:
<!-- Includes 'one.html' -->
<div example="one"></div>
<!-- Includes 'two.html' -->
<div example="two"></div>
The other option that I found was to do what is essentially a manual ng-include
. The problem I’ve found with this is that it makes the directive a bit harder to test. By going around Angular’s built in ways of including the template, you are circumventing the $templateCache
.
To do this, you use the $http
and $compile
service to retrieve and compile the template yourself:
angular.module('myApp')
.directive('example', function($http, $compile) {
return {
link: function(scope, element, attrs) {
$http.get(attrs.example + '.html').then(function(response) {
element.html($compile(response.data)(scope));
});
}
};
});
This version of the directive would be used the same as above, allowing you to include one.html
or two.html
.
Whatever you decide to use, the good news is that you have options to suit your situation.