By Lightbulb1


2012-08-13 16:27:07 8 Comments

I have a problem where i'm initialising a variable on the scope in a controller. Then it gets changed in another controller when a user logs in. This variable is used to control things such as the navigation bar and restricts access to parts of the site depending on the type of user, so its important that it holds its value. The problem with it is that the controller that initialises it, gets called again by angular some how and then resets the variable back to its initial value.

I assume this is not the correct way of declaring and initialising global variables, well its not really global, so my question is what is the correct way and is there any good examples around that work with the current version of angular?

12 comments

@Megaman 2017-01-23 14:40:06

You can also use the environment variable $window so that a global variable declare outside a controller can be checked inside a $watch

var initWatch = function($scope,$window){
    $scope.$watch(function(scope) { return $window.globalVar },
        function(newValue) {
            $scope.updateDisplayedVar(newValue);
    });
}

Becareful, the digest cycle is longer with these global values, so it is not always real-timed updated. I need to investigate on that digest time with this configuration.

@Andy Corman 2018-10-09 22:13:49

It's actually pretty easy. (If you're using Angular 2+ anyway.)

Simply add

declare var myGlobalVarName;

Somewhere in the top of your component file (such as after the "import" statements), and you'll be able to access "myGlobalVarName" anywhere inside your component.

@Rahul Murari 2018-06-29 06:51:52

Try this, you will not force to inject $rootScope in controller.

app.run(function($rootScope) {
    $rootScope.Currency = 'USD';
});

You can only use it in run block because config block will not provide you to use service of $rootScope.

@Black Mamba 2017-06-12 10:21:47

I just found another method by mistake :

What I did was to declare a var db = null above app declaration and then modified it in the app.js then when I accessed it in the controller.js I was able to access it without any problem.There might be some issues with this method which I'm not aware of but It's a good solution I guess.

@Kevin 2014-03-17 22:46:11

localStorage.username = 'blah'

If you're guaranteed to be on a modern browser. Though know your values will all be turned into strings.

Also has the handy benefit of being cached between reloads.

@Shaz 2014-10-04 17:19:41

Heh, I'm going to store all variables via localStorage. We will even have some sort of persistency then! Also, to get around the string limitation, let's store the .toString() of a function then eval it when needed!

@┼╗ubrówka 2016-09-05 13:11:51

like already mentioned by @Shaz, this has the problem of persistency

@Dean Or 2014-06-16 17:28:13

If you just want to store a value, according to the Angular documentation on Providers, you should use the Value recipe:

var myApp = angular.module('myApp', []);
myApp.value('clientId', 'a12345654321x');

Then use it in a controller like this:

myApp.controller('DemoController', ['clientId', function DemoController(clientId) {
    this.clientId = clientId;
}]);

The same thing can be achieved using a Provider, Factory, or Service since they are "just syntactic sugar on top of a provider recipe" but using Value will achieve what you want with minimal syntax.

The other option is to use $rootScope, but it's not really an option because you shouldn't use it for the same reasons you shouldn't use global variables in other languages. It's advised to be used sparingly.

Since all scopes inherit from $rootScope, if you have a variable $rootScope.data and someone forgets that data is already defined and creates $scope.data in a local scope you will run into problems.


If you want to modify this value and have it persist across all your controllers, use an object and modify the properties keeping in mind Javascript is pass by "copy of a reference":

myApp.value('clientId', { value: 'a12345654321x' });
myApp.controller('DemoController', ['clientId', function DemoController(clientId) {
    this.clientId = clientId;
    this.change = function(value) {
        clientId.value = 'something else';
    }
}];

JSFiddle example

@Blaise 2014-07-07 18:22:34

When I changed the value on one view, the new value is not persistent. How come? Can you please update your answer and let us see how your clientId can be updated?

@Nabarun 2014-07-19 23:00:19

@DeanOr Is it possible to preserve the updated value between refreshes of the page? The value gets reinitialised if I refresh the page.

@Dean Or 2014-07-24 17:35:29

You'll have to use something else for that like a cookie, local storage, or database.

@jemiloii 2016-12-03 00:09:55

I really like this one the best. I can now modify by build process for dev, stage, and prod

@RushabhG 2017-04-05 10:38:55

There is a simple article explaining the use of constants and values similar to Global variables: ilikekillnerds.com/2014/11/…

@pgpv 2017-05-09 08:52:02

"The other option is to use $rootScope, but it's not really an option because you shouldn't use it for the same reasons you shouldn't use global variables in other languages. It's advised to be used sparingly." Sparingly doesn't mean never. If you have a real and proper use for a global variable you SHOULD do it. That's the whole point of global variables, that's why they exist.

@user742030 2015-08-28 22:17:24

// app.js or break it up into seperate files
// whatever structure is your flavor    
angular.module('myApp', [])    

.constant('CONFIG', {
    'APP_NAME' : 'My Awesome App',
    'APP_VERSION' : '0.0.0',
    'GOOGLE_ANALYTICS_ID' : '',
    'BASE_URL' : '',
    'SYSTEM_LANGUAGE' : ''
})

.controller('GlobalVarController', ['$scope', 'CONFIG', function($scope, CONFIG) {

    // If you wish to show the CONFIG vars in the console:
    console.log(CONFIG);

    // And your CONFIG vars in .constant will be passed to the HTML doc with this:
    $scope.config = CONFIG;
}]);

In your HTML:

<span ng-controller="GlobalVarController">{{config.APP_NAME}} | v{{config.APP_VERSION}}</span>

@pkozlowski.opensource 2012-08-13 16:54:18

You've got basically 2 options for "global" variables:

$rootScope is a parent of all scopes so values exposed there will be visible in all templates and controllers. Using the $rootScope is very easy as you can simply inject it into any controller and change values in this scope. It might be convenient but has all the problems of global variables.

Services are singletons that you can inject to any controller and expose their values in a controller's scope. Services, being singletons are still 'global' but you've got far better control over where those are used and exposed.

Using services is a bit more complex, but not that much, here is an example:

var myApp = angular.module('myApp',[]);
myApp.factory('UserService', function() {
  return {
      name : 'anonymous'
  };
});

and then in a controller:

function MyCtrl($scope, UserService) {
    $scope.name = UserService.name;
}

Here is the working jsFiddle: http://jsfiddle.net/pkozlowski_opensource/BRWPM/2/

@Jakob Stoeck 2013-02-21 15:52:15

From the Angular FAQ: Conversely, don't create a service whose only purpose in life is to store and return bits of data.

@Craig Myles 2013-05-08 06:53:08

I'm using the Express + Angular seed by Btford. If I set a variable on the $rootScope in Controller1 say and move to another url (powered by Controller2 say) I can access this variable. However if I refresh the page on Controller2 then the variable is no longer accessible on $rootScope. If I am saving user data on sign in how can I ensure this data is accessible elsewhere even on page refresh?

@fmquaglia 2013-05-20 18:58:32

I've added a more complete version of the original jsFiddle here

@user1876508 2013-07-17 21:31:29

Does anyone have examples of using rootScope in this case?

@Michael J. Calkins 2013-08-24 17:37:47

I prefer to have a MainCtrl that encompasses my entire app. I keep any global values on that level. $scope.main.user = { name: "anonymous" } and then all my child ctrl's have access to the $scope.main object.

@deck 2013-09-06 06:53:22

@JakobStoeck I have been waffling on whether or not to use a service for environmental values. Ended up using $provider.config() on my app module.

@mohamnag 2014-02-05 13:59:17

interestingly the angular seed DOES use a service only for a value. and my question is, isn't it better to use a service as this can be tested but anything to rootScope nor in config can not be easily tested. correct me if I'm wrong.

@user2483724 2014-03-18 23:39:14

@JakobStoeck Combine this with this answer and you're left with putting the data on the rootScope. I don't think that's right either. What's the angular way of storing and returning globally used bits of data?

@Alireza Mirian 2014-08-13 22:26:01

@JakobStoeck So why there is a value recipe?! Actually its only purpose in life is store and return a value!

@Adrian Lopez 2014-12-21 17:11:19

Then what's the alternative @JakobStoeck? sessionStorage?

@Brian 2015-01-21 17:54:19

I'm curious what the disadvantages are of a service that is specifically for storing values. Isolated, only injected where you need it, and easily testable. What is the downside?

@a14m 2015-01-29 13:43:54

does using service as global variables persist between page refreshes ? It works fine and the value is persisted between views till I refresh... and it became blank ?! am I doing it wrongly ?!

@Cédric 2015-04-09 14:00:56

@artmees You can store your variables into cookies then restore them on refresh (during app loading)

@Max Yari 2015-06-26 19:41:48

oh god, why everybody is afraid of reaal global variables, if you know what your app will consist of, just make a real global js variable instead overcomplicating stuff

@Iwan1993 2015-07-05 14:55:43

I updated the fiddle, as references passed by property will not be bind to properties of type of e.g. boolean. jsfiddle.net/BRWPM/1456

@ksa_coder 2015-11-24 20:05:52

If I create the service as mentioned above, how can i update its variable values? let's say name must be updated from controller.

@m1ld 2016-05-26 12:52:42

In 2016 I can't find in FAQ any mention about constants.

@ChiefTwoPencils 2016-12-16 23:06:18

@ksa_coder, I know it's late but for future readers: if you inject SomeService into SomeController (self) and wanted to set the name variable from there you'd do: SomeService.name = self.name;. Know that the service is a singleton and therefore its name variable could be changed from any component which has it injected.

@negrotico19 2020-03-10 17:14:28

I think if we have multiple controllers, say a lot. And we need some "global variables" available for all controllers, let's say the userId. Then By using Services will required a lot of service injections into controllers. In this scenario I'll prefer to use $rootScope but what is the best practice?

@jason328 2015-01-22 19:31:36

Please correct me if I'm wrong, but when Angular 2.0 is released I do not believe$rootScope will be around. My conjecture is based on the fact that $scope is being removed as well. Obviously controllers, will still exist, just not in the ng-controller fashion.Think of injecting controllers into directives instead. As the release comes imminent, it will be best to use services as global variables if you want an easier time to switch from verison 1.X to 2.0.

@CatalinBerta 2015-03-23 14:50:53

I agree, putting data directly onto $rootScope is against Angular's whole purpose. Take a bit of time and organize your code properly and it will help you, not only in the AngularJS 2.x upgrade, but generally throughout your app's development as it grows more complex.

@uylmz 2016-06-10 16:30:57

If $rootScope is removed, just write a new service that's called "$rootScope" :)

@user909694 2014-12-19 19:37:18

In the interest of adding another idea to the wiki pool, but what about AngularJS' value and constant modules? I'm only just starting to use them myself, but it sounds to me like these are probably the best options here.

Note: as of the time of writing, Angular 1.3.7 is the latest stable, I believe these were added in 1.2.0, haven't confirmed this with the changelog though.

Depending on how many you need to define, you might want to create a separate file for them. But I generally define these just before my app's .config() block for easy access. Because these are still effectively modules, you'll need to rely on dependency injection to use them, but they are considered "global" to your app module.

For example:

angular.module('myApp', [])
  .value('debug', true)
  .constant('ENVIRONMENT', 'development')
  .config({...})

Then inside any controller:

angular.module('myApp')
  .controller('MainCtrl', function(debug, ENVIRONMENT), {
    // here you can access `debug` and `ENVIRONMENT` as straight variables
  })

From the initial question is actually sounds like static properties are required here anyway, either as mutable (value) or final (constant). It's more my personal opinion than anything else, but I find placing runtime configuration items on the $rootScope gets too messy, too quickly.

@Ben Wheeler 2015-05-01 17:24:13

I find the value module very useful and concise. especially when you bind it to a $scope variable within a controller, so that changes within that controller's logic or view are bound to the global variable/value/service

@pkdkk 2014-07-31 12:36:25

You can also do something like this ..

function MyCtrl1($scope) {
    $rootScope.$root.name = 'anonymous'; 
}

function MyCtrl2($scope) {
    var name = $rootScope.$root.name;
}

@Ahmad Ahmadi 2015-06-10 13:04:27

$rootScope is undefined when you use it this way.

@NateFriedman 2013-09-01 16:30:40

Example of AngularJS "global variables" using $rootScope:

Controller 1 sets the global variable:

function MyCtrl1($scope, $rootScope) {
    $rootScope.name = 'anonymous'; 
}

Controller 2 reads the global variable:

function MyCtrl2($scope, $rootScope) {
    $scope.name2 = $rootScope.name; 
}

Here is a working jsFiddle: http://jsfiddle.net/natefriedman/3XT3F/1/

@Tony Lâmpada 2013-09-20 15:22:30

This does not work in views of isolated scope directives. See jsfiddle.net/3XT3F/7. But you can use $root to work around it. See jsfiddle.net/3XT3F/10. Thanks to @natefaubion for pointing it out

@xyonme 2015-01-16 03:43:41

on refresh, $rootScope value would be empty.

@user2136053 2017-01-16 07:09:08

hardcoding the $rootScope.name equals some value..actually we need to read it and set it there.

Related Questions

Sponsored Content

20 Answered Questions

[SOLVED] Using global variables in a function

6 Answered Questions

[SOLVED] How do I use $scope.$watch and $scope.$apply in AngularJS?

7 Answered Questions

[SOLVED] 'this' vs $scope in AngularJS controllers

18 Answered Questions

19 Answered Questions

[SOLVED] How do I access the $scope variable in browser's console using AngularJS?

14 Answered Questions

[SOLVED] How does data binding work in AngularJS?

30 Answered Questions

17 Answered Questions

[SOLVED] How to declare global variables in Android?

1 Answered Questions

Sponsored Content