0

I'm writing my first angularjs app, and it's beginning to make sense. However, I have a sign up form that isn't getting the messages in some cases to alert users to problems. I'm using Firebase to authenticate, which works fine. But I'm storing users by a unique username as the key. So before I run the $createUser function, I do a quick query to see if there's already a user object with this key-- if not, I create the user.

The problem is when there is an existing user with this username. The console log value prints fine, but the error message (bound to $scope.authMsg) doesn't show up the first time-- but if I click the "register" button again, then the message shows up in the expected message div.

Any hints on the message issue (or suggestions for this code) would be appreciated!

$scope.register = function() {
    $scope.authMsg = '';
    var ref = new Firebase(FIREBASE_URL);
    $scope.authObj = $firebaseAuth(ref);

    // check if the username is taken
    ref.child("/users/"+$scope.account.username).on("value", function(snapshot) {
        if (snapshot.val()) {
            //
            // PROBLEM HERE!!
            //
            $scope.authMsg = 'Username exists-- did you forget your password?'; // doesn't show on page until second submit
            console.log('Username exists-- did you forget your password?'); // prints to console as expected
        } else {
            $scope.authObj.$createUser({ email: $scope.account.email, password: $scope.account.password })
            .then(function(userData) {
                console.dir(userData);
                return $scope.authObj.$authWithPassword({
                    email: $scope.account.email,
                    password: $scope.account.password
                });
            }).then(function(authData) {
                // we created a user and are now logged in-- store user info
                var userdata = {};
                userdata[$scope.account.username] = {
                                uid: authData.uid,
                                first_name: $scope.account.first_name,
                                last_name: $scope.account.last_name,
                                email: $scope.account.email,
                                full_name: $scope.account.first_name+' '+$scope.account.last_name
                            };
                var usersRef = ref.child("users");
                // save the userdata
                usersRef.set(userdata);
                console.log("Logged in as:", authData.uid);
                $state.go('app.dashboard');
            }).catch(function(error) {
                $scope.authMsg = error;
                console.error("Error: ", error);
            });
        }
    }, function (errorObject) {
        $scope.authMsg = 'The read failed: ' + errorObject.code;
        console.log('The read failed: ' + errorObject.code);
    });
};
user101289
  • 9,888
  • 15
  • 81
  • 148
  • Why are we using ref.on() and AngularFire together here? You could avoid most of these problems by taking advantage of AngularFire, which handles digest scopes and crazy Angular background stuff. Also, you probably want once(), since on() will be triggered each time the data changes. [The guide](https://www.firebase.com/docs/web/guide/) is your friend. – Kato Jan 12 '15 at 18:36

1 Answers1

2

I'm assuming, the Firebase callback does not involve an angular digest cycle.

To handle this, write

if (snapshot.val()) {
    $scope.$apply(function() {
        $scope.authMsg = 'Username exists— did you forget your password?';
    });

A useful reading about the topic: http://jimhoskins.com/2012/12/17/angularjs-and-apply.html

David Frank
  • 5,918
  • 8
  • 28
  • 43