2

I'm working in Angular with parent/child Controller inheritance and am encountering some behavior that I do not understand.

Basically, I set a property on an object in a parent Controller, and set it to a different value in the child Controller. I output the value that was set in the parent Controller before the code in the child Controller should run. However, I am seeing that the child Controller code has already run and set the value.

Parent.Controller.js

testapp.controller('ParentController', function($scope) {
  $scope.init = function() {
    $scope.myValue = 'Primitive value, defined in ParentController';
    $scope.myObject = {
      value: "Object property value, defined in ParentController"
    }
  } 

  $scope.init();
});

Child.Controller.js

testapp.controller('ChildController', function($scope) {
    $scope.init = function() {
    $scope.myValue = 'Primitive value, set in ChildController';
    $scope.myObject.value = "Object property value, set in ChildController";
  } 

  $scope.init();
});

HTML Template

<div ng-controller="ParentController" class="outer">
  1. Primitive value on scope: <span style="font-weight:bold">{{myValue}}</span>
  <br/>2. Object value on scope: <span style="font-weight:bold">{{myObject.value}}</span>
  <p>
    <div ng-controller="ChildController" class="inner">
      3. Primitive value on scope: <span style="font-weight:bold">{{myValue}}</span>
      <br/>4. Object value on scope: <span style="font-weight:bold">{{myObject.value}}</span>
    </div>
  <p>
  5. Primitive value on scope: <span style="font-weight:bold">{{myValue}}</span>
  <br/>6. Object value on scope: <span style="font-weight:bold">{{myObject.value}}</span>      
</div>

I would have expected #2 to show the value of the object that was defined by the Parent Controller, since the Child Controller should not yet have executed (the ng-controller directive for the ChildController is a couple lines south of this).

Here is a Plunk

If anyone could help me understand this behavior, I would really appreciate it.

Thanks,

Philip

3 Answers 3

2

It doesn't matter which controller is executed when: since the scope is inherited between the two controllers, so do the myObject variable.

Hence when the child controller updates myObject.value, it is using the same myObject than its parent controller, so you see the same value in both places in your HTML.

That is expected and often wanted. If you don't want the child controller to affect its parent, you should define a new object on that child:

testapp.controller('ChildController', function($scope) {
  $scope.init = function() {
    $scope.myValue = 'Primitive value, set in ChildController';
    $scope.myChildObject =  {value: "Object property value, set in ChildController"};
  } 
});

PS: If you add a console.log in both parent and child init functio, you will see that the parent controller is indeed read before the child one.

Sign up to request clarification or add additional context in comments.

Comments

1

When the value is changed later on, the dynamic binding also changes the first display of the variable.

Since no myObject is defined in the child scope, the one in the parent scope is changed.

Comments

1

Has nothing to do with execution order but with prototypal inheritance.

Primitives don't have inheritance but objects do.

Primitive example

var a="foo";
var b = a; //"foo"
a="some value"
alert(b) // is still "foo"

b is assigned value that a had at the time of assignment only

object example

var a={x:'foo'};
var b = a; //  {x:'foo'}
a.x="a new value";
alert(b.x) // also changed to "a new value" 

a and b are references to the same object

What you are seeing is the primitives don't bind to the parent but the object does ...as to be expected.

The childscope primitives will have values assigned from the parent based on what they are at the moment they are assigned. After that changes to either variable will be independent of the source or child

The objects are still references and changes made anywhere to any individual reference will be reflected in all references

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.