How do I use $rootScope in Angular to store variables?
Asked Answered
D

8

219

How do I use $rootScope to store variables in a controller I want to later access in another controller? For example:

angular.module('myApp').controller('myCtrl', function($scope) {
  var a = //something in the scope
  //put it in the root scope
});

angular.module('myApp').controller('myCtrl2', function($scope) {
  var b = //get var a from root scope somehow
  //use var b
});

How would I do this?

Decasyllabic answered 18/9, 2013 at 19:31 Comment(6)
you should inject $rootScope in controller and use it as simple javascriptPadus
$rootScope is not the right way to do this. Making variables available across multiple controllers is pretty much what services are for.Hydrokinetics
@Steve: Angular's FAQ says "don't create a service whose only purpose in life is to store and return bits of data" This will put too much load on the $digest cycle..Gearhart
If I cannot inject controllers into services how do I send a variable from your said service to my other controller ? I see no way to get this working...appreciate your insight here..Kutch
Why can't you inject your controller into your service @landed?Decasyllabic
well, because its not injectable, you will need a syringe for that..Damper
H
251

Variables set at the root-scope are available to the controller scope via prototypical inheritance.

Here is a modified version of @Nitish's demo that shows the relationship a bit clearer: http://jsfiddle.net/TmPk5/6/

Notice that the rootScope's variable is set when the module initializes, and then each of the inherited scope's get their own copy which can be set independently (the change function). Also, the rootScope's value can be updated too (the changeRs function in myCtrl2)

angular.module('myApp', [])
.run(function($rootScope) {
    $rootScope.test = new Date();
})
.controller('myCtrl', function($scope, $rootScope) {
  $scope.change = function() {
        $scope.test = new Date();
    };

    $scope.getOrig = function() {
        return $rootScope.test;
    };
})
.controller('myCtrl2', function($scope, $rootScope) {
    $scope.change = function() {
        $scope.test = new Date();
    };

    $scope.changeRs = function() {
        $rootScope.test = new Date();
    };

    $scope.getOrig = function() {
        return $rootScope.test;
    };
});
Highpriced answered 18/9, 2013 at 19:55 Comment(5)
Plus 1 for ... uh ... actually answering OP's question. (Although @MBielski and others are right).Identic
If I do the $scope.test = 'Some value', will the $rootScope.test change as well?Microdot
@AllenLinatoc no, it wont they are two different objects although the scope of $rootScope is global (over all controllers) but $scope remains local to the controller. If you use $scope.test in two different controllers, know they are two different variable whether $rootScope.test would be the same variable in all controllersDamper
I'm assuming you wouldn't want to use $rootScope often for the same reason you wouldn't use global variables in other languages?Labour
How many number of rootscope variables we can create in an app?Foam
I
161

Sharing data between controllers is what Factories/Services are very good for. In short, it works something like this.

var app = angular.module('myApp', []);

app.factory('items', function() {
    var items = [];
    var itemsService = {};

    itemsService.add = function(item) {
        items.push(item);
    };
    itemsService.list = function() {
        return items;
    };

    return itemsService;
});

function Ctrl1($scope,items) {
    $scope.list = items.list; 
}

function Ctrl2($scope, items) {
    $scope.add = items.add;
}

You can see a working example in this fiddle: http://jsfiddle.net/mbielski/m8saa/

Impeller answered 18/9, 2013 at 20:52 Comment(15)
+1 The $rootScope shouldn't be used to share variables when we have things like services and factories.Superadd
an approach that uses both is a sane one, maybeSferics
Well, Angular FAQ says this at the bottom of the page: "Conversely, don't create a service whose only purpose in life is to store and return bits of data." See: docs.angularjs.org/misc/faqEuthenics
This is a simple example. I believe that they are saying not to have a service that appears in only one controller. I can't count how many places the staff that developed Angular have specifically said that services are the official way to pass data between controllers. Look around the mailing list, ask the various Angular luminaries, and see what you get. I might also note that your quote is at the bottom of the section entitled "$rootScope exists, but it can be used for evil." Passing data from one controller to another is evil.Impeller
But if you need to loop though your items in two different view/controller, you need to copy the data first in the controller to give it to the view? (I believe this is $rootScope solved)Franci
No, you don't need to copy it. Services are singletons, so the data is the same in any view/controller that the service appears in.Impeller
@Euthenics Tez I'm really intrigued by this comment in the Angular docs. Why do they say this? Reason being, I'm currently creating a service that queries a SQL database and returns data. Should I do this on $rootScope instead?Aubine
Dear God No! What you are doing is exactly what services are for.Impeller
There is an excellent tutorial here : sravi-kiran.blogspot.com/2013/03/…Deel
It is up to the developer to use judgement as to whether a service should be used or a rootScope quick fix, for some things the global scope is a facility and a handy one - and I think thats what Angular docs are trying to say. Lets keep the art in programming and not become robots to MVC blah blah blah entirely. You might use the above service and $watch the variable if you need one controller to know about the change however as it stands here its not really communication between controllers.Kutch
I would suggest being careful to not blindly jump to using a service to share data between controllers. In many cases, controller inheritance can be employed via $scope or controllerAs. For instance, if you're using UI Router, you can create a parent state and share data from it with all children states. Remember services are singletons and live throughout the entire life of the app, while controllers are reinstantiated each time they're used. A good case for sharing data via a service might be when several controllers need access to the same data; for instance, authService.getAccount().Sudor
Following up with my last comment, note that authService provides access to data needs to be available throughout the lifetime of the app (i.e. the account data). Also, authService would likely provide behavior surrounding the account data, such as an authService.authenticate() method. Lastly I would say the "items" service here is pretty much the same thing as a Data Transfer Object, and those are often considered evil and a sign of code smell. If you're using a bunch of services just to store data, I'd re-think your architectural approach.Sudor
i just see your code and one area is not clear that you called $scope.add = items.add; but not passing any value to add function...why?Mcgary
Because we are assigning that functionality to the scope variable that is used in the form. Go check it in the fiddle. It works.Impeller
@Superadd what do you mean? $rootScope is a service, in fact.Adagio
N
22
angular.module('myApp').controller('myCtrl', function($scope, $rootScope) {
   var a = //something in the scope
   //put it in the root scope
    $rootScope.test = "TEST";
 });

angular.module('myApp').controller('myCtrl2', function($scope, $rootScope) {
   var b = //get var a from root scope somehow
   //use var b

   $scope.value = $rootScope.test;
   alert($scope.value);

 //    var b = $rootScope.test;
 //  alert(b);
 });

DEMO

Necropsy answered 18/9, 2013 at 19:39 Comment(4)
So in Angular you don't usually use var?Decasyllabic
its depends on condition. if want to show in html then u need to use otherwise u can use varNecropsy
Oh scope is for DOM stuff?Decasyllabic
This may be late but for any late comer, scope is a glue between view and controller per AJS documentation. scope does not directly references DOM. then what it does? here is more thorough docs docs.angularjs.org/guide/scopeRamonaramonda
U
9

i find no reason to do this $scope.value = $rootScope.test;

$scope is already prototype inheritance from $rootScope.

Please see this example

var app = angular.module('app',[]).run(function($rootScope){
$rootScope.userName = "Rezaul Hasan";
});

now you can bind this scope variable in anywhere in app tag.

Underpass answered 2/7, 2015 at 5:57 Comment(0)
G
6

first store the values in $rootScope as

.run(function($rootScope){
$rootScope.myData = {name : "nikhil"}
})

.controller('myCtrl', function($scope) {
var a ="Nikhilesh";
$scope.myData.name = a;
});

.controller('myCtrl2', function($scope) {
var b = $scope.myData.name;
)}

$rootScope is the parent of all $scope, each $scope receives a copy of $rootScope data which you can access using $scope itself.

Galleon answered 1/5, 2016 at 3:50 Comment(0)
T
3

If it is just "access in other controller" then you can use angular constants for that, the benefit is; you can add some global settings or other things that you want to access throughout application

app.constant(‘appGlobals’, {
    defaultTemplatePath: '/assets/html/template/',
    appName: 'My Awesome App'
});

and then access it like:

app.controller(‘SomeController’, [‘appGlobals’, function SomeController(config) {
    console.log(appGlobals);
    console.log(‘default path’, appGlobals.defaultTemplatePath);
}]);

(didn't test)

more info: http://ilikekillnerds.com/2014/11/constants-values-global-variables-in-angularjs-the-right-way/

Trier answered 8/3, 2016 at 9:57 Comment(0)
E
2

http://astutejs.blogspot.in/2015/07/angularjs-what-is-rootscope.html

 app.controller('AppCtrl2', function ($scope, $rootScope) {
     $scope.msg = 'SCOPE';
     $rootScope.name = 'ROOT SCOPE';
 });
Entoblast answered 17/7, 2015 at 1:58 Comment(0)
M
1

There are multiple ways to achieve this one:-

1. Add $rootScope in .run method

.run(function ($rootScope) {
    $rootScope.name = "Peter";
});

// Controller
.controller('myController', function ($scope,$rootScope) {
    console.log("Name in rootscope ",$rootScope.name);
    OR
    console.log("Name in scope ",$scope.name);
});

2. Create one service and access it in both the controllers.

.factory('myFactory', function () {
     var object = {};

     object.users = ['John', 'James', 'Jake']; 

     return object;
})
// Controller A

.controller('ControllerA', function (myFactory) {
    console.log("In controller A ", myFactory);
})

// Controller B

.controller('ControllerB', function (myFactory) {
    console.log("In controller B ", myFactory);
})
Moloch answered 9/10, 2016 at 20:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.