14

I have noticed that from time to time I'll make a change to one of the templates within my AngularJS application and that at runtime, the change won't be visible. Rather, I'll have to refresh the application and if that fails, go to the path of the template itself and refresh it in order to see this change.

What's the best way to prevent caching of these templates like this? Ideally, I'd like them to be cached during the current use of the Angular application, but that the next time I load the page, they retrieve the latest and greatest templates without having to manually refresh.

I'm using ui-router if that makes any difference here. Thanks!

Whit Waldo
  • 3,312
  • 3
  • 36
  • 60

2 Answers2

17

You can use a decorator and update UI Router's $templateFactory service to append a suffix to templateUrl

function configureTemplateFactory($provide) {
    // Set a suffix outside the decorator function 
    var cacheBuster = Date.now().toString();

    function templateFactoryDecorator($delegate) {
        var fromUrl = angular.bind($delegate, $delegate.fromUrl);
        $delegate.fromUrl = function (url, params) {
            if (url !== null && angular.isDefined(url) && angular.isString(url)) {
                url += (url.indexOf("?") === -1 ? "?" : "&");
                url += "v=" + cacheBuster;
            }

            return fromUrl(url, params);
        };

        return $delegate;
    }

    $provide.decorator('$templateFactory', ['$delegate', templateFactoryDecorator]);
}

app.config(['$provide', configureTemplateFactory]);
Aman Mahajan
  • 1,293
  • 14
  • 14
  • I'm making the switch to ui-router for this very reason, but I'm having difficulty making your example work. Can you provide how I would actually call this to append the suffix to the templateUrl? Thanks. – iTrout Mar 07 '15 at 06:04
  • 1
    good to know about this config option, but won't all those unique-id'ed pages accumulate in client side's cache? – Ivan Ferrer Villa Mar 27 '15 at 11:37
  • The above code is a workaround for browser cache so next time you reload your application then the value of cacheBuster variable will be different and the templates are fetched from the server again. The idea is to have a different value of cacheBuster for each session. – Aman Mahajan Apr 03 '15 at 23:54
  • A much better alternative is to use a plugin like gulp-angular-templatecache to register angular js templates in the $templateCache. This should be used along with gulp-rev. Everytime a template changes, a new JavaScript file with a different revision number will be created and caching will never be an issue. – Aman Mahajan Aug 07 '15 at 21:27
  • 1
    This is not working for template url function templateUrl: function($stataParams) { return '/serverUrl?id=' + $stataParams.id + '&cid=' + $stataParams.cid; } – Biju Thomas Aug 31 '15 at 14:08
2

Above solution was great and was not working for template urls

function templateUrl: function($stataParams) { return '/serverUrl?id=' + $stataParams.id + '&cid=' + $stataParams.cid; }

fixed by

function templateFactoryDecorator($delegate) {
    var fromUrl = angular.bind($delegate, $delegate.fromUrl);
    $delegate.fromUrl = function (url, params) {
        if (url !== null && angular.isDefined(url)) {
            if (typeof url == 'function') {
                url = url.call(url, params);
            }
            if (angular.isString(url)) {
             url += (url.indexOf("?") === -1 ? "?" : "&");
             url += "v=" + Date.now().toString();
             }
         }

         return fromUrl(url, params);
     };

     return $delegate;
}
Biju Thomas
  • 929
  • 3
  • 11
  • 23