tuks
tuks

Reputation: 790

AngularJS : Data binding in directive template doesn't work with ng-repeat

I created this simple plunker to demonstrate the problem:

http://plnkr.co/edit/xzgzsAy9eJCAJR7oWm74?p=preview

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

app.controller('ctrl',function($scope){
  $scope.items = {};
})

app.directive('myDirective',function(){
  return {
    restrict: 'E',
    scope: {
      item: "=item"
    },
    template: "<h2>ng-repeat: </h2>" +
    "<button ng-repeat='i in [1,2,3]' ng-click='item = true'>Set to true</button>" +
    "<h2>no ng-repeat: </h2>" + 
    "<button ng-click='item = false'>Set to false</button>"
  }
})

 

  <body ng-controller='ctrl'>
    <h1>Item: {{items.someItem}}</h1>
    <my-directive item='items.someItem'></my-directive>
  </body>

Two way data binding works when I pass a model to the directive, unless it is accessed from inside of ng-repeat. Why is this happening and how to solve this problem?

Upvotes: 1

Views: 3294

Answers (1)

sheh
sheh

Reputation: 1023

You find answer here. Briefly, ng-repeat create a new scope, a primitive data type (boolean, integer, ...) copied by value in the new scope. But objects ({}, []) copied by pointer (not value) and it be same in the new scope and parents scope.

Edited:

I solved your case plnkr

Html:

<!DOCTYPE html>
<html ng-app='app'>

  <head>
    <script data-require="angular.js@*" data-semver="1.3.0-beta.5" src="https://code.angularjs.org/1.3.0-beta.5/angular.js"></script>
    <script src="script.js"></script>
  </head>

  <body ng-controller='ctrl'>
    <h1>Item: {{items.someItem}}</h1>
    <my-directive item='items.someItem'></my-directive>
  </body>

</html>

JavaScript:

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

app.controller('ctrl', function($scope) {
  $scope.items = {};
})

app.directive('myDirective', function() {
  return {
    restrict: 'E',
    scope: {
      extItem: "=item"
    },
    template: "<h2>ng-repeat: </h2>" +
      "<button ng-repeat='i in [1,2,3]' ng-click='intItem.val = true'>Set to true</button>" +
      "<h2>no ng-repeat: </h2>" +
      "<button ng-click='intItem.val = false'>Set to false</button>",
    link: function(scope, element, attrs) {
      scope.intItem = {
        val: scope.extItem
      };
      scope.$watch('intItem.val', function(){scope.extItem = scope.intItem.val})
    }
  }
})

In this solution I'm create internal object intItem with Boolean property val, which passed into ng-repeat and added $watch for intItem.val.

Upvotes: 1

Related Questions