Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inspecting AngularJS scopes using the Batarang Chrome extension

I have an question about AngularJs scopes and especially the way those can be inspected with the Batarang Chrome extension.

I have the following html:

<!doctype html>
<html lang="en" ng-app="myApp">
<head>
    <meta charset="utf-8">
    <title>My AngularJS App</title>
    <link rel="stylesheet" href="css/app.css"/>
</head>
<body>

<div ng-controller="myCtrl">

    <div enhanced-textarea ng-model="name"></div>
     <div cmp>
        <h3>{{name}}</h3>
        <div notice></div>
    </div>
</div>

<script src="lib/angular/angular.js"></script>
<script src="js/directives.js"></script>
<script src="js/controllers.js"></script>
<script src="js/app.js"></script>
</body>
</html>

Here are the directives:

'use strict';

angular.module('myApp.directives', [])
    .directive('cmp', function () {
        return {
            restrict: 'A',
            controller: 'cmpCtrl',
            replace: true,
            transclude: true,
            scope: {
                name: '='
            },
            template: '<div ng-transclude></div>'
        };
    })
    .controller('cmpCtrl', ['$scope', '$element', '$attrs' , function ($scope, $element, $attrs) {
        $scope.$parent.$watch('name', function (newVal) {
            if (newVal) {
                $scope.$parent.updatedSize = newVal.length;
            }
        }, true);
    }])
    .directive('enhancedTextarea', function () {
        return {
            restrict: 'A',
            replace: true,
            transclude: true,
            template: '<textarea ng-transclude></textarea>'
        };
    })
    .directive('notice', function () {
        return {
            restrict: 'A',
            require: '^cmp',
            replace: true,
            scope: {
                updatedSize: '='
            },
            template: '<div>{{size}}</div>',
            link: function ($scope, $element, $attrs, cmpCtrl) {
                $scope.$parent.$watch('updatedSize', function (newVal) {
                    if (newVal) {
                        $scope.size = newVal;
                    }
                }, true);
            }
        };
    });

and the controller:

'use strict';

angular.module('myApp.controllers', [])
  .controller('myCtrl', ['$scope', function($scope) {
        $scope.name = 'test';
  }]);

When I inspect the scopes using batarang, I come up with the following conclusion:

  • Scope 002: ng-app
  • Scope 003: ng-controller (myCtrl)
  • Scope 004: ????
  • Scope 005: cmpCtrl (controller for cmp directive)
  • Scope 006: inside cmp (h3 and notice)
  • Scope 007: link function of notice directive

    1. Is the above correct?
    2. Also, my biggest interrogation is what does the 004 scope correspond to?

Full app is located on github here

See also screen capture below:

screen capture

like image 673
balteo Avatar asked Mar 09 '14 14:03

balteo


2 Answers

It's not that each $scope has to correspond to an element of your page. In fact in every AngularJS app there are a bunch of $scopes which aren't directly linked to any element.

In your case it's the ng-transclude which causes a child scope to be created.

Take a look at the implementation of AngularJS which causes the creation of your 004 $scope.

if (!transcludedScope) {
    transcludedScope = scope.$new();
    transcludedScope.$$transcluded = true;
    scopeCreated = true;
}

https://github.com/angular/angular.js/blob/master/src/ng/compile.js#L959

If you like to dig deeper yourself, go and set a breakpoint right here in your AngularJS file:

enter image description here

Then just use the call stack and follow the rabbit...

like image 187
Christoph Avatar answered Oct 19 '22 21:10

Christoph


I also use this scenario to debug and inspect what is in the scope of an element, might be helpful:

  • You inspect the element with chrome dev tools
  • Once you select certain element you can get its scope by typing in console:

angular.element($0).scope()

  • You can get the controller in the same way just instead of scope() you can type controller()

  • In order to set a breakpoint in you code and look at in in chrome debugger (I sometimes find this easier than setting a breakpoint in dev tools) you can type:

debugger;

in your source and dev tool will stop there so you see the declared vars etc.

like image 43
v0d1ch Avatar answered Oct 19 '22 20:10

v0d1ch