AnotherMike
AnotherMike

Reputation: 2913

Saving Updates to AngularFire $firebaseArray in a Service Called from a Directive

I am pulling my hair out trying to figure this out, I feel like I've tried everything to get this working.

I am creating essentially a todo app. I am using AngularFire in a service. There is an item directive that is repeating items that each have a checkbox. When a checkbox is checked/unchecked it should call a method on the DataService to update the item object {completed: false} to {completed: true} or vice versa each time it's checked/unchecked. ngChange passes in the individual object from an array of objects (objects are representing a unique item). Everything seems to work except being able to save the updated item after the checkbox is checked/unchecked. Everything I've tried has given for example, this error: "Invalid record; could determine key for somekey"

In the screenshot below, the console says it updates the object, but throws an error on trying to save the updated entry to firebase. Everything I've tried passing in has given the same error. What am I doing wrong here? Please take a look at the code below. I've spent a long time fiddling with this, so any help would be greatly appreciated. Please if anything doesn't make sense, ask me instead of downvoting, I'm really trying to explain this the best I can and really need help. Thank You!

Console log errors

Service Code:

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;

  }]);

Directive Code:

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

Item Directive Template:

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

Controller:

app.controller('mainCtrl', ['$scope','DataService', function($scope, DataService) {

  this.complete = DataService.complete;

}])

Upvotes: 1

Views: 1567

Answers (1)

Kyle
Kyle

Reputation: 1503

I think the problem here is that you're using the actual firebase key to try and save the data. According to the angularfire docs the $save method actually accepts 1 of 2 parameters:

$save(recordOrIndex)

So either the record - which would be the entire object or the index wich would be the indexed location inside of your local array [0,1,2,3,...]

I think your best bet would be to try and save the entire object opposed to using the unique key. So like this:

completeGoal.$save(data);

Hopefully it's that easy!

Here's the link to the angularfire api I'm referencing:

https://www.firebase.com/docs/web/libraries/angular/api.html#angularfire-firebasearray-saverecordorindex

Upvotes: 0

Related Questions