¿Cómo puedo decirle a AngularJS que "actualice"

168

Tengo un evento click que ocurre fuera del alcance de mi directiva personalizada, así que en lugar de usar el atributo "ng-click", estoy usando un oyente jQuery.click () y llamo a una función dentro de mi alcance de la siguiente manera:

$('html').click(function(e) {
  scope.close();
);

close () es una función simple que se ve así:

scope.close = function() {
  scope.isOpen = false;
}

En mi opinión, tengo un elemento con "ng-show" vinculado a isOpen como este:

<div ng-show="isOpen">My Div</div>

Al depurar, encuentro que se llama a close (), isOpen se actualiza a falso, pero la vista AngularJS no se actualiza. ¿Hay alguna forma de decirle a Angular manualmente que actualice la vista? ¿O hay un enfoque más "angular" para resolver este problema que no estoy viendo?

Dustin
fuente

Respuestas:

315

La solución fue llamar ...

$scope.$apply();

... en mi devolución de llamada de evento jQuery.

Dustin
fuente
9
Este enlace será útil, creo. jimhoskins.com/2012/12/17/angularjs-and-apply.html
Roman Sklyarov
66
no debería ser eso $scope.$apply();?
ErichBSchulz
Puede usar tanto $ scope como scope, es solo una diferencia de notación pero resulta igual.
usuario1226868
44
@ErichBSchulz -A menudo en las directivas, veo el alcance utilizado sin el $ que creo que es probable que diferencie entre él y el '$ alcance' que se inyecta en los controladores. En los controladores, es importante hacer referencia por $ scope para que Angular sepa qué dependencia inyectar, mientras que en una función de enlace directivo, siempre pasa los mismos 4 elementos por ordinal y no requiere un nombre específico (ámbito, elemento, atributos, controlador )
cchamberlain
30

¿Por qué $applydebería llamarse?

TL; DR : $applydebe llamarse siempre que desee aplicar cambios realizados fuera del mundo angular.


Solo para actualizar la respuesta de @ Dustin , aquí hay una explicación de lo que $ apply hace exactamente y por qué funciona.

$apply()se usa para ejecutar una expresión en AngularJS desde fuera del marco de AngularJS. (Por ejemplo, desde eventos DOM del navegador, setTimeout, XHR o bibliotecas de terceros). Debido a que estamos llamando al marco AngularJS, necesitamos realizar un ciclo de vida de alcance adecuado para el manejo de excepciones , la ejecución de relojes .

Angular permite que cualquier valor se use como un objetivo vinculante. Luego, al final de cualquier turno de código JavaScript, verifica si el valor ha cambiado. Ese paso que verifica si algún valor de enlace ha cambiado realmente tiene un método, $scope.$digest()1 . Casi nunca lo llamamos directamente, ya que usamos $scope.$apply()en su lugar (que llamará $scope.$digest).

Angular solo monitorea las variables utilizadas en expresiones y cualquier cosa dentro de una $watchvida dentro del alcance. Por lo tanto, si está cambiando el modelo fuera del contexto angular, deberá $scope.$apply()solicitar la propagación de dichos cambios; de lo contrario, Angular no sabrá que se han modificado, por lo que el enlace no se actualizará 2 .

Mistalis
fuente
14

Utilizar

$route.reload();

recuerde inyectar $routea su controlador.

test30
fuente
55
Además, cuando use el enrutador ui, asegúrese de usar$state.reload()
Jeffrey Roosendaal
¡Esto fue muy útil para nuestras pruebas de captura de pantalla! Nos burlamos del estado, pero a veces no necesariamente tenemos observadores que observan los cambios, lo que puede resultar en fallas confusas o fallas intermitentes. Pero poder recargar el alcance de esta manera ayuda a combatir eso.
theblang