Como posso dizer ao AngularJS para "atualizar"

168

Eu tenho um evento click que acontece fora do escopo da minha diretiva personalizada. Portanto, em vez de usar o atributo "ng-click", estou usando um ouvinte jQuery.click () e chamando uma função dentro do meu escopo da seguinte maneira:

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

close () é uma função simples que se parece com isso:

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

Na minha opinião, eu tenho um elemento com "ng-show" vinculado a isOpen assim:

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

Ao depurar, estou descobrindo que close () está sendo chamado, isOpen está sendo atualizado para false, mas a exibição do AngularJS não está sendo atualizada. Existe uma maneira de dizer manualmente ao Angular para atualizar a exibição? Ou existe uma abordagem mais "angular" para resolver esse problema que não estou vendo?

Dustin
fonte

Respostas:

315

A solução foi ligar para ...

$scope.$apply();

... no meu retorno de chamada do evento jQuery.

Dustin
fonte
9
Este link será útil, eu acho. jimhoskins.com/2012/12/17/angularjs-and-apply.html
Roman Sklyarov
6
não deveria ser $scope.$apply();?
ErichBSchulz
Você pode usar $ scope ou scope, é apenas uma diferença de notação, mas resulta na mesma.
User1226868
4
@ErichBSchulz -Muitas vezes em diretivas, vejo o escopo usado sem o $ que acredito diferenciar entre ele e o '$ scope' que é injetado nos controladores. Nos controladores, é importante referenciar por $ scope para que o Angular saiba qual dependência injetar, enquanto em uma função de link de diretiva, ele sempre passa os mesmos 4 elementos por ordinal e não exige um nome específico (scope, elemento, attrs, controller )
Cchamberlain 31/03
30

Por que $applydeveria ser chamado?

TL; DR : $applydeve ser chamado sempre que você desejar aplicar alterações feitas fora do mundo Angular.


Apenas para atualizar a resposta de @ Dustin , aqui está uma explicação do que $ apply exatamente faz e por que funciona.

$apply()é usado para executar uma expressão no AngularJS de fora da estrutura do AngularJS. (Por exemplo, nos eventos DOM do navegador, setTimeout, XHR ou bibliotecas de terceiros). Como estamos chamando a estrutura do AngularJS, precisamos executar o ciclo de vida adequado do escopo de tratamento de exceções , executando relógios .

Angular permite que qualquer valor seja usado como um destino de ligação. Em seguida, ao final de qualquer turno do código JavaScript, ele verifica se o valor foi alterado. Essa etapa que verifica se algum valor de ligação foi alterado realmente possui um método, $scope.$digest()1 . Quase nunca chamamos isso diretamente, como usamos em $scope.$apply()vez disso (que chamará $scope.$digest).

Angular monitora apenas variáveis ​​usadas em expressões e qualquer coisa dentro de uma $watchvida dentro do escopo. Portanto, se você estiver alterando o modelo fora do contexto Angular, precisará solicitar $scope.$apply()a propagação dessas alterações; caso contrário, o Angular não saberá que foram alteradas, portanto, a ligação não será atualizada 2 .

Mistalis
fonte
14

Usar

$route.reload();

lembre-se de injetar $routeno seu controlador.

test30
fonte
5
Além disso, ao usar ui-router, certifique-se de uso$state.reload()
Jeffrey Roosendaal
Isso foi super útil para nossos testes de captura de tela! Zombamos do estado, mas às vezes não necessariamente temos observadores que observam as alterações, o que pode resultar em falhas confusas ou intermitentes. Mas ser capaz de recarregar o escopo assim ajuda a combater isso.
theblang