web-dev-qa-db-fra.com

$ regardez ne pas tirer sur le changement de données

J'ai une configuration de montre contre le modèle d'un menu déroulant ui-select2 (à partir de ui-bootstrap). La montre se déclenche à la charge, mais pas sur les changements de données et je ne comprends pas pourquoi.

Ce n'est pas le problème habituel de ne pas appliquer le changement de modèle ni d'utiliser le troisième paramètre pour la comparaison d'égalité (du moins d'après mon code).

Que dois-je faire pour l'obtenir?

Voici un exemple montrant le problème.

57
µBio

J'ai réparé des trucs.

http://plnkr.co/edit/5Zaln7QT2gETVcGiMdoW?p=preview

Le JS

var myMod = angular.module("myApp",[]).controller("MainController",  function($scope){
  $scope.myModel = {selectedId:null};
}).controller("DetailController",function($scope){
  $scope.items = [1,2,3,4];

  $scope.watchHitCount = 0;
  $scope.$watch('myModel.selectedId', function(newVal, oldVal){
    console.log(newVal + " " + oldVal);
    $scope.watchHitCount++;
  },true);
});

L'index.html

  <body ng-app="myApp">
    <div ng-controller="MainController">
      <ng-include src="'detail.html'" ng-controller="DetailController"></ng-include>
    </div>
  </body>

Le detail.html

<pre>watch hit: {{watchHitCount}}</pre>
<pre>selected value: {{myModel.selectedId}}</pre>
<select ng-model="myModel.selectedId" ui-select2="">
  <option></option>
  <option ng-repeat="item in items" value="{{item}}">{{item}}</option>
</select>

Il se plaignait de ne pas trouver le contrôleur, donc je l'ai configuré comme je le ferais normalement avec une application nommée et un module déclaré avec des contrôleurs définis.

J'ai également ajouté un objet pour conserver la valeur dans votre modèle. Il est déconseillé d'utiliser l'objet $ scope en tant que modèle. à un objet qui est votre modèle.

35
shaunhusain

Essayez de passer true comme troisième argument à .$watch()

$rootScope.Scope documentation

$watch(watchExpression, listener, objectEquality)

objectEquality (optionnel) - {boolean =} - Compare l'objet pour l'égalité plutôt que pour la référence.

121
Casey Flynn

Il existe un correctif simple pour cela, utiliser watch avec un objet complexe au lieu d'une simple variable

Par exemple (NE PAS UTILISER)

$scope.selectedType=1;//default
$scope.$watch(
            function () {
                return $scope.selectedType;
            },
            function (newValue, oldValue) {
                if (!angular.equals(oldValue, newValue)) {
                    $scope.DoWork();
                }
            },
            true);

Mais utiliser ci-dessous

$scope.selecteditem={selectedType:1};
$scope.$watch(
            function () {
                return $scope.selecteditem.selectedType;
            },
            function (newValue, oldValue) {
                if (!angular.equals(oldValue, newValue)) {
                    $scope.DoWork();
                }
            },
            true);

notez que "slectedTypes" dans le deuxième exemple situé à l'intérieur de l'objet, pas seulement une variable de portée. cela fonctionnera même dans les anciennes Angular versions.

12
Tarek El-Mallah

Si vous utilisez l'approche controller-as, certaines lectures pourraient suggérer une syntaxe comme celle-ci:

var myController = {
    myValue: 1
};
$scope.$watch('$ctrl.myValue', function () {
    ...
}, true);

Plutôt que d’envelopper le champ dans une fonction comme celle-ci:

var myController = {
    myValue: 1
};
$scope.$watch(function () {
    return myController.myValue;
}, function () {
    ...
}, true);
6
garryp