Am new to Angular and came across this weird behavior of Custom Directive when its scope is set to true. In this condition, AngularJS will create a new scope by inheriting parent scope ( usually controller scope, otherwise the application’s rootScope ). So any changes made in Parent will be reflected to child and vice-versa. This behavior is inconsistent in this JSFiddle link
HTML :
<div ng-app="schoolApp">
<div ng-controller="schoolCtrl">
<h2 ng-click="reverseName()">{{schoolName}}, Click me to reverse school name</h2>
<h2>Student Name : {{student.firstName}} {{student.lastName}}<br>
Student Contact Num : {{student.mobileNum}}
</h2>
<div>Edit in parent :
<input type='text' ng-model='student.firstName'>
<input type='text' ng-model='student.lastName'>
</div>
<div my-directive class='directive'></div>
</div>
</div>
JS (Controller n Directive) :
var app = angular.module("schoolApp", []);
app.controller("schoolCtrl", function($scope) {
$scope.schoolName = 'Oxford Academy';
$scope.reverseName = function() {
$scope.schoolName = $scope.schoolName.split('').reverse().join('');
};
$scope.student = {
firstName: 'Chris',
lastName: 'Johnson',
mobileNum: 123456
}
});
app.directive("myDirective", function() {
return {
restrict: "EA",
scope: true,
template: "<strong>Inside Directive Scope</strong>" +
"<div>School Name is : {{schoolName}}</div>" +
"Change School name : <input type='text' ng-model='schoolName' />" +
"<br><br>" +
"<div> Student Details :</div>" +
"Student Name : {{student.firstName}} {{student.lastName}}<br>" +
"Student Contact Num : {{student.mobileNum}}" +
"<br><br>" +
"Change Student First Name : <input type='text' ng-model='student.firstName'/><br>" +
"Change Student Last Name : <input type='text' ng-model='student.lastName'/><br>" +
"Change Student Contact Number : <input type='text' ng-model='student.mobileNum'/>"
};
});
Issue Scenario : As long as am changing School Name in Controller (Parent Scope) its reflecting in Custom Directive (my-directive) but once i change School Name in Child Scope looks like there is some disconnection. Neither changes in Child Scope are reflecting in Parent nor is vice-versa working now.
But following same steps to Change Student First name or Last name in Controller (Parent Scope) will show up in Custom Directive (my-directive) and Changing Student First name or Last name in Child Scope will reflect in Parent scope. No matter how many iterations of changes you do for Student First name n Last name it works fine.
Can someone tell me what wrong am doing or is there something i need to understand that's working under the hood ?
scope : true
( Directive gets a new scope )
There is nothing that Angular is doing here but the weird behavior is because of JavaScript Prototypical inheritance. What will happen when a child is changing primitive values (string, number, boolean)
on a parent, it will end up creating a copy of the value in the child, and break the inheritance chain. That's the reason when schoolName
is changed in Directive (Child Scope) its getting a copy of its own and inheritance chain with Parent is gone for toss.But this is not the case when you change a JS Object (which is student object attached to $scope in your case), inheritance chain will remain intact no matter what.
scope : false
( Directive uses its parent scope )On other hand if you had set scope to false, your child would have always used Parent scope and there will never be a chance of breaking the inheritance chain.
Hope this helps :-)