Categorías
AngularJS Javascript

Qué son y cómo usar los watchers $watch y $watchCollection en AngularJS

1-vNhaw1SCSu_DuKwSHZSQnQ

Los watcher monitorean constantemente cambios en una variable y hacen algo en respuesta a ese cambio.

$watch() y cómo funciona

El objeto $scope tiene una función propia llamada $watch() que sirve para registrar un watcher. Para poder entender mejor todo esto, voy a escribir un trozo de código de una app que nos permite añadir videojuegos a nuestra lista de deseos y cuando tengamos dos videojuegos nos dará un aviso de que tenemos dos, pero cómo sabremos que tenemos dos y no cinco o veinte?

Ahí es donde entran al juego los watchers, podemos colocar el $watch en el contador de juegos para así cuando llegue a 2 nos salte el aviso.

<body ng-controller="codigoDiarioCtrl">
        <h3>Juegos en la tienda: </h3>
        Juegos que tengo en mi lista: {{gamesCounter}}
        <ul>
            <li ng-repeat="game in games">
                {{game}}. <a href="#" ng-click="addToGamesList(game)">Add to Games Wish List</a>
            </li>
        </ul>
</body>
angular.module('codigoDiario').controller('codigoDiarioCtrl', function($scope) {
  $scope.games = ['Metro 2033','Age of Empires 2','Warcraft III'];
  $scope.addToGamesList=function(game){
    $scope.gamesCounter++;
  };

  $scope.gamesCounter=0;
  $scope.$watch('gamesCounter',function(nuevoValor,antiguoValor){
    if(nuevoValor==2){
      alert('Muy bien! Ya tienes 2 juegos en tu lista de deseos, no te apetece comprarlos? ');
    }
  });
});

Hemos añadido un enlace a la lista de juegos en el que al pulsarlo se añadirá ese juego a nuestra lista de juegos deseados y la función addToGamesList será disparada aumentando con 1 el contador de juegos que tenemos.

Para tener un control sobre la variable contador, vamos a crear un watcher, el primer parámetro que recibe es el nombre de la variable que queremos estar monitoreando, en este caso, el contador y el segundo parámetro es una función callback con otros dos parámetros, el primero obligatorio, es el nuevo valor que acaba de recibir esa variable tras detectar un cambio, y el segundo parámetro es opcional, que es el valor antiguo de dicha variable.

$scope.$watch('gamesCounter',function(nuevoValor,antiguoValor){});

Ahora, dentro de la función callback vamos a comprobar si el nuevoValor == 2, si lo es, lanzaremos una alerta al usuario para que se entere.

if(nuevoValor==2){
      alert('Muy bien! Ya tienes 2 juegos en tu lista de deseos, no te apetece comprarlos? ');
}

El valor de retorno de la función $scope.watch() es otra función que se puede usar para «apagar» el monitoreo cuando ya no le queramos dar uso. El unbinding es bueno ya que libera memoria que podremos aprovechar más adelante para otras cosas.

var unbindWatcher = $scope.$watch('gamesCounter',function(nuevoValor,antiguoValor){
    if(nuevoValor==2){
      alert('Muy bien! Ya tienes 2 juegos, deberías de parar de comprar juegos por este mes! ');
      unbindWatcher();
    }
  });

$watchCollection y su funcionamiento

Puede haber algún en el que lo que queramos estar monitoreando no sea una una simple variable sino un conjunto de valores como un array o un objeto, para ese caso debemos usar $watchCollection(). Si tenemos fijado un array, al haber un cambio, añadir un nuevo valor al array, quitar un valor o modificar, saltará el listener en respuesta a ese cambio. Si lo que estamos usando es un objeto en vez de un array, saltará en caso de que se añada un nuevo atributo, eliminado o editado.

$scope.$watchCollection('miColeccion',function(nuevaColeccion, antiguaColeccion){
  //algo que ocurrirá al haber un cambio
  console.log(nuevaColeccion); //imprimimos en la consola el nuevo objeto 
});

Espero que con estas explicaciones os haya quedado un poco más claro como usarlos y para que sirven estos dos métodos de nuestro querido $scope.

Por Deniz M.

Desarrollador a tiempo completo, amante del buen rol y los juegos de plataforma. Mi tiempo libre me gusta invertirlo para ver series y malas peliculas