Angularjs 在从指令调用的服务中保存对AngularFire$firebaseArray的更新

Angularjs 在从指令调用的服务中保存对AngularFire$firebaseArray的更新,angularjs,angularfire,Angularjs,Angularfire,我竭尽全力想弄明白这一点,我觉得我已经尽了一切努力让它工作 我正在创建一个todo应用程序。我在服务中使用AngularFire。有一个item指令重复每个都有复选框的项。当复选框被选中/取消选中时,它应该调用DataService上的一个方法来将项对象{completed:false}更新为{completed:true},或者在每次选中/取消选中时反之亦然。ngChange从对象数组中传入单个对象(对象表示唯一的项)。除了选中/取消选中复选框后能够保存更新的项目外,其他一切似乎都正常。我尝试

我竭尽全力想弄明白这一点,我觉得我已经尽了一切努力让它工作

我正在创建一个todo应用程序。我在服务中使用AngularFire。有一个item指令重复每个都有复选框的项。当复选框被选中/取消选中时,它应该调用DataService上的一个方法来将项对象{completed:false}更新为{completed:true},或者在每次选中/取消选中时反之亦然。ngChange从对象数组中传入单个对象(对象表示唯一的项)。除了选中/取消选中复选框后能够保存更新的项目外,其他一切似乎都正常。我尝试过的所有方法都给出了一个错误,例如:“无效记录;可以确定某个密钥的密钥”

在下面的屏幕截图中,控制台表示它更新了对象,但在尝试将更新的条目保存到firebase时抛出错误。我尝试传递的所有内容都会出现相同的错误。我做错了什么?请看下面的代码。我花了很长时间来摆弄这个,所以任何帮助都将不胜感激。如果有什么不合理的地方,请问我,而不是投反对票,我真的在尽力解释这一点,我真的需要帮助。谢谢大家!

服务代码:

var app = angular.module('dataService', ['firebase']);

app.factory('DataService', ["$firebaseArray",
  function ($firebaseArray) {
  //create, retrieve, update, destroy data from angularfire 

  var url = 'https://myFirebase.firebaseio.com/item';
  var fireRef = new Firebase(url);

  var factory = {};

  factory.complete = function (data) {
    var completeGoal = $firebaseArray(fireRef);
    console.log("complete, fired in factory");
    var itemID = data.$id;
    console.debug("this item ID: " + itemID);

    if(data.completed === true) {
      console.log("this item data.completed: " + data.completed)
      data.completed = false;
      console.log("this item data.completed: is NOW " + data.completed)
    }
    else {
      console.debug("this item data.completed: " + data.completed)
      data.completed = true;
      console.debug("this item data.completed: is NOW " + data.completed)
    }

    completeGoal.$save(itemID);
    console.log(completeGoal.$save(itemID));
  }

  return factory;

  }]);
app.directive('item', function() {
  return {
    scope: {
      item: '=set',
      onClick: '&',
      listType: '=',
      complete: '='
    },

    controller: function() {},
    controllerAs: 'ctrl',
    bindToController: true,
    transclude: true, 
    replace: true,
    restrict: 'EA',
    templateUrl: 'directives/items.html',
    link: function(scope, elem, attrs) {

      scope.$parent.onChange = function (data) {
        scope.ctrl.complete(data);
      }        

      //filter the items by type
      var typeFilter = {type: scope.ctrl.listType}
      scope.filterExpr = typeFilter;       
    }
  }
});
  <div class="row goal-item" ng-repeat="item in ctrl.item | filter:filterExpr">        
    <div class="col-xs-12 col-sm-8 col-sm-offset-2">
      <ul>
        <li>
          <label class="checkbox" ng-click="onChange(item)">
            <input type="checkbox" class="goal-checkbox" ng-click="null" />              
          </label>
          <span class="goal-title goal-completed">{{item.text}}</span>
        </li>
      </ul>
    </div>
  </div>
app.controller('mainCtrl', ['$scope','DataService', function($scope, DataService) {

  this.complete = DataService.complete;

}])
指令代码:

var app = angular.module('dataService', ['firebase']);

app.factory('DataService', ["$firebaseArray",
  function ($firebaseArray) {
  //create, retrieve, update, destroy data from angularfire 

  var url = 'https://myFirebase.firebaseio.com/item';
  var fireRef = new Firebase(url);

  var factory = {};

  factory.complete = function (data) {
    var completeGoal = $firebaseArray(fireRef);
    console.log("complete, fired in factory");
    var itemID = data.$id;
    console.debug("this item ID: " + itemID);

    if(data.completed === true) {
      console.log("this item data.completed: " + data.completed)
      data.completed = false;
      console.log("this item data.completed: is NOW " + data.completed)
    }
    else {
      console.debug("this item data.completed: " + data.completed)
      data.completed = true;
      console.debug("this item data.completed: is NOW " + data.completed)
    }

    completeGoal.$save(itemID);
    console.log(completeGoal.$save(itemID));
  }

  return factory;

  }]);
app.directive('item', function() {
  return {
    scope: {
      item: '=set',
      onClick: '&',
      listType: '=',
      complete: '='
    },

    controller: function() {},
    controllerAs: 'ctrl',
    bindToController: true,
    transclude: true, 
    replace: true,
    restrict: 'EA',
    templateUrl: 'directives/items.html',
    link: function(scope, elem, attrs) {

      scope.$parent.onChange = function (data) {
        scope.ctrl.complete(data);
      }        

      //filter the items by type
      var typeFilter = {type: scope.ctrl.listType}
      scope.filterExpr = typeFilter;       
    }
  }
});
  <div class="row goal-item" ng-repeat="item in ctrl.item | filter:filterExpr">        
    <div class="col-xs-12 col-sm-8 col-sm-offset-2">
      <ul>
        <li>
          <label class="checkbox" ng-click="onChange(item)">
            <input type="checkbox" class="goal-checkbox" ng-click="null" />              
          </label>
          <span class="goal-title goal-completed">{{item.text}}</span>
        </li>
      </ul>
    </div>
  </div>
app.controller('mainCtrl', ['$scope','DataService', function($scope, DataService) {

  this.complete = DataService.complete;

}])
项目指令模板:

var app = angular.module('dataService', ['firebase']);

app.factory('DataService', ["$firebaseArray",
  function ($firebaseArray) {
  //create, retrieve, update, destroy data from angularfire 

  var url = 'https://myFirebase.firebaseio.com/item';
  var fireRef = new Firebase(url);

  var factory = {};

  factory.complete = function (data) {
    var completeGoal = $firebaseArray(fireRef);
    console.log("complete, fired in factory");
    var itemID = data.$id;
    console.debug("this item ID: " + itemID);

    if(data.completed === true) {
      console.log("this item data.completed: " + data.completed)
      data.completed = false;
      console.log("this item data.completed: is NOW " + data.completed)
    }
    else {
      console.debug("this item data.completed: " + data.completed)
      data.completed = true;
      console.debug("this item data.completed: is NOW " + data.completed)
    }

    completeGoal.$save(itemID);
    console.log(completeGoal.$save(itemID));
  }

  return factory;

  }]);
app.directive('item', function() {
  return {
    scope: {
      item: '=set',
      onClick: '&',
      listType: '=',
      complete: '='
    },

    controller: function() {},
    controllerAs: 'ctrl',
    bindToController: true,
    transclude: true, 
    replace: true,
    restrict: 'EA',
    templateUrl: 'directives/items.html',
    link: function(scope, elem, attrs) {

      scope.$parent.onChange = function (data) {
        scope.ctrl.complete(data);
      }        

      //filter the items by type
      var typeFilter = {type: scope.ctrl.listType}
      scope.filterExpr = typeFilter;       
    }
  }
});
  <div class="row goal-item" ng-repeat="item in ctrl.item | filter:filterExpr">        
    <div class="col-xs-12 col-sm-8 col-sm-offset-2">
      <ul>
        <li>
          <label class="checkbox" ng-click="onChange(item)">
            <input type="checkbox" class="goal-checkbox" ng-click="null" />              
          </label>
          <span class="goal-title goal-completed">{{item.text}}</span>
        </li>
      </ul>
    </div>
  </div>
app.controller('mainCtrl', ['$scope','DataService', function($scope, DataService) {

  this.complete = DataService.complete;

}])

我认为这里的问题是,您正在使用实际的firebase密钥来尝试保存数据。根据angularfire文档,$save方法实际上接受2个参数中的1个:

$save(recordOrIndex)
所以要么记录是整个对象,要么索引是本地数组[0,1,2,3,…]中的索引位置

我认为最好的办法是尝试保存整个对象,而不是使用唯一键。所以像这样:

completeGoal.$save(data);
希望就这么简单

以下是我引用的angularfire api的链接:


我认为这里的问题是您正在使用实际的firebase密钥来尝试保存数据。根据angularfire文档,$save方法实际上接受2个参数中的1个:

$save(recordOrIndex)
所以要么记录是整个对象,要么索引是本地数组[0,1,2,3,…]中的索引位置

我认为最好的办法是尝试保存整个对象,而不是使用唯一键。所以像这样:

completeGoal.$save(data);
希望就这么简单

以下是我引用的angularfire api的链接: