I'm curious if there's a way to override single, specific templates from the ui-bootstrap-tpls file. The vast majority of the default templates fit my needs, but there's a couple specific ones I'd like to replace without going through the whole process of grabbing all the default templates and getting them wired up to the non-tpls version.
-
1I've also found myself decorating the `$modal` service to get more configurability without (hopefully) creating too much of a maintenance headache. `$provide.decorator('$modal'`... In my case I didn't want to render the `modalWindow` element. Ever. I just wasn't using it, and this was the best I could come up with. I'd love to hear a better way if anyone has it. – bodine Sep 03 '14 at 17:48
4 Answers
Yes, directives from http://angular-ui.github.io/bootstrap are highly customizable and it is easy to override one of the templates (and still rely on the default ones for other directives).
It is enough to feed $templateCache
, either feeding it directly (as done in the ui-bootstrap-tpls
file) or - probably simpler - override a template using the <script>
directive (doc).
A contrived example where I'm changing alert's template to swap x
for Close
is shown below:
<!doctype html>
<html ng-app="plunker">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.js"></script>
<script src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.4.0.js"></script>
<script src="example.js"></script>
<link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.min.css" rel="stylesheet">
<script id="template/alert/alert.html" type="text/ng-template">
<div class='alert' ng-class='type && "alert-" + type'>
<button ng-show='closeable' type='button' class='close' ng-click='close()'>Close</button>
<div ng-transclude></div>
</div>
</script>
</head>
<body>
<div ng-controller="AlertDemoCtrl">
<alert ng-repeat="alert in alerts" type="alert.type" close="closeAlert($index)">
{{alert.msg}}
</alert>
<button class='btn' ng-click="addAlert()">Add Alert</button>
</div>
</body>
</html>
Live plunker: http://plnkr.co/edit/gyjVMBxa3fToYTFJtnij?p=preview

- 117,202
- 60
- 326
- 286
-
19I like this answer. I just don't like the fact that it's not included in the documentations page of Angular UI and took me quite a while to figure out how to do something as simple as showing a modal. – trivektor Sep 28 '13 at 08:10
-
2@BruceBanner Documentation and solid working examples are the two biggest downfalls of Angular UI. The project is great but it needs some sweet tender developer love. – Robin van Baalen Sep 25 '14 at 13:29
-
1@RobinvanBaalen this is an angular-js feature (not angular-ui), [it's already documented in angular js's official docs](https://docs.angularjs.org/api/ng/service/$templateCache) – vikki Sep 27 '14 at 09:48
-
Please check @JcT answer about $provide.decorator, as that's the Angular way (the good way in this case) to override directive templates. And it's fairly easy. Just adding/overriding a template to $templateCache is not really the best practice. – John Bernardsson Jul 01 '15 at 16:27
-
@John I'm not sure from where you get things "that's the Angular way (the good way in this case)" and "just adding/overriding a template to $templateCache is not really the best practice" but as one of angular-ui and angular maintainers I can assure you that there is nothing wrong with overriding templates. Unless you've got specific issues to share... – pkozlowski.opensource Jul 01 '15 at 16:49
-
Well, the concern is not about overriding templates. Is about the pattern used to do so. In the "Decorator" pattern I am pointing out (used in another answer), for this specific case it's only about overriding the template. The difference is about a pattern that let's you state a well defined point for modifying(decorating) a Directive, as opposed to a pattern that defines a template a bit like "in the middle of nowhere", whose id is the one of a template from some directive you want to modify. The first one is very clear on what is doing, and I think the latter doesn't. – John Bernardsson Jul 02 '15 at 08:41
-
Hence the "just adding/overriding a template to $templateCache is not really the best practice" declaration :) Maybe I should change it to: "just adding/overriding a template to $templateCache to modify a directive is not really the best practice". Also, I see Angular's $templateCache as exactly that, a cache so the browser doesn't need to request it every time is painted, not as a map to which you create overriding template patterns against. That's where the phrase "that's the Angular way (the good way in this case)" comes. But well, I accept this is just an opinion, of course :) – John Bernardsson Jul 02 '15 at 08:43
Using $provide.decorator
Using $provide
to decorate the directive avoids the need to directly mess around with $templateCache
.
Instead, create your external template html as you might normally, with whatever name you please, and then override the directive's templateUrl
to point at it.
angular.module('plunker', ['ui.bootstrap'])
.config(['$provide', Decorate]);
function Decorate($provide) {
$provide.decorator('alertDirective', function($delegate) {
var directive = $delegate[0];
directive.templateUrl = "alertOverride.tpl.html";
return $delegate;
});
}
Fork of pkozlowski.opensource's plunkr: http://plnkr.co/edit/RE9AvUwEmKmAzem9mfpI?p=preview
(Note that you must append the 'Directive' suffix to the directive name you intend to decorate. Above, we're decorating UI Bootstrap's alert
directive, so we use the name alertDirective
.)
As you may often want to do more than just override the templateUrl
, this provides a good starting point from which to further extend the directive, for example by overriding/wrapping the link or compile function (for example).
-
9This is the correct solution and follows angular best practices. You should NEVER use strings to create HTML, nor should you have to explicitly include it in the index.html file where you inject third party scripts. Thanks @JcT! – TommyMac Apr 16 '15 at 17:38
-
2Hi, is `alertDirective` a keyword? if yes, what is the keyword for `Tabs`? I am trying to do similar thing on tabs, but i looked through the alert.js, and i don't see where they had `alertDirective` in there. – codenamezero May 27 '15 at 22:13
-
4The angularjs `$compileProvider` attaches a 'Directive' suffix to the name of your directive when you register it (the `$filterProvider` does similarly with a 'Filter' suffix); for most purposes this is invisible, but when decorating you'll need to append this suffix to the directive you intend to target. For instance, `tabDirective` or `tabsetDirective`, etc. Not exactly clearly documented anywhere that I could find, but here's a reference to the similar behaviour for `$filterProvider` at least: https://docs.angularjs.org/api/ng/provider/$filterProvider – JcT May 27 '15 at 23:40
-
2Thanks a lot @JcT, a great answer. This is the correct way to go. And, as you say, a good starting point to "decoration" of 3rd party directives :) – John Bernardsson Jul 01 '15 at 16:23
-
The solution has worked for me as well. Is there a way to use default AND custom template for same Bootstrap directive under different modules? It seems that my custom template always overrides the default. – Valera Tumash Feb 10 '16 at 01:07
-
this solution doesn't work with angular-ui 1.3.2. see plunk http://plnkr.co/edit/E88IsLodO2a7CvH6gcC6?p=preview – ps0604 May 06 '16 at 17:39
-
There were some other unrelated errors in that plunk; for instance, 1.3.2 uses prefixed directives such as 'uib-alert' instead of 'alert' (note that it also includes 'template-url' prop to override templates). Fixed: http://plnkr.co/edit/sIIaTX?p=preview – JcT May 09 '16 at 11:59
-
1@ValeraTumash: Sorry for late answer. Yeah I think your config will get clobbered; however, from Angular v1.3 I believe you can supply a `function(element, attributes)` to templateUrl. You could use this for some dynamic behaviour (return original templateUrl function or your own url string depending on an attribute, etc). However, ui.bootstrap now also uses this same functionality to let you supply a `template-url` attribute on a directive, so you could also potentially use that if you're happy to supply the template path directly via directive element attribute. – JcT May 09 '16 at 13:06
-
-
The answer from pkozlowski.opensource is really useful and helped me out a lot! I tweaked it in my condition to have a single file defining all of my angular template overrides and loaded the external JS to keep payload size down.
To do this, go to the bottom of the angular ui-bootstrap source js file (e.g. ui-bootstrap-tpls-0.6.0.js
) and find the template you are interested in. Copy the entire block that defines the template and paste it into your overrides JS file.
e.g.
angular.module("template/alert/alert.html", []).run(["$templateCache", function($templateCache) {
$templateCache.put("template/alert/alert.html",
" <div class='alert' ng-class='type && \"alert-\" + type'>\n" +
" <button ng-show='closeable' type='button' class='close' ng-click='close()'>Close</button>\n" +
" <div ng-transclude></div>\n" +
" </div>");
}]);
Then just include your overrides file after ui-bootstrap and you achieve the same result.
Forked version of pkozlowski.opensource's plunk http://plnkr.co/edit/iF5xw2YTrQ0IAalAYiAg?p=preview

- 4,908
- 3
- 35
- 52
-
1I use this same pattern, and although it works; I really wish there was a better way. I think I would prefer configuration to clobbering. – bodine Sep 03 '14 at 17:45
You can use template-url="/app/.../_something.template.html"
to override the current template for that directive.
(Works in Accordion Bootstrap at least.)

- 6,955
- 6
- 43
- 57

- 71
- 1
- 1