32

I understand I can get the scope by element:

scope = angular.element($0).scope();
scope.$id; // "003"

How do I get reverse: Find the DOM element using the scope $id, such as 003?

I'd like to do this for debugging purposes. My scope tree shows something and I'd like to identify where it came from.

SimplGy
  • 19,503
  • 15
  • 101
  • 143

4 Answers4

32

Although it's not very sexy each dom node gets a class ng-scope so you could tech do something like this maybe:

function getScope(id) {
var elem;
$('.ng-scope').each(function(){
    var s = angular.element(this).scope(),
        sid = s.$id;

    if(sid == id) {
        elem = this;
        return false; // stop looking at the rest
    }
});
return elem;
}
drzaus
  • 23,063
  • 16
  • 132
  • 194
btm1
  • 3,856
  • 2
  • 21
  • 26
  • 1
    Does the trick. Guess I thought there'd be a list of scopes somewhere ripe for the fetching :) – SimplGy Apr 25 '14 at 00:25
  • 2
    I'm with ya. I wish there was too as I've encountered a need for this very thing. – btm1 Apr 25 '14 at 03:04
  • If it's a real use case, don't forget you can also crawl up from $rootScope. I've used DOM vs rootScope traversal to count and always get different numbers. http://stackoverflow.com/a/21776522/111243 – SimplGy Apr 25 '14 at 05:56
  • seems like directives don't necessarily have `.ng-scope` -- http://stackoverflow.com/a/26413528/1037948 – drzaus Oct 16 '14 at 20:41
  • I think most people want this for when they aren't using a directive...you wouldn't need this unless you are doing something pretty advanced. – btm1 Dec 18 '14 at 16:35
  • @user2173353 What do you mean the `$element` on the controller? Then pass it into the directive? – mlhDev Dec 13 '16 at 22:25
  • This is only true in development mode. You should not use this as it does not work in release mode. – MGDavies Jun 30 '17 at 09:01
7

Trying out the answer, I found that directives don't seem to have the class ng-scope, so here's a modified version that'll fallback to everything.

var getByScopeId = function(id) { 
    var filterfn = function(i,el) {
        var sc = angular.element(el).scope();

        return sc && sc.$id == id;
    };
    // low hanging fruit -- actual scope containers
    var result = $('.ng-scope').filter(filterfn);
    if(result && result.length) return result;

    // try again on everything...ugh
    return $(':not(.ng-scope)').filter(filterfn);
}

Usage:

var results = getByScopeId('003')
Community
  • 1
  • 1
drzaus
  • 23,063
  • 16
  • 132
  • 194
  • note: should use something more optimized than the `.filter` fn, i.e. stop after success http://jsfiddle.net/drzaus/3vLwzgkh/3/ – drzaus Nov 18 '14 at 15:40
  • 3
    Note: scope() only works when debug data is enabled. This is usually turned off in production for performance – Charlie Brown Dec 04 '14 at 20:58
  • It did technically work for me but I don't understand the results: n.fn.init context: document length: 0 prevObject: n.fn.init(2304) [...] [[Prototype]]: Object(0) – mjaggard Oct 20 '21 at 08:11
  • Ah, I see. Despite being present in the page when I output {{$id}} the function didn't find the ID I was looking for (hence `length:0`) – mjaggard Oct 20 '21 at 08:15
5

The same solution written in es2015, without JQuery dependency:

getElementFromScopeId = (id) => [].slice.call(document.querySelectorAll('.ng-scope')).map((x) => angular.element(x)).filter(x => x.scope().$id == id).pop();
drphrozen
  • 317
  • 3
  • 4
-1

You can always get the scope using element's id.

Example:

html:

<div id="myId"></div>

js:

  var myEl = angular.element(document.querySelector('#myId'));
  var myScope = angular.element(myEl).scope(); 

Live example : http://jsfiddle.net/choroshin/7XQA7/2/

also as David Chase suggested, you can always use batarang - Extends Chrome Developer Tools, adding tools for debugging and profiling AngularJS applications.

Alex Choroshin
  • 6,136
  • 2
  • 27
  • 35