Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularFire - Wait until user data is retrieved in controller

The user registers with username, email, and password. I authenticate using FirebaseSimpleLogin with the email, take the user id, and then load my user using the user id:

var ref = new Firebase(FIREBASE_URL + 'users'); // data containing user information
var users = $firebase(ref);

$rootScope.$on('$firebaseSimpleLogin:login', function (e, authUser) { // wait until authenticated
  var query = $firebase(ref.startAt(authUser.uid).endAt(authUser.uid)); // find user by uid
  query.$on('loaded', function () {
    setCurrentUser(query.$getIndex()[0]); // get username from query
  });
});

function setCurrentUser (username) {
  $rootScope.currentUser = User.findByUsername(username);
}

Now, my problem is that I would like to redirect to the user profile page if I am logged in in my HomeCtrl:

app.controller('HomeCtrl', function ($rootScope, $scope, $location, Auth, User) {
    // wait for current user to be set
    // if signed in
    // location.path('/user/' + currentUser.username);
});

Unfortunately, I am not sure how to wait until the setCurrentUser function is completed before I redirect. Is there a way I can have a function in my controller wait until this other function is completed?

I have a workaround, but I'm pretty sure this is not the right way to do it. Right now, I am watching for my user variable to be updated, and then calling all functions after it changes to a user, as in:

$scope.$watch(
        function() { return $rootScope.currentUser }, // watch for variable to change
        function() {
            if ($rootScope.currentUser) { // if the current user is defined, change path
                $location.path('/users/' + $rootScope.currentUser.username);
            }
        }
    )
like image 479
user3677945 Avatar asked Oct 12 '25 02:10

user3677945


1 Answers

Try resolving the route for your users. Take the plunker demo below for example.

Plunker Demo

The app is just a simple login page to a profile page. It has a HomeCtrl that navigates to a ResolveCtrl (which is the profile page) after a login.

The HomeCtrl just manages a login view. When a user is successfully logged in we navigate to the profile page. (The Auth object is a custom wrapper I made available in the Plunker).

.controller('HomeCtrl', function($scope, Auth, $window) {
  $scope.user = {
    email: '[email protected]',
    password: 'password'
  };
  $scope.login = function() {
    Auth.login('password', $scope.user);
  };
  
  Auth.onLogin(function(e, user) {
    console.log('logged in!');
    $window.location.href = '#/resolve';
  });
  
})

Now that we're logged in we'll go the ResolveCtrl. This controller resolves the current user before it has been loaded. That's the data parameter.

.controller('ResolveCtrl', function($scope, $route, data) {
  $scope.user = data;
})

But where is that parameter coming from? We can set a resolve object in our $routeProvider. This tells the ResolveCtrl it can't load until we've resolved this promise. Since the Auth.getCurrentUser() returns a promise we just need to return that and it will get resolved for us.

.config(['$routeProvider',
  function($routeProvider) {
    $routeProvider
      .when('/', {
        templateUrl: '_home.html',
        controller: 'HomeCtrl',
      })
      .when('/resolve', {
        templateUrl: '_resolve.html',
        controller: 'ResolveCtrl',
        resolve: {
          data: function(Auth) {
           // load the user before the view is loaded
           return Auth.getCurrentUser();
          }
        }
      })
      .otherwise({
        redirectTo: '/'
      });
  }
])

Now when the page gets loaded we know that the user will be there.

like image 90
David East Avatar answered Oct 14 '25 16:10

David East