Very new to angular; I'm sure I'm missing something really obvious.
I have a login form on my page. What I want to happen is to have the form hide after the user successfully logs in.
My entire page uses a single controller.
Here's the HTML; I've stripped out all but the login fields, although there is actually other content inside the same controller:
<div ng-app="Localizer" ng-controller="StoreListCtrl" ng-init="my_occasion = ''">
<div ng-show="user_signed_in===false">
<div class="row"><h1>Have an account?</h1>
<p>Sign in to quickly access addresses saved to your account</p></div>
<div class="row">
<div class="data">
<input type="username" ng-model="username" name="username" data-placeholder="Username" />
</div>
<div class="data">
<input type="password" ng-model="password" name="password" data-placeholder="Password" />
</div>
<div class="data">
<div class="syo-acctSignBtn yButtonTemplate" ng-click="login_user()">Sign In<div class="btnArrow iconPosition"></div></div>
</div>
</div>
</div>
</div>
When the user clicks the Sign In button, a function called login_user()
runs. This works; if I manually refresh the page, I do see that I'm logged in and the div that needs to be hidden is hidden. But without refreshing the page, the div remains visible, even though the variable it relies on (user_signed_in
) does get updated.
Here's the login_user
function in my controller; I've stripped out a lot of stuff, including front-end field validation:
$scope.login_user = function() {
$.post('/site/ajax/login/do_login', {'username': $scope.username, 'password': $scope.password}, function(data) {
if (data.success) {
$window.user_state.status = $window.user_status_key.STATE_SIGNED_IN;
$scope.user_signed_in = $window.user_state.status == $window.user_status_key.STATE_SIGNED_IN;
console.log("user status: " + $window.user_state.status );
console.log("user status key: " + $window.user_status_key.STATE_SIGNED_IN);
console.log("scope.user_signed_in: " + $scope.user_signed_in);
} else {
Modal({
title: "Could not Login",
text: data['errMsg'],
yellow_button: {btn_text: "OK"}
});
}
});
};
This is the result of the console.log
lines:
user status: signed in user status key: signed in scope.user_signed_in: true
Since user_signed_in
does not equal false
, I would expect all the form content shown inside the <div ng-show="user_signed_in===false">
div to hide. But it doesn't (again, unless I manually refresh the page.) What am I missing?
The problem is that you update the variable (user_logged_in
) outside of the Angular context, so Angular knows nothing about it (until you refresh the page for example).
You should wrap the body of your callback in $scope.$apply()
:
$apply() is used to execute an expression in angular from outside of the angular framework. (For example from browser DOM events, setTimeout, XHR or third party libraries). Because we are calling into the angular framework we need to perform proper scope life cycle of exception handling, executing watches.
(emphasis mine)
BTW, you wouldn't face the same problem if you performed your request using the $http
service, because it is Angular-context-aware.