2

I have a isolate scope directive that I am using inside ng-repeat, which is iterating over an array from the controller of that template. The template is as follows:

<!DOCTYPE html>
<html>

  <head>
    <link rel="stylesheet" href="bootstrap.min.css" />
    <script src="angular.min.js"></script>
    <script src="script1.js"></script>
  </head>

  <body ng-app="AddNewTest" ng-controller="AddNewController">
    <div class="items" ng-repeat="row in rows">
      <add-new-row data="row" index="$index"></add-new-row>
    </div>
  </body>

</html>

The directive is defined as follows:

angular.module('AddNewTest', []).
directive('addNewRow', function ($timeout) {
  return {
    controller: 'AddNewController',
    link: function (scope, element, attribute) {
      element.on('keyup', function(event){
        if(scope.index + 1 == scope.rows.length) {
          console.log('keyup happening');
          $timeout(function () {
            scope.rows.push({ value: '' });
            scope.$apply();
          });
        }
      })
    },
    restrict: 'E',
    replace: true,
    scope: {
      index: '='
    },
    template: '<div class="add-new"><input type="text" placeholder="{{index}}" ng-model="value" /></div>'
  }
}).
controller('AddNewController', function ($scope, $timeout) {
  $scope.rows = [
    { value: '' }
  ];
});

But even after adding new row and doing a $apply() the ng-repeat is not rendering the new data added. Please help.

Plnkr Link Here

jsbisht
  • 9,079
  • 7
  • 50
  • 55
  • 1
    You have **isolate scope** in directive. Pass array of `rows` in directive. Like this `scope: { index: '=', rows:"=" }`.Don't create rows in controller `AddNewController`. Remove `$scope.rows = [ { value: '' } ]`. – Stepan Kasyanenko Aug 29 '16 at 12:52
  • How do you want this to work? An input for each value? Only 1 input that is used to push into the array? What result do you expect? – gyc Aug 29 '16 at 14:19
  • @gyc I would like to add new row on keyup event in the last row. – jsbisht Aug 30 '16 at 09:41

2 Answers2

1

Pass array of rows to directive as follow:-

 scope: {
  index: '=',
  rows :'='
},

<add-new-row rows="rows"  index="$index"></add-new-row>

Working plunker

jitender
  • 10,238
  • 1
  • 18
  • 44
  • Thanks for the help. Removing the controller from directive defination helped update of ng-repeat on row update. – jsbisht Aug 30 '16 at 09:47
1

Each ng-repeat creates an isolated scope than you declare an isolated scope inside your directive that has the same controller as the div. You're swimming in the $scope soup :)

I would personnally make a clean and independent directive with its own controller.

angular.module('AddNewTest', []).
directive('addNewRow', function () {
  return {
    restrict: 'E',
    controller: MyController,
    controllerAs: '$ctrl',
    template: '{{$ctrl.rows.length}}<div class="add-new"><pre>{{$ctrl.rows | json}}</pre><input type="text" placeholder="0" ng-model="value" /></div>'
  }
}).
controller('MyController', MyController);

function MyController($scope) {
  var vm = this;
  this.rows = [ { value: '' } ];

   $scope.$watch("value",function(value){
     if(value)
      vm.rows.push({ value: value });
   });
}

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

Of course you can still bind some data to the directive using bindToController (instead of scope:{}) and if you need an ng-repeat, do it in the directive template directly.

gyc
  • 4,300
  • 5
  • 32
  • 54
  • Yeah. My bad. I use seperate controller for each directive i create. But this time i messed up trying to reuse the same as for the global template as. – jsbisht Aug 30 '16 at 12:30