0

I am creating an login page using Angular. After I process my login in the backend, I set the values in MyService from my LoginCtrl and then move to the next page using $window.location.href= 'main.jsp'; . But when I call the values which I set in LoginCtrl from HomeCtrl, the values are empty?

I know that Services are singletons and will maintain the same state throughout the app. But in this case, It jut resets. I think it is because of using $window.location.href. Please help me solve my problem.

This is my service ( MyService ):

app.service('MyService', function() {
    var user = {
        name: '',
        permissions: ''
    };

    this.getUser = function() {
        return user;
    }

    this.setUser = function(userr) {
        this.user = userr;
    }
});

This my LoginCtrl: ( I've just posted the http.post part)

$http({
                method: 'POST',
                url: 'login',
                data: JSON.stringify($scope.user),
                headers: {
                    'Content-Type': 'application/json'
                }
            }).success(function(data) {
                if (!("failure" == data)) {
                    console.log(data);
                    var user = MyService.getUser();
                    user.name = data.name;
                    user.permissions = data.permissions;
                    console.log(user);
                    console.log(MyService.getUser());

                     $window.location.href = 'main.jsp';
                    // MyService.changeLocation('main.jsp', true);
                } else {
                    $scope.information = "Invalid username/password!"
                }
            }).error(function(data) {
                console.log(data);
            });

And this is my HomeCtrl:

app.controller('HomeCtrl', function($scope, $http,MyService) {

    console.log(MyService.getUser());
    var user = MyService.getUser();
    $scope.flashMessage="Hello " + user.name;
});

Here user.name is empty.

v1shnu
  • 2,211
  • 8
  • 39
  • 68
  • where are you setting the user anyways ? I cannot see `setUser()` being used – nalinc Jul 17 '15 at 11:58
  • I mean, in LoginCtrl, while reaching the `sussess` callbak, shouldnt you be setting the response values to user object first ? – nalinc Jul 17 '15 at 12:00
  • I get the User object from the Service and setting the values to that object. Will that not set the user object in the Service as well ? – v1shnu Jul 17 '15 at 12:46
  • Nope that wont work, see the updated answer – nalinc Jul 17 '15 at 13:03

2 Answers2

1

You are changing your web page. The angular application is not persisted across the website boundary; remove the alteration to the window.location.href.

In order to simulate page changing in Angular consider using the official router (shipped with Angular 1.4+), ngRoute or Angular UI Router. These solutions use the HTML History Api and fallback to hashbang URLs to emulate the sort of thing you're trying to achieve.

This ends up creating a single-page application, which is what Angular is designed for.

Dan
  • 10,282
  • 2
  • 37
  • 64
  • Actually I have used Angular routing in the page which it gets redirected to. There, I will be using views to make it as a SPA. Is there any other way I can make this happen ? – v1shnu Jul 17 '15 at 12:48
0

In LoginCtrl, while reaching the success callback, you are not setting the response value(data in your case) to user object in MyService service.

You are getting the user object from the Service by

var user = MyService.getUser();

But setting the values to that object will not set the user object in the Service.

You need to use MyService.getUser(user); to set values in your service and the same will be available in your HomeCtrl

    $http({
            method: 'POST',
            url: 'login',
            data: JSON.stringify($scope.user),
            headers: {
                'Content-Type': 'application/json'
            }
        }).success(function(data) {
            if (!("failure" == data)) {
                console.log(data);
                var user= {};
                user.name = data.name;
                user.permissions = data.permissions;
                MyService.getUser(user);  //set the values for user 
                var obj= MyService.getUser();   //get the values for user

                console.log(obj);   
               //should display user object 
               //with respective name and permissions should be available

                console.log(MyService.getUser());

                 $window.location.href = 'main.jsp';
                // MyService.changeLocation('main.jsp', true);
            } else {
                $scope.information = "Invalid username/password!"
            }
        }).error(function(data) {
            console.log(data);
        });

UPDATE:

The reason why your code doesnt seem to work is: you are using $window incorrectly to change the route. $window.location.href = 'main.html' is somehow changing the route outside angular's context and hence not running the HomeCtrl. To fix this, you need to do the following:

  • First, define routes for your angular application (preferabbly using ui-router)

     app.config(function($stateProvider){
       $stateProvider
           .state('login',{
                 url:'/', 
                 templateUrl:'login.html',          
                 controller:'LoginCtrl'
             })
             .state('main',{
                 url:'/main',
                 templateUrl:'main.html',
                 controller:'HomeCtrl'
             })
              .state("otherwise", { url : '/'})
       })
    
  • Use $location.url('/main'). Notice it is same as the url pattern we defined for state: main. Or better, you should use $state.go('home'); to redirect the user to desirable state

Here's a working plunkr

Hope this helps!

nalinc
  • 7,375
  • 24
  • 33
  • Here, I can't pass data directly to the service. Since the data returns with a list of entries while my service uses only name and permission. So can I set the values to the user object and then pass it to the service ?? – v1shnu Jul 17 '15 at 13:09
  • Did the above. Still couldn't find my service with the set values in the next page . – v1shnu Jul 17 '15 at 13:17
  • @ViChU: Hi, I have added a working [**plunkr**](http://plnkr.co/edit/C4mwUTqR1fWOGb99XqtP?p=preview). Its modified a bit but works best to fit the scenario. Please have a look. – nalinc Jul 20 '15 at 11:50
  • @ViChU: Basically, the reason why your code aint working is: `$window.location.href = 'main.html'` is not invoking the *controller* corresponding to main.html(which is **HomeCtrl**). It is not resetting, it is not setting at all. – nalinc Jul 20 '15 at 11:53
  • please check this question of mine which is also the same issue -http://stackoverflow.com/questions/31514988/maintain-angular-service-through-page-change – v1shnu Jul 20 '15 at 12:28
  • I have actually used routing but only after my authentication is done and it is redirected to the main.html. Inside main.html, I have used different routes configured using ngRoute. – v1shnu Jul 20 '15 at 12:29
  • 1
    I went with this approach of mine since my login page does not contain a navbar and just the username and password form. After my authentication is done, I will redirect to the main page which has a navbar in the top. The content below that changes where I have used routing. I just don't know how to get this fixed or how I can find an alternative solution – v1shnu Jul 20 '15 at 12:31
  • How about using only in index.html ? for **login state**, it will contain login template(with username/password fields)..and for **main** state, `` would contain a navbar, a footer(maybe) and a *content* – nalinc Jul 20 '15 at 12:34
  • That is how your index.html should look like, ` `.. How you populate ng-view is upto user authentication/login-state :) – nalinc Jul 20 '15 at 12:36
  • In this case, I will have to add the navbar in each of the partials which I will be using. So I thought of isolating the navbar from the rest of the code. If nothing works, then that is the only way to go. – v1shnu Jul 20 '15 at 12:36
  • Still waiting to see if there are any possibilities of getting this done. – v1shnu Jul 20 '15 at 12:38
  • better use a directive for navbar..something like ;) – nalinc Jul 20 '15 at 12:38
  • ya, that seems to be a good idea . Anyways thanks for ur help man :) – v1shnu Jul 20 '15 at 12:39
  • Well, that is the drawback of **ngRouter**: it does NOT allow nested views(while **ui-router** does). Had you be using ui-router, you could have a **nested view** inside main.html(which itself is a view in index.html) – nalinc Jul 20 '15 at 12:39
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/83747/discussion-between-vichu-and-nln). – v1shnu Jul 20 '15 at 12:41
  • @ViChU: No worries mate ;) I'll soon come up with an implementation with **ngRouter**. This one is with [ui-router](http://plnkr.co/edit/C4mwUTqR1fWOGb99XqtP?p=preview) – nalinc Jul 20 '15 at 12:42