Steven Franklin
Steven Franklin

Reputation: 655

AngularFire 0.8 bindTo only works for first change

Hi I've been trying to create an app using the new angularfire version 0.8, which features an update version of $bind, $bindTo. However im having a little difficulty with it. The bind to method only appears to propagate changes back to firebase on the first update. Subsequent changes to the data on the page do not. Do I need to rebind the object on every update?

I've created a simple app to show the issue. The app has an object created in a factory (Test) which adds an object to the $rootScope. The controller then accesses this, and a view accesses it and updates as required.

Factory (services/test.js)

app.factory('Test',function($firebase, FIREBASE_URL, $rootScope) {
    var URL = FIREBASE_URL + 'test12/';
    var Test = {
        create: function (user,obj) {
            console.log("Creating new test object");
            obj.something = "1234";
            obj.somethingElse = "567";
            obj.$priority="7";
            obj.$save();
            setCurrentTest(user);
        },
        getCurrent: function() {
            return $rootScope.currentTest;
        }
    };

    function setCurrentTest(user) {
        var obj = $firebase(new Firebase(URL)).$asObject();

        obj.$loaded().then(function() {
            if (obj.$priority) {
                obj.$bindTo($rootScope,'currentTest').then(function() {
                    console.log("bound");
                });
            }
            else {
                Test.create(user,obj);
            }
        });
    }

    $rootScope.$on('$firebaseSimpleLogin:login', function(e, user) {
        setCurrentTest(user);
    });

    return Test;
});

Controller (controller/test.js)

app.controller('TestCtrl', function($scope,  Test) {
    $scope.testy = Test.getCurrent();
});

View (test.html)

<div class="t_center">
    <h3>Testing</h3>
        <div>
            <input type="test" name="test1" value="testy.something" ng-model="testy.something"/>
            <input type="test" name="test2" ng-model="testy.somethingElse"/>
        </div>
    <br/>
</div>

Im currently using;

Any advice greatly appreciated.

Background I don't think my example code highlighted what I was trying to achieve very well so I will provide a little background to what I was trying to do. The object I create here (called "Test" in the example here) is actually basically a users profile. Amongst the usual usery type things (name etc) it also contains some preferences which are used by all of the controllers. Rather than copy that code around I wanted to make a service which obtained the users profile on login and placed it in the $rootScope ready for whatever controller required it. If the service couldn't find the profile in the system then it creates it (with sensible values).

Upvotes: 1

Views: 1276

Answers (1)

Kato
Kato

Reputation: 40582

Since this seems like a gross misappropriation of $rootScope, it seemed simpler to fix the issue than to understand what is wrong with your example. Here's a working example with a service and $bindTo.

var app = angular.module("sampleApp", ["firebase"]);

app.constant('FIREBASE_URL', 'https://kato-so25069621.firebaseio-demo.com/');

app.factory('Test',function($firebase, FIREBASE_URL) {
    return function(path) {
        var URL = FIREBASE_URL + path;
        var obj = $firebase(new Firebase(URL)).$asObject();
        obj.$loaded(function() {
            console.log('loaded', obj);
            if( obj.$value === null ) { // if object has not been initialized
                angular.extend(obj, {
                    something: "1234", 
                    somethingElse: "567",
                    $priority: 7
                });
                obj.$save();
            }
        });
        return obj;
    }
});

app.controller('TestCtrl', function($scope,  Test) {
    Test('test12/').$bindTo($scope, 'testy');
});

Note these important principles:

  • the service is no longer bound to $rootScope
  • we use $bindTo with the current $scope, so when it is destroyed it unbinds automagically
  • we do not worry about authentication inside our service but assume user is already authenticated, see more below

The only component missing here is authentication, which was purposefully left out. This should not be checked in every service and controller (instead, check out Using Simple Login with Routers under Authentication in the guide.

Upvotes: 3

Related Questions