¿Cómo ignoro la carga inicial cuando miro los cambios del modelo en AngularJS?

Tengo una página web que sirve como editor para una sola entidad, que se ubica como un gráfico profundo en la propiedad $ scope.fieldcontainer. Después de obtener una respuesta de mi API REST (a través de $ recurso), agrego un reloj a ‘fieldcontainer’. Estoy usando este reloj para detectar si la página / entidad está “sucia”. En este momento estoy haciendo que el botón guardar salte pero realmente quiero que el botón Guardar sea invisible hasta que el usuario ensucie el modelo.

Lo que obtengo es un disparador único del reloj, que creo que está sucediendo porque la asignación .fieldcontainer = … se produce inmediatamente después de crear el reloj. Estaba pensando en usar una propiedad “dirtyCount” para absorber la falsa alarma inicial, pero eso me parece muy raro … y pensé que tenía que haber una forma “idiomática angular” para lidiar con esto, no soy el único usando un reloj para detectar un modelo sucio.

Aquí está el código donde establecí mi reloj:

$scope.fieldcontainer = Message.get({id: $scope.entityId }, function(message,headers) { $scope.$watch('fieldcontainer', function() { console.log("model is dirty."); if ($scope.visibility.saveButton) { $('#saveMessageButtonRow').effect("bounce", { times:5, direction: 'right' }, 300); } }, true); }); 

Sigo pensando que tiene que haber una manera más limpia de hacer esto que proteger mi código “UI dirtying” con un “if (dirtyCount> 0)” …

establecer una bandera justo antes de la carga inicial,

 var initializing = true 

y luego, cuando los primeros $ vigilen incendios, hagan

 $scope.$watch('fieldcontainer', function() { if (initializing) { $timeout(function() { initializing = false; }); } else { // do whatever you were going to do } }); 

La bandera se derribará justo al final del ciclo de resumen actual, por lo que el próximo cambio no se bloqueará.

La primera vez que se llama al oyente, el valor anterior y el nuevo serán idénticos. Así que haz esto:

 $scope.$watch('fieldcontainer', function(newValue, oldValue) { if (newValue !== oldValue) { // do whatever you were going to do } }); 

Esta es en realidad la forma en que los documentos angulares recomiendan manejarlo :

Después de que un observador se registra con el scope, el oyente fn se llama asincrónicamente (a través de $ evalAsync) para inicializar al observador. En casos raros, esto es indeseable porque se llama al oyente cuando el resultado de watchExpression no cambió. Para detectar este escenario dentro del oyente fn, puede comparar newVal y oldVal. Si estos dos valores son idénticos (===), se llamó al oyente debido a la inicialización

Me doy cuenta de que esta pregunta ha sido respondida, sin embargo, tengo una sugerencia:

 $scope.$watch('fieldcontainer', function (new_fieldcontainer, old_fieldcontainer) { if (typeof old_fieldcontainer === 'undefined') return; // Other code for handling changed object here. }); 

Usar banderas funciona pero tiene un poco de olor a código , ¿no crees?

Simplemente válido el estado del nuevo val:

 $scope.$watch('fieldcontainer',function(newVal) { if(angular.isDefined(newVal)){ //Do something } }); 

Durante la carga inicial de los valores actuales, el campo de valor antiguo no está definido. Entonces, el ejemplo a continuación lo ayuda a excluir las cargas iniciales.

 $scope.$watch('fieldcontainer', function(newValue, oldValue) { if (newValue && oldValue && newValue != oldValue) { // here what to do } }), true;