Isolated scope binding doesn't work when updated inside a $scope.$watch

Why does the below code not work? I'm trying to get pass x to the directive, then updated the value of x based on ywhich is internal to the directive.

var app = angular.module('app',[]);

app.controller('Ctrl', ['$scope', function($scope){
  $scope.x=[];
}]);

app.controller('dirCtrl', ['$scope', function($scope){
  $scope.y=[];
  
  $scope.click=function(){
    $scope.y.push({});
  }
  
  $scope.$watch('y', function(){
    $scope.x=$scope.y;
    console.log("$scope.x updated in $watch call");
  },true);
}]);
                           
app.directive('directive', [function(){
    return {
        restrict: 'E',
        scope: {
            x: '=',
        },
        template: '<div ng-controller="dirCtrl"><button ng-click="click()">clicky</button>y:{{y}}</div>'
    };
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
  <div ng-controller="Ctrl">
    <directive x='x'></directive>
    x:{{x}}
  </div>
</div>

Upvotes: 0

Views: 452

Answers (2)

Andr&#233; Werlang
Andr&#233; Werlang

Reputation: 5944

$scope.$watch() doesn't do a deep watch. The y reference per se never change, just its contents. Use $scope.$watchCollection() instead.

UPDATE:

When you use a binding without a dot notation, it ends up creating a new slot inside the $scope. The trick is to use something like obj.x.

See the changes needed:

var app = angular.module('app',[]);

app.controller('Ctrl', ['$scope', function($scope){
  $scope.obj = {
    x: []
  };
}]);

app.controller('dirCtrl', ['$scope', function($scope){
  $scope.y=[];
  
  $scope.click=function(){
    $scope.y.push({});
  };

  $scope.$watch('y', function(){
    $scope.obj.x = $scope.y;
    console.log("$scope.obj.x updated in $watch call");
  },true);
}]);

app.directive('directive', [function(){
    return {
        restrict: 'E',
        scope: {
            obj: '=',
        },
        template: '<div ng-controller="dirCtrl"><button ng-click="click()">clicky</button>y:{{y}}</div>'
    };
}]);
<!DOCTYPE html>
<html>

  <head>
    <link rel="stylesheet" href="style.css">
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
    <script src="script.js"></script>
  </head>

  <body>
<div ng-app="app">
  <div ng-controller="Ctrl">
    <directive obj='obj'></directive>
    x: {{obj.x}}
  </div>
</div>
  </body>

</html>

Upvotes: 2

Viktor
Viktor

Reputation: 257

You're sending in a Number which is not an object and therefor not bound by reference. Put it as a property of an object instead and pass that into the directive:

$scope.obj = {
    x: 5
};

Upvotes: 0

Related Questions