2016-02-25 14 views
5

ich zwei $watches auf meinem Controller verwenden, die ein Auge auf diese beiden Objekte nehmen sollen:

$scope.gastos = { 
    name: "Gastos mensuales", 
    data: [0,0,0,0,0,0,0,0,0,0,0,0], 
    labels: ["Enero", "Febrero", "Marzo", "Abril", "Mayo", 
       "Junio", "Julio", "Agosto", "Septiembre", "Octubre", 
       "Noviembre", "Diciembre"] 
}; 

$scope.ganancias = { 
    name: "Ganancias mensuales", 
    data: [0,0,0,0,0,0,0,0,0,0,0,0], 
    labels: ["Enero", "Febrero", "Marzo", "Abril", "Mayo", 
       "Junio", "Julio", "Agosto", "Septiembre", "Octubre", 
       "Noviembre", "Diciembre"] 
}; 

Zwei Diagramme (von den Charts.js und Winkel-Charts Plugins) lese Daten von ihnen. Ich habe die Diagramme in benutzerdefinierte Anweisungen eingefügt, die die Daten von einem Attribut erhalten, und sie funktionieren ordnungsgemäß.

Das Problem ist, dass ich ein anderes Diagramm erstellen möchten, die ein anderes Objekt liest, die diese gleich ist, aber es die Daten in dieser Methode berechnet:

function calcularBeneficios(){ 
var data = []; 
for(var i=0;i<12;i++){ 
    data[i] = $scope.ganancias.data[i] - $scope.gastos.data[i]; 
} 
    console.log("FUNCTION DATA: "+data); 
return data; 
} 

Dies sind die Uhren (Ich habe versucht, sowohl die beobachtete object und die object.data Variable):

$scope.$watch("gastos", function(){ 
    $scope.beneficios.data = calcularBeneficios(); 
    console.log("SCOPE: "+$scope.beneficios.data); 
}); 

$scope.$watch("ganancias", function(){ 
    $scope.beneficios.data = calcularBeneficios(); 
    console.log("SCOPE: "+$scope.beneficios.data); 
}); 

Dies funktioniert nicht. Sie sehen alle console.logs? Ich sehe nur die "SCOPE" console.log, einmal (nicht einmal zweimal für ganancias). Wenn ich die Daten in einigen Eingaben ändere, die an diese zwei Objekte gebunden sind, funktioniert alles (die Diagramme werden in Echtzeit aktualisiert), aber das beneficios Diagramm funktioniert nicht, außerdem funktionieren diese Uhren einfach nicht.

Mache ich etwas falsch bei diesen zwei Uhren?

+0

im 'console.log ("scope")' ist '$ scope.beneficios.data' gedruckt wird aus mit seinem aktualisierten Wert? – Rhumborl

+3

Mögliches Duplikat von [$ watch wird bei Arrayänderung nicht ausgelöst] (http: // stackoverflow.com/questions/15363259/watch-nicht-ausgelöst-on-array-change) – mido

Antwort

5

Das Problem ist, dass Sie die Top-Level-gastos und ganancias Objekte beobachten. Es gibt zwei mögliche Probleme mit diesem:

  1. Als docs for $watch sagen, ist standardmäßig normale JavaScript Ungleichheit verwendet, um zu bestimmen, ob ein Objekt geändert hat (x !== y). Da das Objekt selbst das gleiche Objekt ist, ändern Sie nur die Daten innerhalb es wird immer wahr, so dass die $watch nicht ausgelöst wird.

  2. Sie können umgehen 1. indem Sie das Flag objectEquality auf true ($scope.$watch('x', function(){}, true)) setzen. Dies führt dann einen tiefen Vergleich durch und sollte Unterschiede im data Array aufnehmen. Dies ist jedoch viel leistungsintensiver.

Wie Sie gerade sind die data Array in jedem Objekt verwenden, können Sie einfach $scope.$watchCollection auf gastos.data verwenden. Das ist sauberer und schneller.

ist hier ein Arbeits Schnipsel dies demonstrieren:

angular.module("myApp", []).controller('myCtrl', function($scope) { 
 

 
    // same code 
 
    function calcularBeneficios() { 
 
    var data = []; 
 
    for (var i = 0; i < 12; i++) { 
 
     data[i] = $scope.ganancias.data[i] - $scope.gastos.data[i]; 
 
    } 
 
    console.log("FUNCTION DATA: " + data); 
 
    return data; 
 
    } 
 

 
    
 
    $scope.beneficios = { 
 
    name: "Beneficios mensuales", 
 
    data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
 
    labels: ["Enero", "Febrero", "Marzo", "Abril", "Mayo", 
 
     "Junio", "Julio", "Agosto", "Septiembre", "Octubre", 
 
     "Noviembre", "Diciembre" 
 
    ] 
 
    }; 
 
    
 
    $scope.gastos = { 
 
    name: "Gastos mensuales", 
 
    data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
 
    labels: ["Enero", "Febrero", "Marzo", "Abril", "Mayo", 
 
     "Junio", "Julio", "Agosto", "Septiembre", "Octubre", 
 
     "Noviembre", "Diciembre" 
 
    ] 
 
    }; 
 

 
    $scope.ganancias = { 
 
    name: "Ganancias mensuales", 
 
    data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
 
    labels: ["Enero", "Febrero", "Marzo", "Abril", "Mayo", 
 
     "Junio", "Julio", "Agosto", "Septiembre", "Octubre", 
 
     "Noviembre", "Diciembre" 
 
    ] 
 
    }; 
 

 
    // watch the array collection in gastos.data 
 
    $scope.$watchCollection("gastos.data", function() { 
 
    $scope.beneficios.data = calcularBeneficios(); 
 
    console.log("SCOPE: " + $scope.beneficios.data); 
 
    }); 
 

 
    // watch the array collection in ganancias.data 
 
    $scope.$watchCollection("ganancias.data", function() { 
 
    $scope.beneficios.data = calcularBeneficios(); 
 
    console.log("SCOPE: " + $scope.beneficios.data); 
 
    }); 
 
    
 
    
 
    // testing functions 
 

 
    $scope.changeGastos = function() { 
 
    $scope.gastos.data[4] = 10; 
 
    } 
 
    
 
    $scope.changeGanancias = function() { 
 
    $scope.ganancias.data[0] = 40; 
 
    } 
 
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script> 
 

 
<div ng-app="myApp" ng-controller="myCtrl"> 
 
    <h3>beneficios.data</h3> 
 
    <ul> 
 
    <li ng-repeat="i in beneficios.data track by $index">{{i}}</li> 
 
    </ul> 
 
    <button ng-click="changeGastos()">Change Gastos</button> 
 
    <button ng-click="changeGanancias()">Change Ganancias</button> 
 
</div>

3

Verwenden $watchCollection statt $watch für eine Sammlung zu sehen.

Oder Sie können auch so sehen:

$scope.$watch("gastos + ganancias", function(){ 
    $scope.beneficios.data = calcularBeneficios(); 
    console.log("SCOPE: "+$scope.beneficios.data); 
}); 
+0

Vielen Dank! Beide funktionieren, aber nur wenn ich auf gastos.data und ganancias.data ziele. Was soll ich verwenden, $ watchCollection und eine Uhr für jede von ihnen, oder diese einfache $ Uhr? – Zerok

+1

Sie sollten '$ watchCollection' stattdessen verwenden, da es weniger teuer sein sollte als die '$ watch'. http://www.bennadel.com/blog/2566-scope-watch-vs-watchcollection-in-angularjs.htm –

+0

Sie können detailliertere Verwendung von $ Watch & $ WatchCollection bei http: // stackoverflow .com/a/29189252/2405040. Es hängt jetzt von Ihrem Bedarf ab. –