![]()
In AngularJS, scope inheritance allows child controllers to inherit properties and methods from parent controllers. This behavior is useful for organizing and sharing data across different parts of an application. Understanding how scope inheritance works is crucial for avoiding unexpected behavior, especially when dealing with objects, primitives, and scope bindings.
Step 1: Understanding AngularJS Scope
Each controller in AngularJS has its own $scope object, which:
- Acts as a bridge between the controller and the view (HTML).
- Inherits from its parent controller’s scope, unless explicitly specified.
- Uses prototypal inheritance, meaning changes in parent scope reflect in child scope unless overridden.
Step 2: Basic Example of Scope Inheritance
1️⃣ Parent and Child Controllers
Let’s define a parent and a child controller in AngularJS.
HTML
<!DOCTYPE html>
<html lang="en" ng-app="app">
<head>
<meta charset="UTF-8">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.min.js"></script>
<title>Scope Inheritance</title>
</head>
<body ng-controller="ParentCtrl">
<h2>Parent Scope: {{ parentMessage }}</h2>
<div ng-controller="ChildCtrl">
<h3>Child Scope: {{ parentMessage }}</h3>
<h3>Child Message: {{ childMessage }}</h3>
</div>
<script src="app.js"></script>
</body>
</html>
JavaScript (app.js)
var app = angular.module('app', []);
app.controller('ParentCtrl', function($scope) {
$scope.parentMessage = "Hello from Parent!";
});
app.controller('ChildCtrl', function($scope) {
$scope.childMessage = "Hello from Child!";
});
How It Works?
- The
ChildCtrlinheritsparentMessagefromParentCtrlbecause of scope inheritance. - The
ChildCtrladdschildMessage, which is specific to it.
The child scope can access parent scope variables but also define its own variables.
Step 3: Overriding Parent Scope Variables in Child Controllers
If a child controller modifies a primitive variable from the parent, it creates a local copy in the child scope (shadowing the parent’s variable).
Example – Overriding Parent Scope
HTML
<body ng-controller="ParentCtrl">
<h2>Parent: {{ message }}</h2>
<div ng-controller="ChildCtrl">
<h3>Child: <input type="text" ng-model="message"></h3>
</div>
</body>
JavaScript
app.controller('ParentCtrl', function($scope) {
$scope.message = "Original Parent Message";
});
app.controller('ChildCtrl', function($scope) {
$scope.message = "Modified in Child";
});
What Happens?
- The
messagevariable inChildCtrlcreates a new local copy and does NOT modifyParentCtrl’smessage. - This is because primitives (strings, numbers, booleans) are assigned by value.
Solution: Use objects instead.
Step 4: Avoiding Shadowing with Objects
To avoid shadowing issues, use objects instead of primitives.
Example – Using Objects
HTML
<body ng-controller="ParentCtrl">
<h2>Parent: {{ data.message }}</h2>
<div ng-controller="ChildCtrl">
<h3>Child: <input type="text" ng-model="data.message"></h3>
</div>
</body>
JavaScript
app.controller('ParentCtrl', function($scope) {
$scope.data = { message: "Original Parent Message" };
});
app.controller('ChildCtrl', function($scope) {
// No local copy; modifies parent’s message directly
});
Why This Works?
- Objects are passed by reference, so
ChildCtrlmodifies the same objectdataused inParentCtrl.
Using objects ensures that both controllers share the same data reference.
Step 5: Using $scope.$parent to Access Parent Scope
If the child scope has a local variable but still needs access to the parent variable, we can use $scope.$parent.
Example – Accessing Parent Scope Explicitly
JavaScript
app.controller('ChildCtrl', function($scope) {
$scope.message = "Modified in Child";
$scope.parentMessage = $scope.$parent.message;
});
Use $scope.$parent when needed, but avoid it for better maintainability.
Step 6: Isolating Scope with scope: {} in Directives
If you define a directive and want to prevent scope inheritance, use an isolated scope.
Example – Isolated Scope in Directive
Directive
app.directive('customDirective', function() {
return {
restrict: 'E',
scope: {
message: '@'
},
template: '<p>Directive Message: {{ message }}</p>'
};
});
HTML
<custom-directive message="Hello from Parent!"></custom-directive>
Isolated scopes prevent unintentional modifications to the parent scope.
Step 7: $rootScope for Global Scope
$rootScopeis the top-level scope shared across the entire AngularJS application.- Be careful using
$rootScopebecause changes affect all controllers.
Example – Using $rootScope
JavaScript
app.run(function($rootScope) {
$rootScope.globalMessage = "Accessible everywhere!";
});
HTML
<p>{{ globalMessage }}</p> <!-- Accessible in any controller -->
Use $rootScope sparingly to avoid unexpected side effects.
Conclusion
| Concept | Behavior |
|---|---|
| Scope Inheritance | Child controllers inherit from parent controllers. |
| Primitive Shadowing | Modifying a primitive in the child creates a new local copy. |
| Using Objects | Objects are passed by reference, avoiding shadowing issues. |
| $scope.$parent | Explicitly accesses the parent’s scope. |
| Isolated Scope in Directives | Prevents accidental scope inheritance. |
| $rootScope | Accessible globally but should be used with caution. |
