Understanding $scope inheritance in nested controllers

Loading

In AngularJS, $scope follows a hierarchical structure, meaning child controllers inherit properties and methods from their parent controllers. This mechanism allows data sharing but can also lead to unexpected behavior if not properly understood.


How $scope Inheritance Works

  1. Each controller has its own $scope, but it inherits from its parent.
  2. Child controllers can access parent properties, but modifications may create a new copy in the child scope.
  3. Inheritance follows JavaScript’s prototypal inheritance, meaning changes in objects (not primitives) reflect in both parent and child.

Example of $scope Inheritance

1️⃣ Basic Example

app.controller("ParentController", function($scope) {
$scope.message = "Hello from Parent!";
});

app.controller("ChildController", function($scope) {
// Child scope automatically inherits `message` from parent
});

HTML:

<div ng-controller="ParentController">
<p>Parent Message: {{ message }}</p>

<div ng-controller="ChildController">
<p>Child Message: {{ message }}</p>
</div>
</div>

Output:

Parent Message: Hello from Parent!
Child Message: Hello from Parent!

Since message is inherited, both parent and child can access it.


Issue with $scope Shadowing

When modifying primitive values (like strings, numbers) inside a child controller, it does not affect the parent scope due to scope shadowing.

2️⃣ Shadowing Issue Example

app.controller("ParentController", function($scope) {
$scope.username = "Narendra";
});

app.controller("ChildController", function($scope) {
$scope.username = "Sai Krishna"; // Creates a new local variable in the child scope
});

HTML:

<div ng-controller="ParentController">
<p>Parent Username: {{ username }}</p>

<div ng-controller="ChildController">
<p>Child Username: {{ username }}</p>
</div>
</div>

Output:

Parent Username: Narendra
Child Username: Sai Krishna

Issue:

  • Child scope creates a new property (username), which hides the parent’s username property.
  • Parent scope remains unchanged.

Solution: Use Objects for Data Binding

To avoid shadowing, always use objects instead of primitives.

3️⃣ Fixing Shadowing Using Objects

app.controller("ParentController", function($scope) {
$scope.user = { name: "Narendra" };
});

app.controller("ChildController", function($scope) {
$scope.user.name = "Sai Krishna"; // Modifies parent object
});

HTML:

<div ng-controller="ParentController">
<p>Parent Username: {{ user.name }}</p>

<div ng-controller="ChildController">
<p>Child Username: {{ user.name }}</p>
</div>
</div>

Output (Updated in Both Parent & Child):

Parent Username: Sai Krishna
Child Username: Sai Krishna

Why?

  • Objects are passed by reference, so changes reflect in both scopes.

$scope Inheritance Behavior in ng-repeat

When using ng-repeat, a new child scope is created for each iteration.

4️⃣ Example: $scope in ng-repeat

app.controller("ListController", function($scope) {
$scope.items = [{ name: "Item 1" }, { name: "Item 2" }];
});
<div ng-controller="ListController">
<ul>
<li ng-repeat="item in items">
<input type="text" ng-model="item.name">
</li>
</ul>
</div>

Each list item gets its own child scope, but updates still affect the parent’s array.


$scope and this in Controller As Syntax

Using this instead of $scope avoids scope inheritance issues.

5️⃣ Example: Using Controller As Syntax

app.controller("ParentController", function() {
this.message = "Hello from Parent!";
});
app.controller("ChildController", function() {
this.message = "Hello from Child!";
});

HTML:

<div ng-controller="ParentController as parent">
<p>Parent Message: {{ parent.message }}</p>

<div ng-controller="ChildController as child">
<p>Child Message: {{ child.message }}</p>
</div>
</div>

No scope shadowing issues because each controller manages its own instance.

Leave a Reply

Your email address will not be published. Required fields are marked *