1

I'm populating a simple To-do notes application using AngularJS and Firebase. (And I'm new to AngularJS, too !) The To-do notes will be saved in $scope.todos variable. This is my app.js code:

myApp.controller('mainController', function($scope, $firebase) {
    // connect to firebase
    var ref = new Firebase("https://XXX.firebaseio.com/todos");
    var fb = $firebase(ref);
    $scope.todos = [];
    // sync as object
    var syncObject = fb.$asObject();
    // 3-way data binding
    syncObject.$bindTo($scope, "todos");

    $scope.addNewTodo = function(){
        var todoTitle = $(".add-todo").val();
        var createdAt = new Date();
        var element = {
            title: todoTitle,
            timestamp: createdAt,
            done: false
        };
        fb.$push(element);
        $(".add-todo").val("");
    };
});

And this is my index.html code:

<div class="container" ng-app="todoApp" ng-controller="mainController">
    <div class="row">
        <div class="col-md-6">
            <div class="todolist not-done">
                <h1>Todos</h1>
                <input type="text" class="form-control add-todo" placeholder="Add todo" ng-enter="addNewTodo()">
                <button id="checkAll" class="btn btn-success">Mark all as done</button>
                <hr/>
                <ul id="sortable" class="list-unstyled" ng-repeat="todo in todos">
                    <li class="ui-state-default">
                        <div class="checkbox">
                            <label>
                            <input type="checkbox" value=""/> {{ todo.title }}</label>
                        </div>
                    </li>
                </ul>
                <div class="todo-footer">
                    <strong><span class="count-todos">{{ todos.length }}</span></strong> Items Left
                </div>
            </div>
        </div>
    </div>
</div>

I added {{todos.length}} for counting the remaining todos elements in the $scope.todos array. But it isn't automatically updated when I add or remove elements from the $scope.todos array. This is a bit strange for me cause it's quite different than what MeteorJS does, if I do the same thing.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
sonlexqt
  • 6,011
  • 5
  • 42
  • 58
  • I'm not really familiar with Firebase but it looks to be Firebase related. In my test it's working: http://plnkr.co/edit/TmGu2V92rz4BrompD8Dx?p=preview – Wayne Ellery Dec 27 '14 at 09:45

2 Answers2

3

I believe you will want to use a Synchronized Array instead of the 3 way data binding https://www.firebase.com/docs/web/libraries/angular/quickstart.html#section-arrays

unobf
  • 7,158
  • 1
  • 23
  • 36
3

As @unobf already said, you should use AngularFire's $asArray in this case.

Firebase loads (and synchronizes) your data asynchronously in the background. This means that it may receive updates to the array even when the current user wasn't the one who added a task. When this happens, it needs to (in addition to updating the array) notify AngularJS that the data was modified. You call $asObject which handles such notifications for objects, but was not designed to handle arrays. For handling the intricacies between Firebase's ordered collections (which don't use indexes, but a different type of keys) and AngularJS arrays, you need to use $asArray.

.controller('mainController', function($scope, $firebase) {
// connect to firebase
var ref = new Firebase("https://XXX.firebaseio.com/todos");
var fb = $firebase(ref);
$scope.todos = [];
// sync as object
var syncObject = fb.$asArray();
// 3-way data binding
$scope.todos = syncObject; // was: syncObject.$bindTo($scope, "todos");

$scope.addNewTodo = function(){
    var todoTitle = $(".add-todo").val();
    var createdAt = new Date();
    var element = {
        title: todoTitle,
        timestamp: createdAt,
        done: false
    };
    $scope.todos.$add(element);  // was: fb.$push(element);
    $(".add-todo").val("");
};

You can find a working example here: http://jsbin.com/celefu

To learn more about this type of problem, also see my answer to these questions:

Community
  • 1
  • 1
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • 1
    Thanks so much for your clear & deep answer ! Now my app works again :) – sonlexqt Dec 27 '14 at 16:41
  • Also check out the [AngularFire guide](https://www.firebase.com/docs/web/libraries/angular/guide.html), which covers most everything said here, albeit less eloquently. – Kato Dec 30 '14 at 17:51