open limitto javascript object angularjs watch angularjs-scope

javascript - limitto - Angular.js solo mira en una propiedad de objeto particular



limitto angular 4 (4)

Básicamente quiero este http://plnkr.co/edit/3yfXbo1c0llO40HZ8WNP?p=preview pero el reloj no se activa cuando cambio algo ...

Sé que esto hubiera funcionado

$scope.$watch(''stuff'', function (newVal, oldVal) { console.log(oldVal, newVal); }, true);

Pero como quiero hacer un resumen dentro de los relojes y no quiero hacer un bucle innecesario o volver a sumar los valores que no cambiaron ...

// editar: tenga en cuenta que el ejemplo plnkr es solo una extracción de la aplicación real, donde puede agregar y eliminar filas y mucho más, como modificar el número total (suma de algunos y algo) de otra entrada fuera de la repetición ng. .


Bueno, si lo tengo, solo quieres sumar something con somethingelse de los objetos internos cuando cambian. Y no quieres recorrer todos los otros objetos internos si el cambio está en uno de ellos.

Bueno, tu $watch no se dispara porque no hay nada. stuff.property , y no hay patrones como stuff.*.something .

Si sabe el momento en que los objetos se empujan o se extraen de la matriz, puede aplicar $scope.$watch(object, function(){}, true) antes / después de insertar cada uno en la matriz. Si no sabe este momento, entonces necesitará $watch la matriz completa, y cuando ocurra un cambio, ejecute todas las funciones de desregistro y $watch nuevo, una por una.

De todos modos, un bucle en los navegadores de hoy en día es bastante rápido, y salvo que estés haciendo cálculos pesados ​​y tengas millones de objetos (lo que ya habría sido un problema de memoria) probablemente serás bueno con eso. Por lo tanto, un esfuerzo para $watch a todos por separado solo es necesario si tiene cálculos realmente pesados, que podrían comprender el rendimiento del sistema.


Estoy sonriendo por todas partes después de que encontré esta solución para su problema. Esta solución no solo va a ver objetos individuales, sino que tampoco va a hacer un bucle completo a través del resto de los objetos para la suma.

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

app.controller(''MainCtrl'', function($scope) { $scope.stuff = STUFF; var i; $scope.sumOfSomething = 0; $scope.sumOfSomethingElse = 0; for(i=0;i < $scope.stuff.length;i++ ){ $scope.$watch(''stuff[''+i+''].something'', function (newVal,oldVal) { // happens when the watch is registered. if(oldVal === newVal){ $scope.sumOfSomething += +newVal; return; } if(newVal){ $scope.sumOfSomething += + (newVal - oldVal); } }); $scope.$watch(''stuff[''+i+''].somethingelse'', function (newVal,oldVal) { // happens when the watch is registered. if(oldVal === newVal){ $scope.sumOfSomethingElse += +newVal; return; } if(newVal){ $scope.sumOfSomethingElse += + (newVal - oldVal); } }); } });

Por cierto, no sé qué tan óptima va a ser esta solución si tiene una gran cantidad de objetos en STUFF . Además, esto no funcionará tal como es si el número de objetos en STUFF va a cambiar. Básicamente, lo que estamos haciendo es usar el bucle de verificación sucio de angular para hacer nuestro resumen por nosotros.

Observe también el orden de newVal y oldVal en la escucha del reloj. Su orden es incorrecta.


No haría un reloj, ya que dependiendo de qué tan grande podría ser su matriz, podría ser muy agotador. En su lugar, simplemente crearía un filtro:

HTML:

Sum of something is: {{ stuff | sum:''something'' }}<br/> Sum of somethingelse is: {{ stuff | sum:''somethingelse'' }}

Javascript:

.filter("sum", function(){ return function(input, params){ var totalSum = 0; for(var x = 0; x < input.length; x++){ totalSum += input[x][params]; } return totalSum; } })

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


Ya que $watch() toma una expresión angular, puede usar una función de observador personalizada. En su caso, la forma más fácil de observar los cambios es simplemente sumar todos los campos que le interesan y luego devolver un solo número que sea agradable y eficiente para angular y su suma estará lista para renderizar.

var sumThings = function(obj, field) { var val = 0; obj.forEach(function(o) { val += parseInt(o[field]); }); return val; }; $scope.$watch(function() { return sumThings($scope.stuff, "something")}, function (newVal, oldVal) { //console.log("watchExpression(''something'') fired!", oldVal, newVal); $scope.somethingSum = newVal; }); $scope.$watch(function() { return sumThings($scope.stuff, "somethingelse")}, function (newVal, oldVal) { $scope.somethingelseSum = newVal; });

Básicamente, al hacer tu resumen estás haciendo tu propia comprobación sucia. Será más eficiente que $watch(STUFF, true) si sus objetos son más complejos de lo que se muestra aquí.

Su plnkr actualizado: http://plnkr.co/edit/d7CvERu3XGkub4l6f1yw?p=preview