Cómo mirar en profundidad una matriz en angularjs?

Hay una variedad de objetos en mi scope, quiero ver todos los valores de cada objeto.

Este es mi código:

function TodoCtrl($scope) { $scope.columns = [ { field:'title', displayName: 'TITLE'}, { field: 'content', displayName: 'CONTENT' } ]; $scope.$watch('columns', function(newVal) { alert('columns changed'); }); } 

Pero cuando TITLE2 los valores, por ejemplo, cambio TITLE a TITLE2 , la alert('columns changed') nunca apareció.

¿Cómo observar profundamente los objetos dentro de una matriz?

Hay una demostración en vivo: http://jsfiddle.net/SYx9b/

Puede establecer el tercer argumento de $watch en true :

 $scope.$watch('data', function (newVal, oldVal) { /*...*/ }, true); 

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

Desde Angular 1.1.x también puede usar $ watchCollection para mirar el reloj superficial (solo el “primer nivel” de) la colección.

 $scope.$watchCollection('data', function (newVal, oldVal) { /*...*/ }); 

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

Hay consecuencias de rendimiento en el buceo profundo de un objeto en tu $ watch. Algunas veces (por ejemplo, cuando los cambios solo son push y pops), es posible que desee $ ver un valor calculado fácilmente, como array.length.

Si va a ver solo una matriz, simplemente puede usar este código:

 $scope.$watch('columns', function() { // some value in the array has changed }, true); // watching properties 

ejemplo

Pero esto no funcionará con múltiples matrices:

 $scope.$watch('columns + ANOTHER_ARRAY', function() { // will never be called when things change in columns or ANOTHER_ARRAY }, true); 

ejemplo

Para manejar esta situación, generalmente convierto las múltiples matrices que quiero ver en JSON:

 $scope.$watch(function() { return angular.toJson([$scope.columns, $scope.ANOTHER_ARRAY, ... ]); }, function() { // some value in some array has changed } 

ejemplo

Como @jssebastian señaló en los comentarios, JSON.stringify puede ser preferible a angular.toJson ya que puede manejar miembros que comienzan con ‘$’ y otros casos posibles también.

Vale la pena señalar que en Angular 1.1.xy superior, ahora puede usar $ watchCollection en lugar de $ watch. Aunque $ watchCollection parece crear relojes poco profundos, por lo que no funcionará con matrices de objetos como usted espera. Puede detectar adiciones y eliminaciones en la matriz, pero no las propiedades de los objetos dentro de las matrices.

$ watchCollection logra lo que quieres hacer. A continuación se muestra un ejemplo copiado del sitio web angularjs http://docs.angularjs.org/api/ng/type/$rootScope.Scope Si bien es conveniente, se debe tener en cuenta el rendimiento, especialmente cuando se mira una gran colección.

  $scope.names = ['igor', 'matias', 'misko', 'james']; $scope.dataCount = 4; $scope.$watchCollection('names', function(newNames, oldNames) { $scope.dataCount = newNames.length; }); expect($scope.dataCount).toEqual(4); $scope.$digest(); //still at 4 ... no changes expect($scope.dataCount).toEqual(4); $scope.names.pop(); $scope.$digest(); //now there's been a change expect($scope.dataCount).toEqual(3); 

Aquí hay una comparación de las 3 formas en que puede ver una variable de ámbito con ejemplos:

$ watch () se desencadena por:

 $scope.myArray = []; $scope.myArray = null; $scope.myArray = someOtherArray; 

$ watchCollection () se desencadena por todo lo anterior Y:

 $scope.myArray.push({}); // add element $scope.myArray.splice(0, 1); // remove element $scope.myArray[0] = {}; // assign index to different value 

$ watch (…, true) se desencadena por TODO lo anterior Y:

 $scope.myArray[0].someProperty = "someValue"; 

SOLO UNA COSA MÁS…

$ watch () es el único que se activa cuando una matriz se reemplaza con otra matriz, incluso si esa otra matriz tiene el mismo contenido exacto.

Por ejemplo, donde $watch() se $watchCollection() y $watchCollection() no:

 $scope.myArray = ["Apples", "Bananas", "Orange" ]; var newArray = []; newArray.push("Apples"); newArray.push("Bananas"); newArray.push("Orange"); $scope.myArray = newArray; 

A continuación se muestra un enlace a un JSFiddle de ejemplo que usa todas las diferentes combinaciones de reloj y muestra los mensajes de registro para indicar qué “relojes” se activaron:

http://jsfiddle.net/luisperezphd/2zj9k872/

Esta solución funcionó muy bien para mí, estoy haciendo esto en una directiva:

scope. $ watch (attrs.testWatch, function () {…..}, true);

el verdadero funciona bastante bien y reactjs para todos los chnages (agregar, eliminar o modificar un campo).

Aquí hay un plunker que funciona para jugar con él.

Profundamente viendo una matriz en AngularJS

Espero que esto te sea útil. Si tiene alguna pregunta, no dude en preguntar, intentaré ayudar 🙂

En mi caso, necesitaba ver un servicio, que contiene un objeto de dirección también visto por varios otros controladores. Estaba atrapado en un ciclo hasta que agregué el parámetro ‘verdadero’, que parece ser la clave del éxito cuando miro objetos.

 $scope.$watch(function() { return LocationService.getAddress(); }, function(address) { //handle address object }, true); 

Establecer el parámetro objectEquality (tercer parámetro) de la función $watch es definitivamente la forma correcta de ver TODAS las propiedades de la matriz.

 $scope.$watch('columns', function(newVal) { alert('columns changed'); },true); // <- Right here 

Piran responde esto lo suficientemente bien y menciona $watchCollection también.

Mas detalle

La razón por la que respondo una pregunta ya respondida es porque quiero señalar que la respuesta de wizardwerdna no es buena y no debe usarse.

El problema es que los resúmenes no ocurren de inmediato. Deben esperar hasta que el bloque de código actual se haya completado antes de la ejecución. Por lo tanto, observar la length de una matriz puede pasar por alto algunos cambios importantes que $watchCollection .

Asume esta configuración:

 $scope.testArray = [ {val:1}, {val:2} ]; $scope.$watch('testArray.length', function(newLength, oldLength) { console.log('length changed: ', oldLength, ' -> ', newLength); }); $scope.$watchCollection('testArray', function(newArray) { console.log('testArray changed'); }); 

A primera vista, puede parecer que estas dispararían al mismo tiempo, como en este caso:

 function pushToArray() { $scope.testArray.push({val:3}); } pushToArray(); // Console output // length changed: 2 -> 3 // testArray changed 

Eso funciona bastante bien, pero considera esto:

 function spliceArray() { // Starting at index 1, remove 1 item, then push {val: 3}. $testArray.splice(1, 1, {val: 3}); } spliceArray(); // Console output // testArray changed 

Tenga en cuenta que la longitud resultante es la misma aunque la matriz tenga un nuevo elemento y haya perdido un elemento, por lo que, al mirar como $watch , la length no ha cambiado. $watchCollection recogió en él, sin embargo.

 function pushPopArray() { $testArray.push({val: 3}); $testArray.pop(); } pushPopArray(); // Console output // testArray change 

El mismo resultado ocurre con un empuje y pop en el mismo bloque.

Conclusión

Para ver cada propiedad en la matriz, use $watch en la matriz con el tercer parámetro (objectEquality) incluido y configurado en verdadero. Sí, esto es caro, pero a veces es necesario.

Para ver cuándo el objeto ingresa / sale de la matriz, use $watchCollection .

NO use $watch en la propiedad de length de la matriz. Casi no hay una buena razón por la que pueda pensar para hacerlo.

 $scope.changePass = function(data){ if(data.txtNewConfirmPassword !== data.txtNewPassword){ $scope.confirmStatus = true; }else{ $scope.confirmStatus = false; } }; 
  
รหัสผ่านต้องมีจำนวน 5 หลัก
รหัสผ่านใหม่ไม่ตรงกัน