31

Once we have a scope in hand, we can navigate to its root and explore the scope hierarchy.

But is there a direct way to find all the scopes on a page?

Likewise given an HTML element, is there a direct way to find its enclosing scope?

wl.
  • 2,270
  • 3
  • 18
  • 13

8 Answers8

80

you can see all of the scopes on the page using this CSS selector

.ng-scope { border: 1px solid red; }

and all of the bindings:

.ng-binding { border: 1px solid red; }

You can then retrieve them by converting the DOM element into selector

var selector = angular.element(some_dom_element);

Then use the selector to retrive the scope/controller/injector

var scope = selector.scope();
var controller = selector.controller();
var injector = selector.injector();
Misko Hevery
  • 47,936
  • 11
  • 40
  • 36
  • 3
    Note part of this answer is outdated: more recent Angular versions do not populate the `ng-scope` CSS class in the DOM any more. – Greg Aug 26 '14 at 03:23
24

Not all scopes are bound to elements. If you want all scopes on the page, walk the scope tree like this:

function getScopes(root) {
    var scopes = [];

    function visit(scope) {
        scopes.push(scope);
    }
    function traverse(scope) {
        visit(scope);
        if (scope.$$nextSibling)
            traverse(scope.$$nextSibling);
        if (scope.$$childHead)
            traverse(scope.$$childHead);
    }

    traverse(root);
    return scopes;
}

getScopes($rootScope)
larspars
  • 1,640
  • 1
  • 15
  • 30
  • 11
    Thank you. Also, for anybody pasting this into the console, you can replace ```$rootScope``` with ```angular.element(document.body).injector().get('$rootScope')``` – sahbeewah Apr 27 '16 at 06:22
16

I don't know why this would be useful to you, but you can do this:

scopeElements = document.getElementsByClassName('ng-scope');
scopes = [].map.call(scopeElements, function(e){ return angular.element(e).scope(); })

The other option is to traverse the scope tree starting at the root scope using our private apis: $$childHead and $$nextSibling.

It's more likely that you just want to see where the scope boundaries are and you can do it with this:

scopeElements = document.getElementsByClassName('ng-scope');
angular.element(scopeElements).css('border', '1px solid red');

Then you can just use web inspector to select an element of interest and get its scope by:

angular.element($0).scope();
Igor Minar
  • 9,574
  • 3
  • 22
  • 13
  • 3
    Note part of this answer is outdated: more recent Angular versions do not populate the ng-scope CSS class in the DOM any more – Greg Aug 26 '14 at 03:24
11

I recommend AngularJS Batarang. It's a debugging tool that lets you visualize all the scopes on the page (among other things).

https://github.com/angular/angularjs-batarang

vonkohorn
  • 1,058
  • 1
  • 9
  • 11
7

You can find out a scope for element using:

$(element).scope()

or

angular.element(element).scope()

I don't think there is a way to get all scopes on a page easily (other than navigating down from root scope).

psyho
  • 7,142
  • 5
  • 23
  • 24
  • Note this will not work if you have debugInfoEnabled(false), which is recommended for significant performance improvements in production code. https://docs.angularjs.org/guide/production – Seb Charrot Oct 26 '17 at 14:56
6

You should develop your application in Google Chrome browser (if you are not using it already) and than you can use awesome Batarang extension that adds new dedicated AngularJS panel to the Developer tools. You can see all the scopes there, what is the relationships between them and what value have all its attributes.

http://blog.angularjs.org/2012/07/introducing-angularjs-batarang.html

xMort
  • 1,545
  • 3
  • 11
  • 20
1

In Chrome, using developer tools. I use the console command line.

Pick an element in the HTML panel of the developer tools and type this in the console:

angular.element($0).scope()

or just right click on a page element and select: inspect element.

$($0).scope() will return the scope associated with the element. You can see its properties right away.

To view an elements parent scope:

$($0).scope().$parent

You can chain this also:

$($0).scope().$parent.$parent

You can look at the root scope:

$($0).scope().$root

If you highlighted a directive with isolate scope, you can look at it with:

$($0).isolateScope()

If available, you can do the same with child scope and sibling scope.

$($0).scope().$sibling

I can walk up and down the scopes to verify what scope has what controllers, objects, etc and when you are working with custom directives, it's essential. In a large code base, it's not so easy to find things like this.

Recently, I had two controllers with the same name, save for one uppercase letter attached to a view. I was using the wrong controller and it took a while before I realized that was the issue with my bindings.

James Drinkard
  • 15,342
  • 16
  • 114
  • 137
0

In Angulars there is $rootScope, which is the root of every scope.It has child field and whole hierarchy is inside $rootScope.If you want to find a scope with html element,you will probably have a problems,because that scope can be Isolated scope.Maybe you have a directive there,which scope is isolated.If you have anything like that,try to use el.isolatedScope()

Hazarapet Tunanyan
  • 2,809
  • 26
  • 30