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 007: link function of notice directive
Full app is located on github here
See also screen capture below:
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:
Then just use the call stack and follow the rabbit...
I also use this scenario to debug and inspect what is in the scope of an element, might be helpful:
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With