Wie kann ich AngularJS anweisen, "zu aktualisieren"?

168

Ich habe ein Klickereignis, das außerhalb des Bereichs meiner benutzerdefinierten Direktive auftritt. Anstatt das Attribut "ng-click" zu verwenden, verwende ich einen jQuery.click () -Listener und rufe eine Funktion in meinem Bereich wie folgt auf:

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

close () ist eine einfache Funktion, die folgendermaßen aussieht:

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

Meiner Ansicht nach habe ich ein Element mit "ng-show", das wie folgt an isOpen gebunden ist:

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

Beim Debuggen stelle ich fest, dass close () aufgerufen wird, isOpen auf false aktualisiert wird, die AngularJS-Ansicht jedoch nicht aktualisiert wird. Gibt es eine Möglichkeit, Angular manuell anzuweisen, die Ansicht zu aktualisieren? Oder gibt es einen "eckigeren" Ansatz zur Lösung dieses Problems, den ich nicht sehe?

Dustin
quelle

Antworten:

315

Die Lösung war anzurufen ...

$scope.$apply();

... in meinem jQuery-Ereignisrückruf.

Dustin
quelle
9
Dieser Link wird hilfreich sein, denke ich. jimhoskins.com/2012/12/17/angularjs-and-apply.html
Roman Sklyarov
6
sollte nicht so sein $scope.$apply();?
ErichBSchulz
Sie können sowohl $ scope als auch scope verwenden. Dies ist nur ein Notationsunterschied, führt jedoch zum gleichen Ergebnis.
user1226868
4
@ErichBSchulz - Oft sehe ich in Direktiven einen Bereich, der ohne das $ verwendet wird, von dem ich glaube, dass es wahrscheinlich zwischen ihm und dem '$ scope' unterscheidet, der in Controller injiziert wird. In Controllern ist es wichtig, nach $ scope zu referenzieren, damit Angular weiß, welche Abhängigkeit zu injizieren ist, während in einer Direktivenverknüpfungsfunktion immer dieselben 4 Elemente als Ordnungszahl übergeben werden und kein bestimmter Name (Gültigkeitsbereich, Element, Attribute, Controller) erforderlich ist ).
Cchamberlain
30

Warum $applysollte angerufen werden?

TL; DR : $applysollte immer dann aufgerufen werden, wenn Sie Änderungen anwenden möchten, die außerhalb der Angular-Welt vorgenommen wurden.


Um die Antwort von @ Dustin zu aktualisieren , finden Sie hier eine Erklärung, was $ apply genau bewirkt und warum es funktioniert.

$apply()wird verwendet, um einen Ausdruck in AngularJS von außerhalb des AngularJS-Frameworks auszuführen. (Zum Beispiel aus Browser-DOM-Ereignissen, setTimeout-, XHR- oder Bibliotheken von Drittanbietern). Weil wir in den AngularJS Rahmen fordern wir brauchen eigentlichen Umfang Lebenszyklus auszuführen Ausnahmebehandlung , Ausführung Uhren .

Mit Angular kann jeder Wert als Bindungsziel verwendet werden. Am Ende einer JavaScript-Code-Runde wird dann überprüft, ob sich der Wert geändert hat. Dieser Schritt, der prüft, ob sich Bindungswerte geändert haben, hat eine Methode: $scope.$digest()1 . Wir nennen es fast nie direkt, wie wir es $scope.$apply()stattdessen verwenden (was anruft $scope.$digest).

Angular überwacht nur Variablen, die in Ausdrücken verwendet werden, und alles, was sich innerhalb eines $watchBereichs innerhalb des Bereichs befindet. Wenn Sie also das Modell außerhalb des Angular-Kontexts $scope.$apply()ändern, müssen Sie die Weitergabe dieser Änderungen anfordern. Andernfalls weiß Angular nicht, dass sie geändert wurden, sodass die Bindung nicht aktualisiert wird. 2 .

Mistalis
quelle
14

Verwenden

$route.reload();

Denken Sie daran, $routein Ihren Controller zu injizieren .

test30
quelle
5
Auch wenn ui-Router verwenden, stellen Sie sicher , zu verwenden$state.reload()
Jeffrey Roosendaal
Das war super hilfreich für unsere Screenshot-Tests! Wir verspotten den Zustand, haben aber manchmal nicht unbedingt Beobachter, die die Änderungen beobachten, was zu verwirrenden Fehlern oder zeitweiligen Fehlern führen kann. Wenn Sie das Zielfernrohr jedoch so nachladen können, können Sie dem entgegenwirken.
Theblang