Right now, I have a factory which loads a JSON file.
angular.module("app").factory("RolesFactory", ['$http', '$q', function($http, $q) {
var d = $q.defer();
$http.get('events.json').success(function(data) {
d.resolve(data);
});
return d.promise;
}]);
And then I call this factory when I need the contents of events.json with this controller:
App.controller('rolesCtrl', ['$scope', 'RolesFactory', function($scope, RolesFactory) {
RolesFactory.then(function(roleData){
$scope.roles = roleData.roles;
});
}]);
All good, but whenever I need to use this data. Isn't it refetching the contents of events.json? Meaning: is Angular reloading the file over and over again? I was hoping to load the file once and call it by a global variable or something.
When my app loads initially, I want it to load and store the contens of events.json -- and then I'd like my app to be able to use this data whenever/wherever.
Is this possible?
As AngularJS is a stateless framework, you have only a few options here, all of which are some kind of client-side caching:
Use localStorage to store your data. Once the data is fetched, you can just save it to localStorage using localStorage.setItem after Stringifying the JSON. You'll need to re-parse the JSON the next time you use it though, so if this is a giant JSON, this is not the best idea
Use sessionStorage to store your data. This is exactly the same as #1, but you will lose data upon termination of session,i.e. closing your browser.
Trust the JSON to be cached in your browser. This is most likely the case. Static assets are by default cached by most modern browsers. So, the second time your factory requests the JSON, the resource isn't actually fetched from the server. It is merely pulled from the browser's cache.
NOTE: The way to check this is to see what the HTTP status code for your resource is, in Chrome's Developer Tools Network tab. If the status says 304 that means it has been pulled from cache.
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
I am new to angular js.Please suggest which one is better . I have a page where I can select a no of check boxes and navigate to 2 nd page.I want to show the checked values when I press back button in browser.
Which one is better using $rootScope or stateparam or localstorage.Please consider performance also.
Going through your options one by one:
$rootScope: You should try to avoid using this option as it is associated to the global state. Use this option only if you want the data you set to be globally available throughout the app and do not want to reuse the same variable names anywhere else.
$stateParams: These typically go into the state URI as a dynamic part of the whole URL. This has only limited usage, and may not be a good idea for your use case where you need to store data from multiple checkboxes.
localStorage: This is slower than using a JavaScript variable, and hence not a good idea.
Services:
Here is a better solution for you, entirely within the AngularJS paradigm: AngularJS services
Excerpt from the link in point 3:
Data should also be stored in services, except where it is being bound
to the $scope. Services are singletons that persist throughout the
lifetime of the application, while controllers are transient between
application states. If data is stored in the controller then it will
need to be fetched from somewhere when it is reinstantiated. Even if
the data is stored in localStorage, it's an order of magnitude slower
to retrieve than from with a Javascript variable.
You can use the service to set and get your data inside your controller anywhere in the app in a consistent manner.
Here is an indicative example:
app.factory('formDetails', formDetails);
function formDetails() {
var formData = {};
return {
getProperty: function () {
return formData;
},
setProperty: function(values) {
formData = values;
}
};
};
Use it in your controller as:
app.controller('MyController', [ '$scope', 'formDetails' , function($scope, formDetails) {
$scope.checkboxData = {};
// on load call service 'get' function
$scope.checkboxData = formDetails.getProperty();
// on some event/watch function call service 'set' function
formDetails.setProperty($scope.checkboxData);
}]);
So I have a simple factory that creates cache object
.factory('jsonCache',function($cacheFactory){
console.log("Creating cache");
return $cacheFactory('weatherCache');
});
I'm then calling that cache object inside my controller like so by passing it in like so. But for some reason the data is not persistent. Every time I reload the page, the cache is empty again.
Any ideas? Did I miss something?
.controller('citiesListCtrl',function($scope,$http,$filter,jsonCache){
jsonCache.get('weatherCache');
console.log(jsonCache); <----- EMPTY
$http.get(url)
.then(function(response) {
jsonCache.put('weatherCache', response.data.records);
console.log(jsonCache); <--- HAS DATA
});
)}
The data is not persistent for very good reason: $cacheFactory cache is nothing but a thin wrapper around plain JS object.
You can check the source to make sure that the service does nothing but simple LRU algorithm.
For data persistence use persistent storage (probably angular-local-storage or angular-localForage). angular-cache is an another replacement for built-in $cacheFactory that supports persistence.
We have an endpoint on our API that includes a set of settings (like default text, other endpoints, etc.). Our frontend is written in AngularJS and we're trying to figure out the best way to get them back to the client, and make them available throughout all directives in the application. Right now our best solution is to include settings as a directive:
angular.module('ourapp')
.factory('settings', function ($http) {
var url = 'http://localhost:8080/settings';
return function (callback){
$http.get(url).success(callback);
};
});
But then all the other calls are wrapped asynchronously.
Is there a better way to do this?
Since the settings come asynchronously from the server, their availability will inherently be asynchronous. If your logic depends on the settings being available, then there is probably no better solution than using promises.
angular.module('ourapp').factory('settings', function($http) {
var url = 'http://localhost:8080/settings';
return $http.get(url); // returns a promise
});
You could use $route to resolve the promise before instantiating controllers. The settings would then be synchronously available in the controllers.
You can also simulate promise unwrapping, i.e. immediately (synchronously) returning an object, which later will be filled with real data. This is great for scopes and templates, and was previously a feature of Angular itself. Be aware that the simulated promise unwrapping may cause bugs if not used cautiously, because the settings data may or may not be there.
Example:
angular.module('ourapp').factory('settings', function($http) {
var url = 'http://localhost:8080/settings';
var settings = {};
$http.get(url).success(function(data) {
angular.extend(settings, data); // fills in data from server
});
return settings; // immediately (synchronously) returned
});
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.