1

I am working with angular js at view layer. I need to use some global variable that will be used and modified by all the controllers method in my application:

 var app = angular.module('myWebservice', ['ngCookies']).run(
    function($rootScope) {
        $rootScope.authToken = null; }); 

 app.controller('UserController', function($cookieStore, $scope, $location,
    $routeParams, $http, $timeout, $rootScope) {

        $scope.login= function() {

    $http.defaults.headers.post = {'Accept' : 'application/json',
        'Content-Type' : 'application/json'};

    $http.post('/myServise/api/user/login-user', {
                        emailId : $scope.username,
                        password : $scope.password

                    }).success(function(data, status) {
                        if (status == 200) {
            $rootScope.authToken = data.object.authToken;
                }).error(function(data, status) {           
                        console.debug(data);});
        }// Else end

};// End Login


app.controller('MerchantController', function($cookieStore, $scope, $location,
    $routeParams, $http, $timeout, $rootScope) {

    $scope.getRootScopeValues = function() 
    //$scope.getRootScopeValues = function($rootScope) 
    {
        $scope.token = $rootScope.authToken;
        console.log($scope.token);// Undefined 
        console.log($rootScope.authToken);// Undefined 
    }
});

I am new to Angular JS, I have also tried to use service but I don't know why I am not able to access global variable (authToken). Please help me I am stuck at this point ....Thanks in advance...

5
  • This is probably because you are trying to access authToken before it is set by the $http post. Commented Apr 7, 2014 at 5:32
  • First I call login and in login method I get authToken and then after set to rootScope at that time if I logged I get value of authToken. Commented Apr 7, 2014 at 5:41
  • I mean you are probably trying tp console.log the authToken in MerchantController before the HTTP request is completed in UserController. Commented Apr 7, 2014 at 5:47
  • No no, Actually when I have done execution with login then only I am calling getRootScopeValues function. When user login then he clicks on link where i have written ng-click="getRootScopeValues()". I can see server logs as well accordingly. Commented Apr 7, 2014 at 5:58
  • The $http.post() returns a promise which means that the value if authToken is set asynchronously (i.e. after the call to login() has completed. So... Commented Apr 7, 2014 at 6:07

2 Answers 2

1

I am not sure how your application works but looks like you have a problem of asynchronous calls (while $http is working you are trying to access the variable which is not set yet). Please look at this answer about Asynchronous calls. Maybe this is your case? Also I should note that using $rootScope is always a bad idea. Try to avoid it. You should use service instead which is also a singleton object and always a much better and maintainable approach.

Sign up to request clarification or add additional context in comments.

4 Comments

+ 1. Service as singleton is definitely the way to go.
I have tried to use service as well but same results "Undefined"
Using rootScope or a service is not a problem here. The problem with using asynchronous calls. You should use callbacks for $http or promises to handle the result.
app.service('shared', function() { var sharedData = { authToken : ''}; return { setAuthToken : function(v) { sharedData.authToken = v; }, update : function() { return sharedData;} } });
0

I need to use some global variable that will be used and modified by all the controllers method in my application

The best way to achieve this is using a Service, but you don't have to if you would like to leave it at the $rootScope

I have tried to use service as well but same results "Undefined"

Because the call for the authToken is asynchronous, the controller could run before the token returns from remote server.

You can add the token retrieval logic to the route definition as a 'resolve' field like this:

.config(function($routeProvider, $locationProvider) {
  $routeProvider
   .when('/your/route', {
    templateUrl: 'book.html',
    controller: 'BookController',
    resolve: {      
      token: function() {
        //return a promise with the token here
      }
    }
  })

However, this is NOT good in your case as you will have to setup the 'resolve' for every route. If you are using AngularUI Route that supports nested routes, you can simply add the 'resolve' to the root state/route. This is what I've been using in my project.

If you are not using AngularUI Route, there's another way of doing it. You can assign the returned value of the $http.post to a variable in the $rootScope e.g. $rootScope.tokenPromise. The returned of $http.post is a promise, you can use the 'then; method to register callbacks, and these callbacks will receive a single argument – an object representing the response.

In your controller, you will have put some extra lines, you will get the token asynchronously like this

app.controller('MerchantController', function($cookieStore, $scope, $location,
    $routeParams, $http, $timeout, $rootScope) {

    $rootScope.tokenPromise.then( function(token){
        console.log(token); //depends on the returned data structure

    } )

});

In your application 'run' block, you will have to create a promise at $rootScope.tokenPromise. you can either use $http to retrieve the token and get the promise there in the run block, or create a pending promise and retrieve the token elsewhere in other places, after which you can resolve the promise.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.