I have an Angular that uses templates via directives. With one of the templates I have there was a bug. After making the change and refreshing my browser I noticed it was not using the file I fixed the bug in. I then learned about template caching. Great feature, but how do I clear out the cache for this updated template?
Note: I'm not using Angular's routes. Just accessing templates via a directive.
Did You use gulp or Grunt?
I personally use template-cache, what it does it collects all html partials/templates and put them into on js file.
pros:
* all templates are loaded at once in one js file.
cons:
* each time You change your html files You have to regenerate your template-cache. You could use gulp to watch your html files and each time You change something it automatically regenerate template-cache for You :)
to sum up, get interesting with gulp-watch and gulp-angular-templatecache to solve your problem.
As an extension of appending your template urls with a number, you might consider instead intercepting the request (all of them) and appending a number (version, release, date, etc) there. Something like this:
angular.module('my-app', []).config(function($httpProvider) {
$httpProvider.interceptors.push(function($window) {
return {
'request': function(config) {
// just yours (other libs, ie pagination might conflict with
// their own insertions)
if (!/^\/path-to-your-templates\//.test(config.url)) {
return config;
}
// pull a # from wherever you like, maybe the window - set by
// your backend layout engine?
if ($window.version) {
if (!config.params) {
config.params = {};
}
if (!config.params.v) {
config.params.v = $window.version;
}
}
return config;
}
};
});
});
Related
I am working on angular js application.
For the first time application is working fine, when we release a new build with new changes, when the user trying to access the page browser is still loading the old files new changes are showing in the browser, to load the new changes user has to clear the cache and reload the application.
Is there any way to clear the browser cache on the application load.
I am clearing the cache like below.
function run($rootScope,$state, $stateParams, authorization, principal,$templateCache) {
//code to clear the cache.....
$rootScope.$on('$viewContentLoaded', function() {
$templateCache.removeAll();
});
}
it is clearing the cache, but pagination is not working after adding this code into application .
Any help appreciated, thanks in advance.
Try to set version for all of you files and http requests, do not clear the cache!
Want to Browse Faster? Stop Clearing Your Browser Cache
how to set version to files and api requests, you can put a global variable to handle it after each publish for example:
var version = "1.0.0";
var app = angular.module("app", []);
app.config(function(){
//for routes
//pages.html?v="+version
//controller.js?v="+version
})
app.controller("ctrl", function($http){
$http.get("api/posts?v=" + version)
})
with this version you can handle your users browser cache.
This is a common problem, to solve this browser cache issues you need to add some kind of unique identifier (hash/timestamp) to all your static files.
There are lot of backend framework which bundles your file, optimize it and add a unique hash to it which gets changed after any change in the original file.
Tools varies depending upon the back-end framework you are using. This is the ideal approach for handling this issue.
You can check gulp-rev, which is a really good library for re-visioning of your static assets.
To do it quickly, you can use an Interceptor on your main module, and append a version number to every request. You need to make sure that after every release you need to change the version number. The downside of this approach is, even the file which has not be changed will get refreshed.
yourModule.factory('cacheInterceptor',
['$templateCache', '$window', function ($templateCache, $window) {
var cacheInterceptor = {
request: function (request) {
if ($templateCache.get(request.url) === undefined) {
var appVersion = '';
appVersion = $window.MyApp.appVersion;
request.url = request.url + '?appVersion=' + appVersion;
}
return request;
}
};
return cacheInterceptor;
}]);
Note: Version number you need to assign on the window object every time the application loads.
You can find more details on Interceptors in AngularJS here
Sorry for a not very specific question by someone new to node webkit, new to Angular, new to about everything in web development:
My app is based on a JSON file that I load at the init of my node webkit app and which is at the center of a bunch of calculations.
In the app, one can open a file dialog to create a new JSON file. Now, of course, I would like the app to recalculate everything based on the new JSON. It works when I press the "refresh" button of node webkit, but I couldn't get it running by using either
require('nw.gui').Window.open('index.html');
nor
require('nw.gui').Window.get().reload(3);.
I am also wondering if handling this on the node level is the good way to do it. Shouldn't it rather be done by Angular? But I couldn't really connect to the content of my controller from an "outside" javascript.
Grateful for any hint...
Having logic on the page loading is always tricky and as you mentioned - requires page reloading what is not very elegant and modern applications avoid this.
In your case, I suggest that if your JSON file is not very big - store it in variable and modify it as needed. The elegant way will be to create Angular service, which can act as a "model".
angular.service('JsonService', function() {
var json = {
// content
};
return {
getJson: function () {
return json;
},
setJson: function (newJson) {
json = newJson;
}
};
});
Then, whenever you need to update JSON invoke setJson(newJson) method and modify your controllers to use the service getJson() method.
You can also add the loading/saving to file functions to this service. The loading function can be invoked in your main controller connected to your dashboard page. Then before the first page will be visible, the JSON file will be already loaded and you preserve desired behavior.
I have a service that I call during app.run() and for some reason when I load the files async at that point they don't seem to take.
Here's the service i'm using:
angular.module('nav').service('SubmoduleService', ['submodules_config',
function(config){
this.autoload = function(){
for(var key in config.modules){
for(var i=0; i<config.modules[key].length; i++){
var src = config.modules[key][i].replace(':path', config.path).replace(':name', key);
console.log(src);
var js = document.createElement("script");
js.type = "text/javascript";
js.src = src;
document.body.appendChild(js);
}
}
return true;
};
}]);
Here's the config file:
angular.module('nav').constant('submodules_config', {
path: "scripts/submodules/:name",
modules: {
gallery: [':path/config.js', ':path/directive.js']
}
});
So basically the config defines a module and all the files that need to get loaded for that module.
I see the files get loaded into the DOM, but for some reason when I load the controller that uses that directive, it doesn't work.
NOTE: The directive works when loading the files explicitly.
Any help is appreciated.
E
By default, angular bootstraps the application on the DOM Ready event. When you load scripts asynchronously, this event can be fired before the scripts load, so angular won't know about the directives contained in them when the DOM is $compiled().
There are quite a few ways to work around this, but they all revolve around deferring compilation of the DOM until the required modules are loaded.
On simple (but not the only) way to defer compilation for a fragment of your application is to simply use ng-if. In pseudo code, it would look something like this:
<div ng-if="moduleWithMyDirectiveLoaded" my-directive></div>
This leaves you with the task of figuring out how to determine if a particular script has been loaded and getting that information into your angular application.
Unfortunately, this isn't trivial. You can write this yourself, but others have already done it for you and you'd probably be better off using one of those tested, cross-browser solutions.
require.js comes to mind as an option, but there are many others that would also work.
I am trying to have external modules change my $translateProvider.translation on the main module. see this as a "tranlation plugin" for my app.
it seems like changing translations from the $translate service is not possible.
mymodule.service('MyService', function ($translateProvider) {
var lib = function () {
//EDITED FOR BREVITY
this._registerTranslations = function (ctrl) {
if (!ctrl.i18n) return;
for (var name in ctrl.i18n) {
/////////////////////////////
// THIS IS THE PLACE, OBVIOUSLY PROVIDER IS NOT AVAILABLE!!!!
$translateProvider.translations(name, ctrl.i18n[name]);
//////////////////////////////
}
};
//EDITED FOR BREVITY
};
return new lib();
});
anyone with a bright idea?
So, to answer your question: there's no way to extend existing translations during runtime with $translate service without using asynchronous loading. I wonder why you want to do that anyway, because adding translations in such a way means that they are already there (otherwise you would obviously use asynchronous loading).
Have a look at the Asynchronous loading page. You can create a factory that will load a translation from wherever you want.
I created an Angular constant to hold new translations. If I want to add a new translation, I add it to the constant. Then in my custom loader, I first check the constant to see if the translation exists (either a new one, or an updated one). If so, I load it from the constant. If not, I load it from a .json file (or wherever you load your initial translations from). Use $translate.refresh() to force translations to be reloaded and reevaluated.
Demo here
The demo is pretty simple. You would need to do a little more work if you wanted to just change a subset of the translations, but you get the general idea.
From the AngularJS docs (https://docs.angularjs.org/guide/providers):
You should use the Provider recipe only when you want to expose an API for application-wide configuration that must be made before the application starts. This is usually interesting only for reusable services whose behavior might need to vary slightly between applications.
Providers are to be used with the application's .config function. $translateProvider for configuration, $translate for other services and controllers.
Question: What is the best way and the best time to pre-load .ng files that are used in routing templates?
In researching this thus far, I've found the following answers:
Use Angular's script directive.
Problem: My content cannot be loaded as a literal string but needs to be fetched from the server. In other words, I have an .ng file as my partial so I cannot do
my content must remain in a .ng file on the server and be fetched
Use $templateCache.put to put a template literal in the cache. Same problem as above.
Use $http to load the .ng file. This works in that it is not a string literal but I am struggling to find the best time to perform this so that it is not blocking (realize its async but still)
To save you from suggesting resources I've already seen, I've read the following:
Is there a way to make AngularJS load partials in the beginning and not at when needed?
https://groups.google.com/forum/#!topic/angular/6aW6gWlsCjU
https://groups.google.com/forum/#!topic/angular/okG3LFcLkd0
https://medium.com/p/f8ae57e2cec3
http://comments.gmane.org/gmane.comp.lang.javascript.angularjs/15975
Maybe use a combination of 2 and 3.
Like you said, $http is async, so why not just put each partial into the templateCache after the app has loaded.
For example:
var myApp = angular.module('myApp', []);
myApp.run(function($http, $templateCache) {
var templates = ['template1.ng', 'template2.ng'];
angular.forEach(templates, function(templateUrl) {
$http({method: 'GET', url: templateUrl}).success(function(data) {
$templateCache.put(templateUrl, data);
});
});
});
I've never had the need for this and definitely haven't tested it, but the idea is there.