user3362334
user3362334

Reputation: 2178

Changing ng-style value in AngularJS in controller

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

Answers (1)

Damoon Rashidi
Damoon Rashidi

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

Related Questions