web-dev-qa-db-fra.com

Comment surveiller les changements sur les modèles créés par ng-repeat?

Considérons ce Plnkr par exemple. Je ne sais pas combien de membres de fooCollection seront créés auparavant. Donc, je ne sais pas combien de modèles bar vont exister.

Mais je sais qu'ils vont être des modèles angulaires et je sais où ils vont être.

Comment puis-je faire un $watch sur ceux-ci?

Je dois le faire car je dois déclencher le comportement lorsqu'un modèle bar est modifié. Regarder le fooCollection lui-même ne suffit pas, l'écouteur $watch ne se déclenche pas lorsqu'un bar est modifié.

Html pertinent:

<body ng-controller="testCtrl">
  <div ng-repeat="(fooKey, foo) in fooCollection">
    Tell me your name: <input ng-model="foo.bar">
    <br />
    Hello, my name is {{ foo.bar }}
  </div>
  <button ng-click="fooCollection.Push([])">Add a Namer</button>
</body>

JS pertinent:

angular
.module('testApp', [])
.controller('testCtrl', function ($scope) {
  $scope.fooCollection = [];

  $scope.$watch('fooCollection', function (oldValue, newValue) {
    if (newValue != oldValue)
      console.log(oldValue, newValue);
  });
});
41
Aditya M P

Créer des contrôleurs d’éléments de liste individuels: démo sur Plnkr

js

angular
  .module('testApp', [])
  .controller('testCtrl', function ($scope) {
    $scope.fooCollection = [];
  })
  .controller('fooCtrl', function ($scope) {
    $scope.$watch('foo.bar', function (newValue, oldValue) {
      console.log('watch fired, new value: ' + newValue);
    });
  });

HTML

<html ng-app="testApp">
  <body ng-controller="testCtrl">
    <div ng-repeat="(fooKey, foo) in fooCollection" ng-controller="fooCtrl">
      Tell me your name: <input ng-model="foo.bar" ng-change="doSomething()">
      <br />
      Hello, my name is {{ foo.bar }}
    </div>
    <button ng-click="fooCollection.Push([])">Add a Namer</button>
  </body>
</html>
34
kapv89

Si votre collection est remplie, vous pouvez placer une montre sur chaque élément du ng-repeat:

html

<div ng-repeat="item in items">
   {{ item.itemField }}
</div>

js

for (var i = 0; i < $scope.items.length; i++) {
   $scope.$watch('items[' + i + ']', function (newValue, oldValue) {
      console.log(newValue.itemField + ":::" + oldValue.itemField);
   }, true);
}
9
Marcel

Vous pouvez passer true en tant que troisième argument dans $ watch

$scope.$watch('something', function() { doSomething(); }, true);

https://docs.angularjs.org/api/ng/type/$rootScope.Scope

5
v-tec

Vous pouvez également créer une directive personnalisée qui informera votre contrôleur principal des modifications.

YourModule.directive("batchWatch",[function(){
return {
    scope:"=",
    replace:false,
    link:function($scope,$element,$attrs,Controller){
        $scope.$watch('h',function(newVal,oldVal){
            if(newVal !== oldVal){
              Controller.updateChange(newVal,oldVal,$scope.$parent.$index);
            }

        },true);

    },
    controller:"yourController"
};
}]);

suppose que votre balisage est comme ça

<ul>
  <li ng-repeat="h in complicatedArrayOfObjects">
      <input type="text" ng-model="someModel" batch-watch="$index" />
  </li>
</ul>

et ceci est votre contrôleur

YourModule.controller("yourController",[$scope,function($scope){
    this.updateChange = function(newVal,oldVal,indexChanged){
      console.log("Details about the change");
    }
}]);

Vous pouvez également jouer autour de la valeur fournie par la fonction link de la directive qui repose sur les 3 premiers arguments, scope, element et attr.

3
Jomaf

Comme je ne voulais pas d'un autre contrôleur, j'ai fini par utiliser ng-change .

Simple jsFiddle: https://jsfiddle.net/maistho/z0xazw5n/

HTML pertinent:

<body ng-app="testApp" ng-controller="testCtrl">
    <div ng-repeat="foo in fooCollection">Tell me your name:
        <input ng-model="foo.bar" ng-change="fooChanged(foo)">
        <br />Hello, my name is {{foo.bar}}</div>
    <button ng-click="fooCollection.Push({})">Add a Namer</button>
</body>

JS pertinent:

angular.module('testApp', [])
    .controller('testCtrl', function ($scope) {
    $scope.fooCollection = [];

    $scope.fooChanged = function (foo) {
        console.log('foo.bar changed, new value of foo.bar is: ', foo.bar);
    };
});
2
Maistho

Essayez de faire ça

 <div ng-repeat="foo in fooCollection" ng-click="select(foo)">Tell me your ame:
        <input ng-model="foo.bar" ng-change="fooChanged(foo)">
        <br />Hello, my name is {{foo.bar}}</div>
        <button ng-click="fooCollection.Push({})">Add a Namer</button>
 </div>

Il y a le code dans la directive/contrôleur

 $scope.selectedfoo = {};
 $scope.select = (foo) => {
    $scope.selectedfoo = foo;
 }

 $scope.$watch('selectedfoo ', (newVal, oldVal) => {
  if (newVal) {

  }
 },true)
0
user2156275