1

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?

1 Answer 1

1

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.

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

2 Comments

Thanks for the reply. I figured that out, but is there a way to pass the object directly? Currently, for my directive, I don't always want to set someItem. I want to be able to pass it to the directive. So, my solution for now is to use attributes like this: <my-directive items='items' item='someItem'> , and then in directive ng-click="items[item] = true", but I think that's just wrong.
@tuks I'm changed my answer

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.