clouchtibat
clouchtibat

Reputation: 73

AngularJS - variable has to be put as object attribute to $watch being triggered

I'm new with AngularJS and I tried this :

  <div ng-controller="ctrl1">
    <div ng-controller="ctrl2">
      <select ng-model="myvar" ng-options="c for c in vars" ></select>
      <div>{{myvar}}</div>
    </div> 
  </div>

  <script src="js/vendor/angular.min.js"></script>     
  <script type="text/javascript">

    var app = angular.module("myapp", [])
    .controller("ctrl1",function($scope, $rootScope) {
      $scope.myvar = 1;
      $scope.vars = [1, 2, 3];

      $scope.$watch("myvar", function(){
        console.log("ctrl1 myvar changed");
      });

    })
    .controller("ctrl2",function($scope, $rootScope) {
      $scope.$watch("myvar", function(){
        console.log("ctrl2 myvar changed");
      });
    })
    .run();

  </script>

When changing the select value, $watch in ctrl1 is never triggered. But if I use an object in $scope and watch its property it works :

  <div ng-controller="ctrl1">
    <div ng-controller="ctrl2">
      <select ng-model="settings.myvar" ng-options="c for c in vars" ></select>
      <div>{{settings.myvar}}</div>
    </div> 
  </div>

  <script src="js/vendor/angular.min.js"></script>     
  <script type="text/javascript">

    var app = angular.module("myapp", [])
    .controller("ctrl1",function($scope, $rootScope) {
      $scope.settings = {
        myvar : 1
      };
      $scope.vars = [1, 2, 3];

      $scope.$watch("settings.myvar", function(){
        console.log("ctrl1 myvar changed");
      });

    })
    .controller("ctrl2",function($scope, $rootScope) {
      $scope.$watch("settings.myvar", function(){
        console.log("ctrl2 myvar changed");
      });
    })
    .run();          

  </script>

Is there a reason for that? What am I doing wrong or what didn't I understand here?

Upvotes: 2

Views: 459

Answers (2)

GordyD
GordyD

Reputation: 5103

Basically you need to use an object, and not a primitive, in the parent scope and then you will be able to update in the child scope. Hence why your second implementation works and not your first.

If you use a primitive it will make a copy of it within the child scope and therefore your watch statement in your parent controller will never be triggered when a change is fired in the child controller. This jsfiddle demonstrates this behaviour - take a look.

HTML

<div ng-app="myapp">
  <div ng-controller="ctrl1">
        <select ng-model="myvar" ng-options="c for c in vars" ></select>
        <div>{{myvar}}</div>
    <div ng-controller="ctrl2">
        <select ng-model="myvar" ng-options="c for c in vars" ></select>
        <div>{{myvar}}</div>
    </div> 
  </div>
</div>

Javascript

var app = angular.module("myapp", [])
.controller("ctrl1",function($scope, $rootScope) {
  $scope.myvar = 1;
  $scope.vars = [1, 2, 3];
  console.log($scope);
  $scope.$watch("myvar", function(){
    console.log($scope.myvar);
    console.log("ctrl1 myvar changed");
  });

})
.controller("ctrl2",function($scope, $rootScope) {
    console.log($scope);
    console.log($scope.myvar);
    console.log($scope);
  $scope.$watch("myvar", function(){
    console.log($scope.myvar);
    console.log($scope.$parent.myvar);
    console.log("ctrl2 myvar changed");
  });
})
.run();

Upvotes: 2

Dayan Moreno Leon
Dayan Moreno Leon

Reputation: 5435

this works perfectly for me i would need more of the html to diagnose.

.controller('MyCtrl2', ['$scope',function($scope) {
      $scope.myvar=1;
      $scope.vars=[1,2,3];
      $scope.$watch('myvar',function(v){
          alert(v);
      })
}]);

 <select ng-options="value for value in vars" ng-model="myvar"></select>

Upvotes: 0

Related Questions