1

I was having success with using AngularFire in a scenario where there is one user on my application.

Now that I have authentication up and running, I'm noticing that assigning items to $scope.items is catastrophic when switching users, mainly due to the $scope failing to update correctly.

Reading directly from the docs...

var ref = new Firebase('https://<my-firebase>.firebaseio.com/items');
angularFire(ref, $scope, 'items');

I need these to be only the items of the currently authorized user. So currently, I do this (if there's a better way, don't hesitate to tell me!)

var ref = new Firebase('https://<my-firebase>.firebaseio.com/items/userId');
angularFire(ref, $scope, 'items');

I generate userId using auth.provider and auth.id, btw. Now that my items are namespaced in (let's say) user1

var ref = new Firebase('https://<my-firebase>.firebaseio.com/items/[user1id]');
angularFire(ref, $scope, 'items');

I add items to $scope.items

$scope.create = function(item) {

  $scope.items.push(item)
  /* Pretend the user adds these from the interface.
  [
    { name: 'eenie' },
    { name: 'meenie' },
    { name: 'miney' },
    { name: 'moe' }
  ]
  */

}

The problem

Now if I just log out and login as someone else, magically that user has eenie meenie miney and moe because $scope.items held the array between logout and login.

I tried to set $scope.items = [] on logout event, but that actually empties all the records. I'm pulling my hair out. This is 0.001% of what I need to do in my project and it's taking my whole weekend.

Update New method

  $scope.create = function() {
    $scope.selectedDevice = {
      name: 'New Device',
      userId: $scope.user.provider + $scope.user.id
    };
    return $scope.devices.push($scope.selectedDevice);
  };

  $scope.$on('angularFireAuth:login', function(evt, user) {
    var promise, ref;
    ref = new Firebase('https://mysite.firebaseio.com/users/' + (user.provider + user.id) + '/registry/');
    promise = angularFire(ref, $scope, 'devices');
  });

It now will accurately create items under the user's id. However, still, once you logout and log back in, those items do not get cleared from $scope.devices. Therefore, they just add themselves to data but under the newly logged in user.

Update

I did a lot of trial and error. I probably set $scope.devices to [] and moved around login events in every possible combination. What eventually worked was @hiattp's fiddle in the accepted answer.

Adam Grant
  • 12,477
  • 10
  • 58
  • 65

2 Answers2

2

This is a result of the implicit data binding remaining intact as you switch users. If the new user shows up and creates a new binding, it will consider the existing data to be local changes that it should assimilate (that's why you see the original user's items being added to the new user), but if you try to clear them first without releasing the binding then you are implicitly telling Firebase to delete that data from the original user's item list (also not what you want). So you need to release the data bindings when you detect the logout (or login) events as needed.

The callback in the angularFire promise provides an "unbind" method (see here and here):

var promise = angularFire(ref, $scope, 'items');
promise.then(function(unbind){
  // Calling unbind() will disassociate $scope.items from Firebase
  // and generally it's useful to add unbind to the $scope for future use.
});

You have a few idiosyncrasies in your code that are likely causing it not to work, and remember that unbind won't clear the local collection for you. But just so you have an idea of how it should work (and to prove it does work) here is a fiddle.

hiattp
  • 2,326
  • 1
  • 20
  • 23
  • No, that isn't really there. I'm just showing what it might look like. I'll clarify above. There would not actually be any literal definition. – Adam Grant Oct 21 '13 at 02:32
  • I tried what you have above, but I'm afraid this does not solve the problem. Items from the previously logged-in user simply add themselves to the new one. I'll post new code above. – Adam Grant Oct 21 '13 at 02:43
  • Gotcha yeah that static array threw me off. I updated the answer, that should help. – hiattp Oct 21 '13 at 04:01
  • I also tried your second link, but it also did not solve the problem. – Adam Grant Oct 21 '13 at 19:27
  • Thanks for taking the trouble to do that. It's crazy mine is not working that way. There must be something else mucking things up. I'll look again and if I find it, I'll post it here for others. – Adam Grant Oct 22 '13 at 16:50
1

You need to unbind $scope.items on logout. The best way to do this will be to save the unbind function given to your promise in $scope:

var ref = new Firebase('https://<my-firebase>.firebaseio.com/items/[user1id]');
angularFire(ref, $scope, 'items').then(function(unbind) {
  $scope.unbindItems = unbind;
});

$scope.$on('angularFireAuth:logout', function() {
  $scope.unbindItems();
});
Anant
  • 7,408
  • 1
  • 30
  • 30