AngularJS-Ansicht wird beim Modellwechsel nicht aktualisiert

73

Ich versuche herauszufinden, wie Angular funktioniert, und habe Probleme, meine Ansicht zu aktualisieren, wenn sich das Modell ändert.

HTML

<div ng-app="test">  
        <p ng-controller="TestCtrl">  
            {{testValue}}  
        </p>  
    </div>

JS

var app = angular.module('test', []);

    app.controller('TestCtrl', function ($scope) {
       $scope.testValue = 0;

        setInterval(function() {
            console.log($scope.testValue++);
        }, 500);
    });

http://jsfiddle.net/N2G7z/

irgendwelche Ideen?

shunryu111
quelle
4
Abgesehen von der folgenden Antwort, wenn Sie Settimeout noch verwenden möchten, müssen Sie den Bereich verwenden. $ apply ()
Ajay Beniwal
6
$ scope. $ apply () ist das, was ich brauche. Das Modell in dem Projekt, an dem ich arbeite, wird nach Benutzerinteraktion aktualisiert. Ich verwende eigentlich kein Timeout oder Intervall, aber es ist gut zu wissen, wie man sie in Zukunft mit Winkel verwendet. danke für die antworten!
Shunryu111
Hier ist ein interessanter Artikel, in dem Sie weitere Informationen über die $ Digest-Zyklen sitepoint.com/understanding-angulars-apply-digest
Mr Washington

Antworten:

121

Wie Ajay Beniwal oben erwähnt hat, müssen Sie Apply verwenden, um die Verdauung zu starten.

var app = angular.module('test', []);

app.controller('TestCtrl', function ($scope) {
   $scope.testValue = 0;

    setInterval(function() {
        console.log($scope.testValue++);
        $scope.$apply() 
    }, 500);
});
Boris Ivanov
quelle
2
Diego Vieiras Antwort ist besser. Als Faustregel gilt: Wenn immer möglich, nutzen Sie die Anbieter / Dienste von Angular, sie bewerben sich selbst.
JuanXarg
Zu der Zeit, als ich diesen Kommentar schrieb, gab es keine $ Intervalle. Es ist nur ein Wrapper für setInterval btw. Es ist auch nicht so sicher
Boris Ivanov
Das ist ein Hack, Angular hat seine eigenen Timer. $ Intervall sollte stattdessen verwendet werden, um Beobachter zu aktualisieren
Anton Savchenko
Lesen Sie meine Kommentare oben
Boris Ivanov
Diese Methode ist nicht sicher zu verwenden, da das Modell für das angegebene Intervall weiterhin aktualisiert wird ...
Vijay Sankhat
37

Verwenden Sie einfach $ interval

Hier ist Ihr Code geändert. http://plnkr.co/edit/m7psQ5rwx4w1yAwAFdyr?p=preview

var app = angular.module('test', []);

app.controller('TestCtrl', function ($scope, $interval) {
   $scope.testValue = 0;

    $interval(function() {
        $scope.testValue++;
    }, 500);
});
Diego Vieira
quelle
29

setTimoutwird außerhalb des Winkels ausgeführt. Sie müssen den $timeoutDienst verwenden, damit dies funktioniert:

var app = angular.module('test', []);

    app.controller('TestCtrl', function ($scope, $timeout) {
       $scope.testValue = 0;

        $timeout(function() {
            console.log($scope.testValue++);
        }, 500);
    });

Der Grund dafür ist, dass die bidirektionale Bindung im Winkel eine schmutzige Prüfung verwendet. Dies ist ein guter Artikel über die schmutzige Prüfung von Angular. $scope.$apply()startet einen $digestZyklus. Dies gilt für die Bindung. $timeoutbehandelt das $applyfür Sie, so dass es der empfohlene Dienst ist, wenn Sie Zeitüberschreitungen verwenden.

Im Wesentlichen erfolgt die Bindung während des $digestZyklus (wenn der Wert als unterschiedlich angesehen wird).

Davin Tryon
quelle
8

Verwenden Sie nicht $scope.$apply()eckig verwendet es bereits und es kann zu diesem Fehler führen

$ rootScope: Inprog-Aktion wird bereits ausgeführt

Wenn Sie zweimal verwenden, verwenden Sie $timeoutoder Intervall

Ana Caroline Ferreira
quelle