60

I am working a project using the AngularJS framework. I am pretty new to using this framework; in the past I have only worked with pure JavaScript and jQuery. The project is a kind of web designer application for a niche market.

As the user moves between pages while designing I want to maintain a session of all the changes they are making.

Now if the user signs in we load the session using data from the database. When the user clicks on save button we update the database with the session data. Someone told me that I can maintain session in Angular similar to backbone. Is this possible? If yes, can you please direct me to a tutorial that does not focus on directives or UI? If this is not possible are there other viable options?

Brian Risk
  • 1,244
  • 13
  • 23
Jehanzeb.Malik
  • 3,332
  • 4
  • 25
  • 41

5 Answers5

58

Here is a kind of snippet for you:

app.factory('Session', function($http) {
  var Session = {
    data: {},
    saveSession: function() { /* save session data to db */ },
    updateSession: function() { 
      /* load data from db */
      $http.get('session.json').then(function(r) { return Session.data = r.data;});
    }
  };
  Session.updateSession();
  return Session; 
});

Here is Plunker example how you can use that: http://plnkr.co/edit/Fg3uF4ukl5p88Z0AeQqU?p=preview

Valentyn Shybanov
  • 19,331
  • 7
  • 66
  • 59
  • Can this session data be stored in local storage ? In case user closes the browser and comes back ... – Amogh Talpallikar Nov 12 '13 at 10:02
  • 5
    Keep in mind that local storage is shared across subdomains, so little bit not so secure. – Valentyn Shybanov Nov 12 '13 at 10:32
  • so in ur case, if the user closes his browser he is anyways logged-out ? – Amogh Talpallikar Nov 12 '13 at 10:40
  • may be use SessionStore? The drawback is that it is not shared between open windows... but for SPA its ok. – Valentyn Shybanov Nov 12 '13 at 10:49
  • I have a login-page thats takes a fullscreen, and thena dashboard which is the angular app. They both have seprate URLs. – Amogh Talpallikar Nov 12 '13 at 10:50
  • But if there share same chrome window and reside on same domain, `window.sessionStorage` would be shared and will be removed when user close window. – Valentyn Shybanov Nov 12 '13 at 11:28
  • I am using the same for storing USER_ID to the session after LOGIN . but it's not working for me. I am working with multiple pages and once I update the session in one page it should maintain the same value through all the pages. but it's loading the other pages with a blank session value. Any suggestion ? – NawazSE Sep 15 '14 at 07:04
  • This answer seems to be outdated. It no longer works with a newer version of angular. – Demodave Aug 17 '15 at 15:48
  • @Demodave that's because AngularJS now don't treat promises as values for views. Updated answer for latest stable AngularJS version. – Valentyn Shybanov Aug 18 '15 at 19:37
  • @ValentynShybanov Answer Posted – Demodave Aug 19 '15 at 15:12
  • Since this is a factory can I assume "Session.updateSession()" will only be called once? Or is it called everytime this factory is injected into a controller? – nav Jan 14 '16 at 16:04
  • 1
    @ValentynShybanov I'm pretty sure that localStorage is *not* shared between domains, even subdomains. Go to http://unix.stackexchange.com/ - open console and add `window.localStorage.setItem('shared', 'yes')` then go to http://dba.stackexchange.com/, open console and `window.localStorage.getItem('shared')` is returns `null` LocalStorage is not shared and cannot be without some trickery. – Emil Devantie Brockdorff Apr 15 '16 at 13:39
  • @nav That function isn't automatically called ever. You have to call it at the start or you app yourself. – user441521 Feb 26 '18 at 17:02
9

Because the answer is no longer valid with a more stable version of angular, I am posting a newer solution.

PHP Page: session.php

if (!isset($_SESSION))
{    
    session_start();
}    

$_SESSION['variable'] = "hello world";

$sessions = array();

$sessions['variable'] = $_SESSION['variable'];

header('Content-Type: application/json');
echo json_encode($sessions);

Send back only the session variables you want in Angular not all of them don't want to expose more than what is needed.

JS All Together

var app = angular.module('StarterApp', []);
app.controller("AppCtrl", ['$rootScope', 'Session', function($rootScope, Session) {      
    Session.then(function(response){
        $rootScope.session = response;
    });
}]);

 app.factory('Session', function($http) {    
    return $http.get('/session.php').then(function(result) {       
        return result.data; 
    });
}); 
  • Do a simple get to get sessions using a factory.
  • If you want to make it post to make the page not visible when you just go to it in the browser you can, I'm just simplifying it
  • Add the factory to the controller
  • I use rootScope because it is a session variable that I use throughout all my code.

HTML

Inside your html you can reference your session

<html ng-app="StarterApp">

<body ng-controller="AppCtrl">
{{ session.variable }}
</body>
Mandy Schoep
  • 942
  • 11
  • 19
Demodave
  • 6,242
  • 6
  • 43
  • 58
8

You can also try to make service based on window.sessionStorage or window.localStorage to keep state information between page reloads. I use it in the web app which is partially made in AngularJS and page URL is changed in "the old way" for some parts of workflow. Web storage is supported even by IE8. Here is angular-webstorage for convenience.

gertas
  • 16,869
  • 1
  • 76
  • 58
  • 1
    I used localStorage in another project. And I must say I found it quiet helpful. I am glad that we have got a viable replacement for the cookies. It is fast and has ample storage space unlike cookies which was slow as we had to read the cookie from a file and the amount of data per cookie was very limited. Another plus is that localStorage data is not available cross-domain. So no other domain can read your data and no conflicts with variable names either. The only issue that I found was that we could not specify any expiration. I hope they do include in future updates. – Jehanzeb.Malik Aug 29 '13 at 08:24
  • @Jehanzeb.Malik web storage gives you ability to define your own scope of expiration. Just add a key-value with timestamp and implement your own logic to overwrite the data or just `window.localStorage.clear()` which wipes everything. – gertas Aug 31 '13 at 23:15
  • That is the point. We have to create a logic for expiring something from web storage. And our logic will only run if our code (web page) is running on the browser and during that time the coded scheduler decides to expire and remove the data. I require data expiration in most of the web apps that I develop. "If" most of the overall apps developed for web require a functionality than it should be implemented and standardized by browsers. These small things save a lot of time for developers. – Jehanzeb.Malik Sep 02 '13 at 11:02
3

You would use a service for that in Angular. A service is a function you register with Angular, and that functions job is to return an object which will live until the browser is closed/refreshed. So it's a good place to store state in, and to synchronize that state with the server asynchronously as that state changes.

Anders Ekdahl
  • 22,685
  • 4
  • 70
  • 59
0

Typically for a use case which involves a sequence of pages and in the final stage or page we post the data to the server. In this scenario we need to maintain the state. In the below snippet we maintain the state on the client side

As mentioned in the above post. The session is created using the factory recipe.

Client side session can be maintained using the value provider recipe as well.

Please refer to my post for the complete details. session-tracking-in-angularjs

Let's take an example of a shopping cart which we need to maintain across various pages / angularjs controller.

In typical shopping cart we buy products on various product / category pages and keep updating the cart. Here are the steps.

Here we create the custom injectable service having a cart inside using the "value provider recipe".

'use strict';
function Cart() {
    return {
        'cartId': '',
        'cartItem': []
    };
}
// custom service maintains the cart along with its behavior to clear itself , create new , delete Item or update cart 

app.value('sessionService', {
    cart: new Cart(),
    clear: function () {
        this.cart = new Cart();
        // mechanism to create the cart id 
        this.cart.cartId = 1;
    },
    save: function (session) {
        this.cart = session.cart;
    },
    updateCart: function (productId, productQty) {
        this.cart.cartItem.push({
            'productId': productId,
            'productQty': productQty
        });
    },
    //deleteItem and other cart operations function goes here...
});
Ibrahim Khan
  • 20,616
  • 7
  • 42
  • 55
Yogesh
  • 773
  • 1
  • 8
  • 22