1

I was wondering if someone could explain the behavior of this angular test application.

In the html, I have controller 2 inside controller 1.

When I click on "click on me 1" w/o having clicked on "click on me 2", $scope.message of controller 2 receives the "clicked 1" value.

Then, I click on "click on me 2". Now if I click on "click on me 1" again, $scope.message of controller 2 will not receive the "clicked 1" value anymore.

I have a theory, but would like to hear from the experts.

Thanks.

var app = angular.module("myApp", []);
app.controller("controller1", function($scope, $http, $filter) {
  $scope.message = "clicked none";
  $scope.clicked = function() {
    $scope.message = 'clicked 1';
  };
});


angular.module("myApp").controller('controller2', function($scope) {
  vm = this;
  vm.clicked = clicked;

  function clicked() {
    $scope.message = 'clicked 2';
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
  <div ng-controller="controller1">
    <div>
      i'm in c1 {{ message}}
      <button type="button" ng-click='clicked()'>Click Me c1!</button>

      <div ng-controller="controller2 as c2">
        i'm in c2 {{ message }}
        <button type="button" ng-click='c2.clicked()'>Click Me c2!</button>
      </div>
    </div>
  </div>
quirimmo
  • 9,800
  • 3
  • 30
  • 45
user2568276
  • 89
  • 2
  • 13
  • Possible duplicate of [What are the nuances of scope prototypal / prototypical inheritance in AngularJS?](https://stackoverflow.com/questions/14049480/what-are-the-nuances-of-scope-prototypal-prototypical-inheritance-in-angularjs). – georgeawg Aug 20 '17 at 21:37
  • See also [AngularJS Developer Guide - Scope Hierarchies](https://docs.angularjs.org/guide/scope#scope-hierarchies). – georgeawg Aug 20 '17 at 21:40

2 Answers2

0

In AngularJS, inner controllers inherit from parent controller if used in the way as you did, and they inherit all the properties.

So in your sample this is what is happening:

  1. The controller2 inherits all the properties of controller1 because it is inside the controller1
  2. At the beginning none of the scopes have the message property, so it is undefined
  3. When you click on the first button, the controller1 has the property message which is inherit from the controller2 as well (so both display the message value)
  4. When you click on the second button, the controller2 overrides that property creating his property message
  5. Since here, both the controllers have a message property but the controller2 has overridden this property in his scope, so it doesn't show any more the value of the controller1's property, even if you click again on the first button

You can verify it with the following:

  1. Click at first on the second button. The controller2 has his property message
  2. The parent cannot access the properties of the children, so the message parent property is still undefined
  3. Click on the first button and you will see that the first value has been assigned to the controller1 too, but without changing the one of the controller2
halfer
  • 19,824
  • 17
  • 99
  • 186
quirimmo
  • 9,800
  • 3
  • 30
  • 45
0

It's desired behavior as once you make change in scope variable inside child controller, it'll be created in (its own) separate scope which parent can't access. But child still able to access parent's scope. So value was not changing afterwards you click button in second controller. Having a '.' in your models will ensure that prototypal inheritance is in play. So that it'll not create its own property version. Check out Understanding scope for details about how scope, inheritance works in angularjs.

And check this plunker example to solve your issue by using '.' in models

Shantanu
  • 3,483
  • 2
  • 17
  • 20