2017-05-22 2 views
0

Ich habe ein Login-Formular, mit einem Absenden-Button. Wenn auf die Schaltfläche geklickt wird, wird ein REST-fähiger Webdienst aufgerufen. Wenn die Anmeldung erfolgreich ist, werden Benutzer auf eine andere Seite weitergeleitet. Wenn dies nicht der Fall ist, sollte ein Bereich mit einer Fehlermeldung angezeigt werden.Ändern der ng-Stil-Wert in AngularJS in Controller

Ich habe versucht, ng-Stil zu verwenden, um die CSS eines Bereichs zu manipulieren, der den Fehler anzeigt.

Hier ist mein Element span:

<span id="login-error-msg" class="login-error" ng-style="errorMsg">*Wrong Username/Password</span> 

Und hier in der Steuerung habe ich eine folgende Zeile ein:

$scope.errorMsg = { "display" : "none"}; 

Und wenn ich Antwort von dem Server, der die Anmeldung nicht erfolgreich war . Ich mache das:

$scope.errorMsg = { "display": "block" }; 

Nichts ändert sich jedoch, das Span-Element bleibt verborgen. Allerdings, wenn ich erneut auf den Absenden-Button klicke. Der Stil ändert sich und die Spannweite ist sichtbar.

Wie soll ich das beheben? Es scheint mir so, als würde der Bereich gerendert, bevor der Wert von $ scope.errorMsg geändert wird.

UPDATE: Ich trted mit ng-show wie vorgeschlagen. Hier ist meine Spannweite:

<span id="login-error-msg" class="login-error" ng-show="displayError">*Wrong Username/Password</span> 

Und hier in der Steuerung I gesetzt: $scope.displayError = false;

An, schließlich, wenn ich eine Antwort vom Server erhalten. Ich mache das:

$scope.displayError = true; 

Allerdings bekomme ich immer noch das gleiche Problem. Ich sehe nur die Änderung, wenn ich die falschen Daten zweimal gebe. Eine Lösung könnte sein, die Seite neu zu laden, aber das scheint unnötig zu sein.

UPDATE 2: Hier ist meine ganze Code für den Controller:

myApp.controller('loginController', function($scope, $rootScope, $http, $location, $timeout, SERVER_PATH) { 

     $scope.displayError = false; 

    $scope.login = function(){ 

       var username = $scope.username; 
       var password = $scope.password; 

       var url = SERVER_PATH + "login/doLogin"; 

       var jsonObj = JSON.stringify({phoneNumber:username, password:password}); 

       $.blockUI({ message: '<h1><img src="images/squares.gif" /> Logging in...</h1>' }); 

       $http.post(url, jsonObj) 
       .then(function successCallback(response) { 

         console.log(JSON.stringify(response.data)); 

         var jsonResponse = JSON.parse(JSON.stringify(response.data)); 
         console.log("JSON response status: " + jsonResponse.status); 

         if (jsonResponse.status == 0) { 
         // Login success 
         setTimeout($.unblockUI, 2000); 
         $rootScope.token = jsonResponse.token; 
         console.log("Login success. Token: " + jsonResponse.token); 
         $timeout(function() { $scope.$apply(function() { $location.path("/sign"); }); }, 2000); 
       }  

       else {   
         setTimeout(function() { 
           $.unblockUI(); 
           $scope.displayError = true; 
           // $scope.errorMsg = { "display": "block" }; 
         }, 2000); 

       } 

     }, function errorCallback(response) { 
         // called asynchronously if an error occurs 
         // or server returns response with an error status. 
         console.log("An error has occured while sending the data to the server..."); 
         setTimeout($.unblockUI, 2000); 
       }); 


}; 

}) 

UPDATE 3: ich durch Änderung der setTimeout zu $ ​​timeout das Problem gelöst, wie Damoon Rashidi vorgeschlagen.

Jetzt ist mein anderes Körper sieht wie folgt aus:

$timeout(function(){ 
         $.unblockUI(); 
         $scope.displayError = true; 
        }, 2000); 
+2

Sie sollten "ngIf" verwenden, um Element zu rendern, Sie können auch 'ngShow' /' ngHide' Direktive verwenden – Satpal

+0

Stellen Sie eine [mcve] zur Verfügung, die das Problem reproduziert. Wie bereits erwähnt, gibt es dafür einfachere Möglichkeiten, aber Ihre sollte auch funktionieren. – charlietfl

+0

Überprüfen Sie meine Antwort –

Antwort

2

Es klingt wie Ihr Digest-Zyklus nicht nach dem ersten Klick ausgeführt wird. Es hängt davon ab, wie Ihr asynchroner Aufruf gehandhabt wird (winkeleigene $http Methoden lösen den Digest-Zyklus aus, nachdem sie erledigt sind).

Ohne den Kontext des Rests des Codes wird es wahrscheinlich funktionieren, wenn Sie eine $scope.$apply() hinzufügen, nachdem Ihre asynchronen Aktionen abgeschlossen sind.

EDIT: Ja, das SetTimeout ist die Sache, die es vermasselt. Angular ist nicht in der Lage, beim Timeout-Callback nach Änderungen in Ihrem Bereich zu suchen. Sie können entweder $timeout(callback, ms) verwenden oder den Anruf $scope.$apply manuell verwenden. Wenn Sie $timeout verwenden, stellen Sie sicher, dass Sie es in Ihren Controller injizieren.

+0

Keine Ahnung, warum das heruntergeregelt wurde, könnte sehr gut stimmen. hide/show wird das gleiche Problem haben, wenn es ein Problem mit der Digest-Synchronisierung gibt. –