Трехсторонняя привязка данных AngularFire не обновляет firebase при изменении флажка

Я разрабатываю простое приложение todo с Angular и Firebase, используя модуль AngularFire.

Итак, у меня есть логический атрибут в моей модели, представленный флажком в шаблоне, проблема в том, что я пытаюсь использовать трехстороннюю привязку данных из AngularFire, используя метод $bind, чтобы синхронизировать все изменения (данные firebase, DOM и ng-model), но данные firebase не обновляются, когда я устанавливаю флажок.

Вот мой контроллер, в котором я использую метод AngularFire $bind:

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);
    };
  }]);

А вот файл tempalte:

<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>  

Я что-то пропустил? Действительно ли это возможно сделать с помощью простого флажка?

Заранее спасибо.


person Bernardo    schedule 27.01.2014    source источник
comment
Вы не указали объект todo, но привязались к одному из его свойств (todo.done). Что произойдет, если вы просто привяжетесь к $scope.done или другому прямому пути?   -  person Kato    schedule 27.01.2014
comment
@Като Ничего не происходит. Я только что обновил вопрос с полным кодом шаблона. Я надеюсь, что это поможет как-то.   -  person Bernardo    schedule 27.01.2014
comment
Като, ты можешь помочь мне с этим? stackoverflow.com/questions/37847600/   -  person Pristine Kallio    schedule 16.06.2016


Ответы (1)


Вы не указали здесь todoService, поэтому будет сложно дать вам точный ответ. Я предполагаю, что todoService возвращает экземпляр $firebase, содержащий todos, так как это кажется вероятным. Имейте в виду, что проблема может быть и в этом коде.

Несколько проблем, которые вы можете решить, что может решить вашу проблему:

Ваш TodoCtrl не относится к элементам

Кажется, вы используете TodoCtrl, как если бы он был создан для каждого элемента в файле ng-repeat. Однако он существует вне области действия ng-repeat и создается только один раз для всего списка.

Ng-repeat не использует вашу существующую область контроллера повторно.

Директивы действуют в изолированной области. Это означает, что они не разделяют область действия с вашим контроллером. Поэтому, когда вы делаете ng-repeat="todo in todos", вы не добавляете todo в область действия вашего контроллера.

Это имеет смысл, поскольку каждая итерация ng-repeat будет перезаписывать один и тот же объект todo.

Вы пытаетесь выполнить двойную привязку к синхронизированному объекту

Вы пытаетесь создать трехстороннюю привязку $scope.todos.[$todo].done, но вы уже создали трехстороннюю привязку $scope.todos. Вместо этого пусть $scope.todos позаботится о синхронизации.

Вы попытались связать $scope.todos с самим свойством

Когда вы вызываете $bind, вы привязываете $scope.todos к $scope.todos.todo.done. Очевидно, что это самореферентное утверждение не то, что вы имели в виду. Я не могу сказать, что возвращает ваш сервис, но, возможно, вы имели в виду это:

todoService.$bind($scope, 'todos');

Если вы не хотите автоматически вносить изменения во весь список задач, вы можете добавить вызов $save вместо использования $bind:

$scope.todos = todoService;

<input type="checkbox" ng-model="todo.done" ng-change="$parent.todos.$save(id)">

Все вместе:

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 ... **/      
   });
person Kato    schedule 27.01.2014