How do I access the $scope variable in browser's console using AngularJS?
Asked Answered
E

20

1317

I would like to access my $scope variable in Chrome's JavaScript console. How do I do that?

I can neither see $scope nor the name of my module myapp in the console as variables.

Eblis answered 6/12, 2012 at 11:52 Comment(4)
For debugging I usually set window.MY_SCOPE = $scope; first thing in my controller function.Polysyllable
If you're considering development/testing in Firefox, you can also use AngScope, a small extension that displays $scope objects of selected DOM elements into Firebug's DOM Inspector.Arcboutant
@JasonGoemaat why not use window.$scope = $scope; so that you can simply use $scope rather than MY_SCOPE - I haven't noticed any problems but maybe i'm missing a security concern or something.Leftwards
Just for clarity, someone new to angular might get confused and think that $scope was magically available in the console if the just saw it being used that way. Also if you then mistakenly use scope in a directive declaration and $scope in the code for instance, you'd be using that on the window object instead of getting an error.Polysyllable
L
1858

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

angular.element($0).scope()

In WebKit and Firefox, $0 is a reference to the selected DOM node in the elements tab, so by doing this you get the selected DOM node scope printed out in the console.

You can also target the scope by element ID, like so:

angular.element(document.getElementById('yourElementId')).scope()

Addons/Extensions

There are some very useful Chrome extensions that you might want to check out:

  • Batarang. This has been around for a while.

  • ng-inspector. This is the newest one, and as the name suggests, it allows you to inspect your application's scopes.

Playing with jsFiddle

When working with jsfiddle you can open the fiddle in show mode by adding /show at the end of the URL. When running like this you have access to the angular global. You can try it here:

http://jsfiddle.net/jaimem/Yatbt/show

jQuery Lite

If you load jQuery before AngularJS, angular.element can be passed a jQuery selector. So you could inspect the scope of a controller with

angular.element('[ng-controller=ctrl]').scope()

Of a button

 angular.element('button:eq(1)').scope()

... and so on.

You might actually want to use a global function to make it easier:

window.SC = function(selector){
    return angular.element(selector).scope();
};

Now you could do this

SC('button:eq(10)')
SC('button:eq(10)').row   // -> value of scope.row

Check here: http://jsfiddle.net/jaimem/DvRaR/1/show/

Leavetaking answered 6/12, 2012 at 12:56 Comment(12)
Thanks. When I try to install Batarang it tells me your computer is not supported , I have ubuntu, any ideas ?Eblis
@jm- as of angular.element($0).scope(), it works until you try to call some methods. I tried, and for some reason no HTTP requests are possible in this setup?Mafala
With chrome in jsfiddle you can get to the show frame with the drop-down at the bottom of the window. Normally it says <top frame> and you want to pick result( fiddle.jsshell.net/ ) to have the console in the context of the running frame.Polysyllable
@Leavetaking i tried your answer(angular.element($0).scope()) but instead getting my scope, i [object object]Maccarone
@murtaza52, Batarang works for me on Ubuntu. Maybe they've fixed the issue you were having since then. I'm using Batarang 0.4.3.Cocotte
Note that if you're disabling the debug info you'll always get undefined using this method. This is intended and can be prevented by.. .well, not disabling the debug info on the $compileProviderGide
alternative to angular.element($0).scope(): you could also do $($0).scope()Presumptuous
Word of warning - Batarang does weird things to your app, for me it was subtly breaking the app on some expressions without any visible hint for this breakage being due to Batarang.Overissue
It may be worth mentioning, that changes you make to $watched variables will not seem to effect. For that you need to also call theScope.$apply().Cymbal
I can't count how many times I have come back to this answer. Thanks Jaime, SO and GoogleBeastly
@Leavetaking should mention how to re-enable getting scope from an element when its been turned off for performance.Disapprove
Can anybody please tell me what is the syntax for angular.element('ele2').scope() in Angular 9+.Cruise
K
192

To improve on jm's answer...

// Access whole scope
angular.element(myDomElement).scope();

// Access and change variable in scope
angular.element(myDomElement).scope().myVar = 5;
angular.element(myDomElement).scope().myArray.push(newItem);

// Update page to reflect changed variables
angular.element(myDomElement).scope().$apply();

Or if you're using jQuery, this does the same thing...

$('#elementId').scope();
$('#elementId').scope().$apply();

Another easy way to access a DOM element from the console (as jm mentioned) is to click on it in the 'elements' tab, and it automatically gets stored as $0.

angular.element($0).scope();
Kaylor answered 2/4, 2013 at 4:49 Comment(2)
angular contains a subset of jquery, so you can always use the later syntax (if it is correct), i'm not sure it isTelford
I ended up with angular.element(document.body).scope(), thank you!Haarlem
C
72

If you have installed Batarang

Then you can just write:

$scope

when you have the element selected in the elements view in chrome. Ref - https://github.com/angular/angularjs-batarang#console

Conchiolin answered 6/9, 2013 at 16:36 Comment(0)
T
39

This is a way of getting at scope without Batarang, you can do:

var scope = angular.element('#selectorId').scope();

Or if you want to find your scope by controller name, do this:

var scope = angular.element('[ng-controller=myController]').scope();

After you make changes to your model, you'll need to apply the changes to the DOM by calling:

scope.$apply();
Touchandgo answered 4/6, 2014 at 17:2 Comment(7)
How does this answer have so many upvotes? You do not need jQuery for this! angular.element is already an element selection method. Stop saying you need jQuery for simple tasks like selecting an element by its id!Termless
I didn't say you need it. What i am saying is if you already have it there you could use it like this.Touchandgo
angular.element already does the thing you are using jQuery for. In fact, if jQuery is available angular.element is a alias for jQuery. You are needlessly complicating your code. angular.element('#selectorId') and angular.element('[ng-controller=myController]') do the same thing, only with less code. You might as well call angular.element('#selectorId'.toString())Termless
@Tyrsius, perhaps your feedback could be less accusatory and angry and a bit more professional?Clein
@Clein You are right, I was needlessly rude. I apologize. It is enough to say that the same thing is being done twice.Termless
Reading through @Tyrsius and @Clein conversation angular.element will be an alias for jQuery if included, if not it will be a jQLite object. If thats the case its .find() will not have the same functionality. According to the docs: find() - Limited to lookups by tag name. Thought that would be worth adding for one else who didn't realize that reading this. (Like me originally).Dwanadwane
I updated the code. I was fairly new to angular at the time and have moved away from it since. I invite you to update the code to make it more useful.Touchandgo
P
31

Somewhere in your controller (often the last line is a good place), put

console.log($scope);

If you want to see an inner/implicit scope, say inside an ng-repeat, something like this will work.

<li ng-repeat="item in items">
   ...
   <a ng-click="showScope($event)">show scope</a>
</li>

Then in your controller

function MyCtrl($scope) {
    ...
    $scope.showScope = function(e) {
        console.log(angular.element(e.srcElement).scope());
    }
}

Note that above we define the showScope() function in the parent scope, but that's okay... the child/inner/implicit scope can access that function, which then prints out the scope based on the event, and hence the scope associated with the element that fired the event.

@jm-'s suggestion also works, but I don't think it works inside a jsFiddle. I get this error on jsFiddle inside Chrome:

> angular.element($0).scope()
ReferenceError: angular is not defined

Polymerous answered 6/12, 2012 at 21:16 Comment(0)
E
10

One caveat to many of these answers: if you alias your controller your scope objects will be in an object within the returned object from scope().

For example, if your controller directive is created like so: <div ng-controller="FormController as frm"> then to access a startDate property of your controller, you would call angular.element($0).scope().frm.startDate

Epimorphosis answered 24/2, 2015 at 4:0 Comment(2)
Controller is accessible to view (hence to console) as a property of $scope, named $ctrl by default, independently of whether you rename it using controllerAs or not. I don't understand where you saw a "caveat" in existing answers. Note most of the answers here were provided back when controllerAs was not a common practice.Taliped
Right. When those answers were given, controllerAs was not common practice, so it was confusing for newbies that may have been following a "cookbook" that was telling them to alias the controller, but then not seeing the properties without using the alias. Things were moving fast two years ago.Epimorphosis
H
9

To add and enhance the other answers, in the console, enter $($0) to get the element. If it's an Angularjs application, a jQuery lite version is loaded by default.

If you are not using jQuery, you can use angular.element($0) as in:

angular.element($0).scope()

To check if you have jQuery and the version, run this command in the console:

$.fn.jquery

If you have inspected an element, the currently selected element is available via the command line API reference $0. Both Firebug and Chrome have this reference.

However, the Chrome developer tools will make available the last five elements (or heap objects) selected through the properties named $0, $1, $2, $3, $4 using these references. The most recently selected element or object can be referenced as $0, the second most recent as $1 and so on.

Here is the Command Line API reference for Firebug that lists it's references.

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

Some other things that you can use are:

  • View an elements parent scope:

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

  • You can chain this too:

$($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()

See Tips and Tricks for Debugging Unfamiliar Angularjs Code for more details and examples.

Hag answered 2/8, 2016 at 16:41 Comment(0)
F
8

I agree the best is Batarang with it's $scope after selecting an object (it's the same as angular.element($0).scope() or even shorter with jQuery: $($0).scope() (my favorite))

Also, if like me you have you main scope on the body element, a $('body').scope() works fine.

First answered 23/1, 2014 at 23:54 Comment(0)
R
7

Just assign $scope as a global variable. Problem solved.

app.controller('myCtrl', ['$scope', '$http', function($scope, $http) {
    window.$scope = $scope;
}

We actually need $scope more often in development than in production.

Mentioned already by @JasonGoemaat but adding it as a suitable answer to this question.

Roulette answered 1/11, 2016 at 16:26 Comment(0)
V
6

You can first select an element from the DOM that's within the scope you want to inspect:

enter image description here

Then you can view the scope object by querying the following in the console:

angular.element($0).scope()

You can query any property on the scope, e.g.:

angular.element($0).scope().widgets

Or you can inspect the controller attached to the scope:

angular.element($0).scope().$myControllerName

(Another option that can work is to put a breakpoint in your code. If the $scope is currently in the current 'plain old JavaScript' scope, then you can inspect the value of $scope in the console.)

Vaccine answered 30/9, 2021 at 5:33 Comment(0)
A
5

Inspect the element, then use this in the console

s = $($0).scope()
// `s` is the scope object if it exists
Amos answered 7/12, 2015 at 15:54 Comment(0)
H
4

I've used angular.element($(".ng-scope")).scope(); in the past and it works great. Only good if you have only one app scope on the page, or you can do something like:

angular.element($("div[ng-controller=controllerName]")).scope(); or angular.element(document.getElementsByClassName("ng-scope")).scope();

Havildar answered 13/12, 2016 at 21:16 Comment(0)
K
3

I usually use jQuery data() function for that:

$($0).data().$scope

The $0 is currently selected item in chrome DOM inspector. $1, $2 .. and so on are previously selected items.

Komatik answered 3/8, 2015 at 20:53 Comment(0)
A
2

Say you want to access the scope of the element like

<div ng-controller="hw"></div>

You could use the following in the console:

angular.element(document.querySelector('[ng-controller=hw]')).scope();

This will give you the scope at that element.

Activism answered 3/9, 2014 at 16:24 Comment(1)
we don't need "document.querySelector" hereOdetteodeum
G
1

At the Chrome's console :

 1. Select the **Elements** tab
 2. Select the element of your angular's scope. For instance, click on an element <ui-view>, or <div>, or etc.
 3. Type the command **angular.element($0).scope()** with following variable in the angular's scope

Example

angular.element($0).scope().a
angular.element($0).scope().b

Chrome's console enter image description here

Grinnell answered 21/6, 2018 at 15:26 Comment(0)
C
1

This requires jQuery to be installed as well, but works perfectly for a dev environment. It looks through each element to get the instances of the scopes then returns them labelled with there controller names. Its also removing any property start with a $ which is what angularjs generally uses for its configuration.

let controllers = (extensive = false) => {
  let result = {};
  $('*').each((i, e) => {
    let scope = angular.element(e).scope();
    if(Object.prototype.toString.call(scope) === '[object Object]' && e.hasAttribute('ng-controller')) {
      let slimScope = {};
      for(let key in scope) {
        if(key.indexOf('$') !== 0 && key !== 'constructor' || extensive) {
          slimScope[key] = scope[key];
        }
      }
      result[$(e).attr('ng-controller')] = slimScope;
    }
  });
  return result;
}
Creswell answered 18/6, 2019 at 22:19 Comment(0)
Y
0

in angular we get jquery element by angular.element().... lets c...

angular.element().scope();

example:

<div id=""></div>

Yemen answered 12/12, 2017 at 9:19 Comment(0)
D
0

For only debugging purposes I put this to the start of the controller.

   window.scope = $scope;

  $scope.today = new Date();

And this is how I use it.

enter image description here

then delete it when I am done debugging.

Deliberation answered 8/3, 2019 at 17:5 Comment(0)
J
0

Also, we can access the scope by name of HTML element like this: angular.element(document.getElementsByName('onboardingForm')[0]).scope()

Jacalynjacamar answered 12/10, 2022 at 3:45 Comment(0)
G
-7

Just define a JavaScript variable outside the scope and assign it to your scope in your controller:

var myScope;
...
app.controller('myController', function ($scope,log) {
     myScope = $scope;
     ...

That's it! It should work in all browsers (tested at least in Chrome and Mozilla).

It is working, and I'm using this method.

Geopolitics answered 17/6, 2015 at 8:52 Comment(3)
Using global variables is a bad practice, but I guess this is okay in most cases. It's only for debugging after all; But still you have to be careful not to use the same variable name twice.Decimate
It's a bad idea because it requires you to modify the source code. This is annoying even if it's your own code, and impossible if it's something running on another server. Even if you can modify the code, you then have to remember to undo it. So while it may work, it is not the best practice.Effeminate
@JimDavis In general I agree, but there are cases when doing this is useful: By temporarily modifying the sources you can let the code do the things you'd have to do manually again and again. So when the problem feels tricky and the debugging is gonna take long, I modify the code. Undoing the changes is trivial with the right tool (git).Khan

© 2022 - 2024 — McMap. All rights reserved.