I have 3 JSP views which all use the same JS file(say app.js).
My UI is on AngularJS which has a different controller for each of the JSP views and also has a custom service which shares information between the controllers. When I load the first JSP, its controller specified in the app.js file saves a value in the custom service. When I load the next JSP file, app.js gets reloaded and so the value that was saved in the custom service is lost.
Is there a way to not re-load JS files? Or is there a better way to go about this?
If you have no control on the server , you can save the data in browser's session storage object to keep data across requests and clean it, when you are done. https://developer.mozilla.org/en/docs/Web/API/Window/sessionStorage
// Save data to sessionStorage
sessionStorage.setItem('key', 'value');
// Get saved data from sessionStorage
var data = sessionStorage.getItem('key');
// Remove saved data from sessionStorage
sessionStorage.removeItem('key')
Javascript variable are not automatically preserved. When you open a new URL in your browser, you do not download again the JS files (they are cached), but they are loaded from scratch in that new page. That means that all previous values are lost, not by accident but by design.
You have different ways to deal with this persistence between page question. One way is server side by using the session:
the js part sends the value to save as parameters of a request
a spring-mvc controller puts that in the session
other views (jsp) or controllers (spring) access the saved value and pass it in the responses
An alternate way is the single page application pattern:
you only load one single full page from the server
the javascript then only sends requests that it processes directly to modify the DOM
Additionally, you could use Windows.sessionStorage to store data client side for the duration of a client session - credits should go to #AmitParashar for this one, more details in his answer.
You can of course mix the 2 patterns (this is commonly done in real world applications), but you must know that every page load will erase all client javascript state
A less common pattern (AFAIK) is to put the state in a cookie. That way it can be shared by the server and the client but:
it is limited to 4k size
you cannot use it for server side security, because it can too easily be forged
Related
I was wondering what is the lifetime of variables stored in factory/services in Angular JS? If we refresh the page, will the values still persist? What will happen if we refresh the entire application? Actually i am trying to store values in factory and fetch them on any page by passing them in respective controllers. So should we refresh (F5) the pplication, will values go undefined in factory?
Any help will be appreciated
The lifetime of a service is the lifetime of the application - services are basically Singletons, created when the application is constructed.
So you basically ask: what actions restart the application?
The user manually 'refreshing' the page: yes. The browser takes the user's request literally: discard the current page and reload it (although of course there are caching issues to think about; but they are separte from the lifetime of any javascript objects).
The application navigating to a URL in the same namespace (i.e., the part of the URL before '/#/'): no. Whatever routes you set up (e.g., '/#/foo/page1') and then navigate to under code control do not trigger the browser to reload the page. The original application object (and thus the Singletons that represent services) remain active.
I tried to google the following question, but nothing came up (which is super weird I need to).
What is an Agular app lifetime in a browser?
Or to rephrase when a user opens an Angular website, the app instances in the browser and stays live until the user leaves the website or closes the browser or?
On the separate note is it better to use a service for holding global variables (e.g. logged user name) or $rootScope?
Thanks!
What is an Agular app lifetime in a browser?
The angular app persists while that particular tab/site is open. If you navigate away from it and then back to it, for all intents and purposes, that's a fresh instance of the application. You could mimic a persistent session but that would entail a custom implementation on your part.
Here is a post on preserving data on a refresh of the application that you might be interested in - AngualrJS: sustaining data on html refresh
On the separate note is it better to use a service for holding global variables (e.g. logged user name) or $rootScope?
This is well documented and you can find myriad sources both here on SO as well as the internet, but it's better to use an angular service to share data among various controllers. It's not recommended that you pollute the $rootScope if you can avoid it.
Here is the same question asked on SO with solutions:
angular set a variable accessible to any scope
How to use variables from a controller in another controller in AngularJS
If you use angular's routing or another way to load views that doesn't reload a page, then an angular application will stay active until you leave the page (closing or refreshing).
Every time you load a page through angular its controller's data is in its initial state so any modification to a controller's data will get lost when you change page (unless you persist it somewhere, that is)
Regarding your second question, the best way should be to get a user's data after every page change (to check if the user is still logged in. Saving a user's data client side without checking if it's still valid might be a security issue). But in any case, a service is a better way to store data than using rootScope
Hello can any one please tell me how to send on form data to another by clicking submit button using angular JS.
There are three ways to do that.
If you are using SPA flow for your website, you can make a service for data that are to be shared among pages. Redirection will only change the hash value of URL and landing page will still have those data from service.
Second is to use the hash value for data as lets say that you are redirecting from baseURL/test1 to baseURL/test2 so instead of redirecting to baseURL/test2, you can redirect to baseURL/test2#/data=* , * representing the data. The redirection will still happen but now you can also get the data.
Third is to use local storage or webSQL ( although limited browser support for webSQL), to save the data and then retrieve back on the next page.
While I will stick to the SPA flow for my angular website and use a service to pass on the data. There is also a way to assign data in $rootScope but that is just not a good practice to pass on data from one page to another.
The problem:
AngularJS forces to split view from model and it's good. But we're experiencing the following downsides because of it: When a user loads our page a browser makes not 1, but 2 requests:
First it loads view template (the first request)
Then Angular services load data from a server (the second request)
And we have a bit slower load page speed.
The question:
Is it possible after first page loading load view with populated data and only then get data from a server when something must be changed on the page?
I tried to find something regarding it, but didn't find anything.
You will have a lot more request as you have to load the Javascript and CSS libraries as well.
You can store your initial data in a service or the rootscope and just update the data when you need it. What's exactly your problem here?
The modular approach would be to break all the different components of the page that consume data into separate data requests, so that the interface can load in progressively as different data requests complete.
Additionally, you can load initial data, but then make some predictions on what the user will do next and lazy load additional data in the background.
Finally, you could store the previously loaded data in local storage (lots of modules out there you can utilize) so that it's pulled instantly upon the user's next visit. You would want to want to also add some sort of timestamp comparison on data in storage and on server to see if it has been updated.
I'm building a wizard-config app with 3 pages. Each page has the same MasterController but different html templates. Each html templates has a different controller, say ControllerOne, ControllerTwo, and ControllerThree.
I load the data via MasterController and I'd like the data and any changes the user makes to be stored temporarily until the save & finish step on the final page. Trouble is as the user goes through the pages, MasterController is called each time and each time it fetches the data and overwrites the user's changes.
I've thought about attaching this data to a service or rootScope but the data initialization still happens in MasterController so the data would still be overwritten when each view is loaded.
Any advice on how I should go creating this functionality or restructuring my app to support this?
EDIT:
To be clear on the service issue. I don't know where to initialize it. If I do it in Controllers 1,2 or 3 my data is reinitialized each time the view changes so that doesn't work. I can't do it in app.run() either because I need to get to MasterController in order to get the necessary ID to make my HTTP request. I can't do it in MasterController because that too is called on each page switch.
Ideally I'd have a view within a view so that only the inner view changes. However angular does not support nested views and I'm trying to find a way around this without having to use angularUI.
To get around the data being loaded from the server on each page change and overwriting the user data, I used an "extend" function (like jQuery's) to extend the server data with the user data on each load. Page changes would call my service(that stores the temporary data) to save the data there and the final "save and finish" button would push the data in the service to the server.