0

I have noticed that in one of my controllers I am getting $rootScope and $scope injected, and they both point to the same object.

Furthermore, in all my other controllers, the $scope object is shared. So whenever I inject scope, it contains the properties/methods assigned to it in all the other controllers that have so far been instantiated.

This isn't an app that I worked on from the beginning and it's pretty massive. I haven't seen this behavior before and I don't know where to begin diagnosing it. Any ideas what is causing this?

The way that we are setting up our controllers/directives is pretty standard and it looks like this:

angular.module('myApp')
  .directive('mainNav', function() {
    return {
      restrict: 'A',
      templateUrl: 'scripts/directives/mainNav/mainNav.html',
      controller: 'mainNavCtrl',
      replace: true,
      link: function(scope, element) {
          //Do DOM-related stuff
        });
      }
    };
  })
  .controller('mainNavCtrl', function($rootScope, $scope, $state) {
    //Do controller stuff
  });

We do also configure our app as follows:

angular.module('myApp', ['ui.router', 'kendo.directives'])
.config(function ($stateProvider, $urlRouterProvider) { $urlRouterProvider.otherwise('/');

$stateProvider
  .state('app', {
    url: '/',
    templateUrl: 'views/app.html',
    resolve: {
      //Fetch stuff
    }
  })
  ;   });

In response to Kursad Gulseven's comment, this is what I'm seeing in Batarang:

Batarang screenshot

The scope with ID 002 gets passed in as $scope and $rootScope to the first controller. When properties are added to $scope, they show up on $rootScope. Then all the other controllers are receiving the scope with ID 00A. So properties added to $scope in those controllers are visible to all other controllers getting $scope injected.

lintmouse
  • 5,079
  • 8
  • 38
  • 54
  • Child scopes inherit their parent scopes' properties unless overridden. Maybe that's what's happening. – Shomz Oct 31 '14 at 22:12

1 Answers1

0

$rootScope and $scope are not the same object.

If you have an object named anObject in root scope and it has an attribute named anAttribute; then you can access that attribute using $scope like this:

$scope.anObject.anAttribute

That's because Angular looks up parent scopes if it cannot find an object in $scope.

UPDATE:

Your mainNav directive should have an inherited child scope by adding scope: true. When "scope" is false, which is the default setting for directives, the parent controller and directive's controller share the same scope object. Setting scope true will create a new child scope for the directive.

Kursad Gulseven
  • 1,978
  • 1
  • 24
  • 26
  • Well, what I noticed was that rootScope and scope both have the same ID (002 in this case). Also, as I add properties to the scope in my controller, they also show up on the rootScope. Not like a child property on the rootScope, but the rootScope itself. – lintmouse Nov 01 '14 at 03:24
  • What do you see on Batarang scope tree? One single scope with id 002 or many nested scopes all of them has id 002? – Kursad Gulseven Nov 01 '14 at 22:30
  • I'm going really simple but did you search your code for anything like assigning root scope to the scope e.g. `$scope = $rootScope`? – Kursad Gulseven Nov 02 '14 at 21:48
  • No, the closest thing we have is $scope = $rootScope.$new() in some unit tests, which obviously isn't the same thing. – lintmouse Nov 03 '14 at 15:05
  • It seems weird. Maybe your `mainNav` directive should have an inherited child scope by adding `scope: true`. I don't get what's really happening in your code. If inherited scope does not work, then I'll ask you create a fiddle mimicking your problem. – Kursad Gulseven Nov 03 '14 at 16:26
  • Yeah, I can do that, but it just makes me feel uncomfortable if it's a workaround and I don't get a handle on the underlying issue. – lintmouse Nov 03 '14 at 18:48
  • When "scope" is false, which is the default setting for directives, the parent controller and directive's controller share the same scope object. Setting scope true will create a new child scope for the directive. (Isolated scopes are irrelevant to your issue.) I'm not sure if this is a workaround, you'll figure that out. I couldn't help you, sorry. By the way, did `scope: true` solve your problem? :) – Kursad Gulseven Nov 03 '14 at 21:10
  • Adding scope: true did work. But what I'm confused about is that in my test app, I didn't need to do that to achieve the behavior of a local scope. So I don't understand why it is necessary in the other app... That's why it feels like a workaround. But it's a workaround that works so if you update your answer, I'll mark it as the answer. And if I find more while digging deeper, I'll update my original post. – lintmouse Nov 04 '14 at 17:36
  • Thanks for your reply. I did update the answer. I assume you don't use mainNav directive as entry point to your test app. – Kursad Gulseven Nov 04 '14 at 17:51
  • Just setting scope to true is a tricky workaround that can lead to a lot of trouble later as these kind of things are hard to track down. With this method you are just "protecting" your directive to inherit the scope. I would suggest to search further until you find the real cause for this problem. I can not see it in your code but sometimes it is something as easy as false parameters: – timtos Nov 04 '14 at 18:11
  • .controller('mainController', ['$rootScope', '$rootScope', function ($scope, $rootScope) {... If you have something like this in your code it would explain such a behavior. But that is just an idea... – timtos Nov 04 '14 at 18:13
  • We use the short hand declaration for dependencies, so I haven't seen that scenario... – lintmouse Nov 04 '14 at 21:52
  • timtos - We are continuing to search deeper, and I will update my original post if I come up with anything. – lintmouse Nov 04 '14 at 21:54