I'm trying to record the logged in user in an AngularJS scope, but getting an error when the page first loads up.
Clicking "Login" seems to work, but then logout bails with the same "$apply already in progress" error.
I'm expecting I've just misunderstood how $apply
works, can anybody help?
Update:
It works seamlessly if I wrap just the if (user)
part in $apply()
as follows.
var auth = new FirebaseAuthClient(ref, function(error, user) {
if (user) {
$scope.$apply(function(){ $scope.user = user; });
console.log(user);
} else if (error) {
// I can't vouch for this, haven't tested it
$scope.$apply(function(){ $scope.user = null; });
console.log(error);
} else {
$scope.user = null;
console.log("logged out");
}
});
Original code:
app.js:
var app = angular.module('app', ['firebase']);
controller.js:
app.controller('Login', ['$scope', 'angularFire',
function($scope, angularFire) {
$scope.loginstatus = 'logged out';
var ref = new Firebase("https://app.firebaseio.com/");
var auth = new FirebaseAuthClient(ref, function(error, user) {
if (user) {
$scope.$apply(function(){ $scope.loginstatus = 'logged in'; });
} else if (error) {
$scope.$apply(function(){ $scope.loginstatus = 'error'; });
alert("Login error: " + error);
} else {
$scope.$apply(function(){ $scope.loginstatus = 'logged out'; });
}
});
$scope.login = function(provider, args) {
auth.login(provider, args);
}
$scope.logout = function() {
auth.logout();
}
}]);
index.html:
<!DOCTYPE html>
<html lang="en" ng-app="app">
<head>
<meta charset="utf-8">
<title>App</title>
<script type="text/javascript" src="https://cdn.firebase.com/v0/firebase.js">
<script type="text/javascript" src='https://cdn.firebase.com/v0/firebase-auth-client.js'></script></script>
<script type="text/javascript" src="lib/angular/angular.js"></script>
<script type="text/javascript" src="lib/angularFire.js"></script>
<script type="text/javascript" src="js/app.js"></script>
<script type="text/javascript" src="js/controllers.js"></script>
</head>
<body ng-controller="Login">
<p>Login status: {{loginstatus}}</p>
<div class="container">
<h1>Login</h1>
<p>
<button ng-hide="user" ng-click="login('twitter')" class="btn btn-primary btn-large">Login</button>
<button ng-show="user" ng-click="logout()" class="btn btn-primary btn-large">Logout</button>
</p>
</div>
</body>
</html>
$apply
is only needed when you're outside of the context of Angular (like a setTimeout, setInterval, or non-Angular XHR callback).
Since FireBaseAuthClient is a tool written with Angular in mind and injected into your controller, it's likely that the callbacks are already wrapped in $scope.$apply
. You can fix your code by removing $scope.$apply
, so just:
var ref = new Firebase("https://app.firebaseio.com/");
var auth = new FirebaseAuthClient(ref, function(error, user) {
if (user) {
$scope.loginstatus = 'logged in';
} else if (error) {
$scope.loginstatus = 'error';
alert("Login error: " + error);
} else {
$scope.loginstatus = 'logged out';
}
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With