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?

Shamoon
  • 41,293
  • 91
  • 306
  • 570
trysis
  • 8,086
  • 17
  • 51
  • 80
  • 1
    you should inject $rootScope in controller and use it as simple javascript – Ajay Beniwal Sep 18 '13 at 19:39
  • 30
    $rootScope is not the right way to do this. Making variables available across multiple controllers is pretty much what services are for. – Steve Feb 19 '14 at 15:07
  • 11
    @Steve: [Angular's FAQ](https://docs.angularjs.org/misc/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.. – Marwen Trabelsi Apr 13 '15 at 09:29
  • 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.. – landed Jun 02 '15 at 19:33
  • Why can't you inject your controller into your service @landed? – trysis Jun 02 '15 at 20:45
  • 2
    well, because its not injectable, you will need a syringe for that.. – Xsmael Nov 10 '16 at 11:22

8 Answers8

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;
    };
});
Laur Ivan
  • 4,117
  • 3
  • 38
  • 62
Jason
  • 15,915
  • 3
  • 48
  • 72
  • 8
    Plus 1 for ... uh ... actually answering OP's question. (Although @MBielski and others are right). – Rap Aug 30 '15 at 19:37
  • If I do the ``$scope.test = 'Some value'``, will the ``$rootScope.test`` change as well? – Allen Linatoc Apr 08 '16 at 01:39
  • 2
    @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 controllers – Xsmael Nov 10 '16 at 11:29
  • I'm assuming you wouldn't want to use $rootScope often for the same reason you wouldn't use global variables in other languages? – Zypps987 Jul 23 '17 at 09:16
  • How many number of rootscope variables we can create in an app? – Jay Apr 06 '18 at 08:34
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/

MBielski
  • 6,628
  • 3
  • 32
  • 43
  • 49
    +1 The `$rootScope` shouldn't be used to share variables when we have things like services and factories. – jjperezaguinaga Sep 18 '13 at 22:02
  • an approach that uses both is a sane one, maybe – Dvid Silva Nov 30 '13 at 22:42
  • 75
    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: http://docs.angularjs.org/misc/faq – Oytun Jan 19 '14 at 11:46
  • 11
    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. – MBielski Jan 20 '14 at 16:05
  • 1
    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) – Thomas Decaux Sep 16 '14 at 17:52
  • 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. – MBielski Sep 16 '14 at 17:55
  • @Oytun 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? – cortexlock Dec 17 '14 at 20:14
  • 1
    Dear God No! What you are doing is exactly what services are for. – MBielski Dec 17 '14 at 21:16
  • There is an excellent tutorial here : http://sravi-kiran.blogspot.com/2013/03/TemplatesRoutingAndSharingDataBetweenViewsInAnAngularJsApplication.html – Alexander May 19 '15 at 21:18
  • 1
    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. – landed Jun 03 '15 at 08:46
  • 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()`. – Chad Johnson Jul 27 '15 at 05:57
  • 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. – Chad Johnson Jul 27 '15 at 06:04
  • 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? – Monojit Sarkar Jun 09 '17 at 14:13
  • Because we are assigning that functionality to the scope variable that is used in the form. Go check it in the fiddle. It works. – MBielski Jun 09 '17 at 15:19
  • @jjperezaguinaga what do you mean? [$rootScope is a service](https://docs.angularjs.org/api/ng/service/$rootScope), in fact. – Marcos R Nov 15 '18 at 08:26
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

Nitish Kumar
  • 4,850
  • 3
  • 20
  • 38
  • So in Angular you don't usually use var? – trysis Sep 18 '13 at 19:43
  • 1
    its depends on condition. if want to show in html then u need to use otherwise u can use var – Nitish Kumar Sep 18 '13 at 19:44
  • Oh scope is for DOM stuff? – trysis Sep 18 '13 at 19:46
  • 1
    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 http://docs.angularjs.org/guide/scope – yantaq Apr 07 '14 at 19:44
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.

roconmachine
  • 1,876
  • 2
  • 17
  • 24
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.

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/

Raza Ahmed
  • 2,661
  • 2
  • 35
  • 46
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';
 });
sathish
  • 21
  • 1
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);
})
ojus kulkarni
  • 1,877
  • 3
  • 25
  • 41