Question

Overview:

I use a watcher event $on $firebaseSimpleLogin to trigger a query and then a function to set current logged in user.

It works fine but as soon as I invoke a $bind method of $firebase, it keeps returning undefined even though the authUser.uid is correct and the same.

User service

 $rootScope.$on('$firebaseSimpleLogin:login', function (e, authUser) {
    var query = $firebase(ref.startAt(authUser.uid).endAt(authUser.uid));
    query.$on('loaded', function () {
      setCurrentUser(query.$getIndex()[0]);
    });
  });

before invoking $bind,

authUser.uid returns simpleLogin:26
query result has an object a24
query.$getIndex()[0] returns a24 <-- the name of the user

after invoking $bind,

authUser.uid returns simpleLogin:26
query result DOES NOT have an object
query.$getIndex()[0] returns undefined

Why does query return nothing after invoking $bind, when the argument passed into is the same (simpleLogin:26)?

Problem seems to only arise AFTER i change something in the remote data via the 3 way bind.

Firebase structure

firebase
|
|--users
   |
   |--a24
   |   |
   |   |--username: a24
   |   |--md5_hash: "..."
   |   |--name: alice
   |
   |--cate
   |   |
   |   |--username: a25
   |   |--md5_hash: "..."
   |   |--name: cate 

authUser object returns the same object both time:

Object {provider: "password", id: "27", uid: "simplelogin:27", email: "a24@a24.com", md5_hash: "b20aaf7e9c4d7123f788eb45ac7fd91a"…}
email: "a24@a24.com"
firebaseAuthToken: "eyJ0eXAiOiJKV1QiLCJh..."
id: "27"
isTemporaryPassword: false
md5_hash: "b20aaf7e9c4d7123f788eb45ac7fd91a"
provider: "password"
uid: "simplelogin:27"
__proto__: Object

Profile Edit Controller ($bind method call)

'use strict';

app.controller('ProfileEditCtrl',
  function($scope, $routeParams, User, $firebase, FIREBASE_URL, $location){
    $scope.user = User.findByUsername($routeParams.username );
    $scope.user.$bind($scope, 'boundUser' );
  });

Profile Edit View

  <!--Profile Pane-->
  <div class="tab-pane active" id="profile" >
    <form class="form-horizontal" action="">
      <div class="control-group"><label class="control-label" for="name">Name</label>
        <div class="controls">
          <input id="name" type="text" data-ng-model="boundUser.fullname" placeholder="Name"/>
        </div>
      </div>
      <div class="control-group"><label class="control-label" for="email">Cafe Name</label>
        <div class="controls">
          <input id="email" type="text" data-ng-model="boundUser.cafename" placeholder="Cafe Name"/>
        </div>
      </div>
      <div class="control-group">
        <div class="controls"><a href="#/users/{{currentUser.username}}">Save</a></div>
      </div>
    </form>
  </div>

Full user Service

'use strict';

app.factory('User', function ($firebase, FIREBASE_URL, $rootScope/*, Auth*/) {
  var ref = new Firebase(FIREBASE_URL + 'users');

  var users = $firebase(ref);

  var User = {
    create: function (authUser, username) {
      /* jshint camelcase: false */
      users[username] = {
        md5_hash: authUser.md5_hash,
        username: username,
        $priority: authUser.uid
      };

      users.$save(username).then(function () {
        setCurrentUser(username);
      });
    },
    findByUsername: function (username) {
      if (username) {
        return users.$child(username);
      }
    },
    getCurrent: function () {
      return $rootScope.currentUser;
    },
    signedIn: function () {
      return $rootScope.currentUser !== undefined;
    }
  };

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

  $rootScope.$on('$firebaseSimpleLogin:login', function (e, authUser) {
    var query = $firebase(ref.startAt(authUser.uid).endAt(authUser.uid));
    query.$on('loaded', function () {
      setCurrentUser(query.$getIndex()[0]);
    });
  });

  $rootScope.$on('$firebaseSimpleLogin:Logout', function () {
    delete $rootScope.currentUser;
  });

  return User;
});
Was it helpful?

Solution 2

It is indeed a bug in the earlier angularfire 0.6.0.

Problem is not longer there from angularfire 0.7.0

OTHER TIPS

Add a parameter to the function passed to the $on event. It will have your id.

query.$on('loaded', function(uid) { ... });

or reference the bound variabke: $scope.boundUser

like this:

$rootScope.$on('$firebaseSimpleLogin:login', function (e, authUser) {
var query = $firebase(ref.startAt(authUser.uid).endAt(authUser.uid));

query.$on('loaded', function (data) {
    setCurrentUser(data[0]);
  });

I can't follow the logic of why you are binding the user variable. Users don't normally change much. Additionally, you are doing it in a controller which is not a singleton. So your code will run every time the view is rendered again pointing to not requiring a bind. If the controller needs to be notified of an asynchronous change to the user then look into angular $broadcast and create your own event to listen for in the controller.

Ok. So I would take a different approach. On the login event:

 ref = <your.firebase.url>+'/users/+'authUser.uid
 var query = $firebase(ref)
 query.$on('loaded', function(userData) {
    setCurrentUser(userData);
 });

Not sure I entirely understand your problem but this will populate the data and the data will be 2-way bound. Meaning, if any data of the server changes after you have done this query then the data will change in your User object. As long as you don't copy the data and hence de-reference it. Hope that helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top