Reputation: 2178
I have a login form, with a submit button. When the button is clicked, a RESTful web service is called. If login is successful it redirects users to another page. If it's not, then a span with an error message should be displayed.
I tried to use ng-style to manipulate the css of a span that displays the error.
Here is my span element:
<span id="login-error-msg" class="login-error" ng-style="errorMsg">*Wrong Username/Password</span>
And here in the controller I have a following line:
$scope.errorMsg = { "display" : "none"};
And if I get response from the server that the login wasn't successful. I do this:
$scope.errorMsg = { "display": "block" };
However, nothing changes, the span element remains hidden. However, when I click on the submit button again. The style changes and thespan is visible.
How should I fix this? It seems to me like the span is rendered before the value of $scope.errorMsg is changed.
UPDATE: I tred using ng-show as suggested. Here is my span:
<span id="login-error-msg" class="login-error" ng-show="displayError">*Wrong Username/Password</span>
And, here in the controller I set: $scope.displayError = false;
An, finally when I get a response from the server. I do this:
$scope.displayError = true;
However, I still get the same problem. I only see the change if I enter the wrong data twice. One solution might be to reload the page, but that seems unneccesary.
UPDATE 2: Here is my whole code for the 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: I solved the issue by changing the setTimeout to $timeout as Damoon Rashidi suggested.
Now my else body looks like this:
$timeout(function(){
$.unblockUI();
$scope.displayError = true;
}, 2000);
Upvotes: 1
Views: 600
Reputation: 46
It sounds like your digest-cycle isn't running after the first click. It depends on how your async call is handled (angular's own $http
methods trigger the digest cycle after they are done).
Without the context of the rest of the code it will probably work if you add a $scope.$apply()
after your async actions are done.
EDIT: Yeah the setTimeout is the thing that's messing it up. Angular doesn't understand to check for changes in your scope in the timeout callback. You can either use $timeout(callback, ms)
or use call $scope.$apply
manually. If you use $timeout
make sure inject it into your controller.
Upvotes: 2