AngularFire 3-way data binding is not updating firebase when a checkbox change
angularfire, angularjs, data-binding, firebase, javascript
Solution
You haven't included todoService here so it's going to be difficult to give you an accurate answer. I'll assume that todoService returns a $firebase instance containing the `todos` since that seems likely. Keep in mind that the problem could be in that code as well.
Several problems you can address, which may resolve your issue:
Your TodoCtrl is not per-item
You seem to be using TodoCtrl as if it were created per-item in the ng-repeat. However, it exists outside the scope of ng-repeat and is only created once for the entire list.
Ng-repeat does not re-use your existing controller scope.
Directives operate in an isolate scope. That means that they do not share scope with your controller. So when you do ng-repeat="todo in todos" you do not add `todo` into your controller's scope.
This makes sense since each ng-repeat iteration would overwrite the same `todo` object.
You are trying to double-bind to a synchronized object
You are trying to create a three-way binding `$scope.todos.[$todo].done`, but you have already created a three-way binding on `$scope.todos`. Instead, let $scope.todos take care of synchronization.
You've attempted to bind $scope.todos to a property in itself
When you call $bind, you are binding $scope.todos to $scope.todos.todo.done. Obviously this self-referential statement isn't what you intended. I can't tell what is returned by your service but maybe you meant this:
todoService.$bind($scope, 'todos');
If you don't want to automatically push changes on the entire todos list, you can add a $save call instead of using $bind:
$scope.todos = todoService;
<input type="checkbox" ng-model="todo.done" ng-change="$parent.todos.$save(id)">
All together:
angular.module('singularPracticeApp')
.service('todoService', function($firebase) {
return $firebase( new Firebase(URL_TO_TODOS_LIST) );
});
.controller('TodoCtrl', function($scope, todoService) {
todoService.$bind($scope, 'todos');
$scope.addTodo = function () {
$scope.todos.$add({text: $scope.todoText, done:false});
$scope.todoText = '';
};
/** ... and so on ... **/
});
Problem
I'm developing a simple todo app with Angular and Firebase using AngularFire module. So I have a boolean attribute in my model represented by a checkbox in the template, the problem is that I'm trying to use the three way data binding from AngularFire using the `$bind` method to keep the all changes syncronized (firebase data, DOM and ng-model) but the firebase data is not updating when I select a checkbox. Here's my controller where I'm using the AngularFire `$bind` method: ``` angular.module('singularPracticeApp') .controller('TodoCtrl', ['$scope', 'TodoService', function ($scope, todoService) { $scope.todos = todoService; $scope.todos.$bind($scope, 'todo.done'); $scope.addTodo = function () { $scope.todos.$add({text: $scope.todoText, done:false}); $scope.todoText = ''; }; $scope.remaining = function () { var count = -11; angular.forEach($scope.todos, function(todo){ count += todo.done? 0 : 1; }); return count; }; $scope.clear = function (id) { $scope.todos.$remove(id); }; }]); ``` And here is the tempalte file: ``` <div ng-controller="TodoCtrl"> <h4>Task runner</h4> <span>{{remaining()}} todos left.</span> <ul> <li ng-repeat="(id, todo) in todos"> <input type="checkbox" ng-model="todo.done"> <span ng-if="todo.done" style="color: #ddd;">{{todo.text}}</span> <span ng-if="todo.done == false">{{todo.text}}</span> <small ng-if="todo.done"><a href="" ng-click="clear(id)">clear</a></small> </li> </ul> <form ng-submit="addTodo()"> <input type="text" ng-model="todoText" placeholder="New todo item"> <input type="submit" class="btn btn-primary" value="add"> </form> </div> ``` Am I missing something? Is really possible to make this work with a simple checkbox? Thanks in advance.