1
votes

Let the image do the talking: http://www.youtube.com/watch?v=4jgdj8LBQRs [25 sec]

Plunker: http://plnkr.co/edit/pL3z77vmYeSZzGMSL0YV?p=preview

Firebase GUI: http://syncing.firebase-demo.io/

I'm using angular 1.2.6 (fairly recent) and AngularFire 0.6 (latest).

Steps to reproduce

  • I have a list of todos that is syncing with Firebase
  • I log in and local changes are propagated to Firebase
  • I log out and I disassociate binding, clearing local scope
  • I log in again: strange things happen (see video)

Critical fragments of code below (plunker has it all)

1. Controller

    $rootScope.$watch("loginState", function() {
        $scope.loginState = $rootScope.loginState;
        if ($scope.loginState == "loggedIn") {
            $scope.$firRef = $firebase(new Firebase($scope.firebaseURL + "testuser/todos/"));
            $scope.$firRef.$bind($scope, "todos").then(function(unbind) {
              $scope.unbindFunction = unbind; // I store reference to unbinding function
            });
        } else if ($scope.loginState == "loggedOut") {
            $scope.unbindFunction(); // and call it on logout
            $scope.$firRef = null // doesn't help either
            $scope.todos = [];
        }
    });

    $scope.login = function() {
        loginService.login();
    }        

    $scope.logout = function() {
        loginService.logout();
    }

(note that I store reference to unbind function and call it on logout)

2. Service

app.factory('loginService', ['$rootScope', function($rootScope) {
    return {
        login: function() {
            $rootScope.loginState = "loggedIn";
        },
        logout: function() {
            $rootScope.loginState = "loggedOut";
        }
    }
}]);

Docs about 3-way data binding: https://www.firebase.com/docs/angular/reference.html#bind-scope-model

Related:

I would be very keen to know how to properly synchronise collections between logging-in and logging-out.

You may consider calling $scope.firRef.$off() as well. I think there might be a separate bug with the unbinding code, I'll take a look. - Anant
First impressions: $scope.firRef.$off() does the trick! Wish I knew that earlier... :) - Mars Robertson
Ok, the big problem here is that you are mixing data types - objects and arrays. In 'logged out' mode, you are using an array, but the regular representation is an object. Don't do this. - Anant
After switching to only use objects, there is still a bug with AngularFire's merge algorithm (i.e. merging changes you made while being 'logged out' along with the data that's already in Firebase). I filed an issue github.com/firebase/angularFire/issues/259 to track this. - Anant
Thank you @Anant for clarification, I've added my comment to github issue so I'm in the know. Regarding use of arrays and objects how would you recommend to solve it? if ($scope.$firRef != null) { $scope.$firRef.$add($scope.newTodo); } else{ $scope.todos.push($scope.newTodo); } - Maybe $scope.arrayNotLoggedIn and $scope.$firebaseLoggedIn ? - Mars Robertson