Michelangelo
Michelangelo

Reputation: 5958

How to prepare arrays for insertion into Firebase database?

I have a question about adding arrays to Firebase using AngularFire. Let's start with a quick example. What I tend to do when my users on the front end create a list is something like this:

angular.module("app", ["firebase"])

  .controller("createListCtrl", function($scope, $firebaseArray) {
      console.log("controller loaded");
      $scope.newList = [];
      $scope.addItemToList = function(itemlist) {
        console.log(itemlist);
        $scope.newList.push({
          "item": itemlist,
          "done": false
        });
      }

      $scope.sendToDb = function() {
        var ref = new Firebase("https://xxxxxx.firebaseio.com");
        var list = $firebaseArray(ref);
        list.$add({
          "list": $scope.newList
        }).then(function(ref) {
          var id = ref.key();
          console.log("added record with id " + id);
          console.log(list.$indexFor(id)); // returns location in the array
        })
      }

Ok all nice and dandy and it all works great but I then I read this article: https://www.firebase.com/blog/2014-04-28-best-practices-arrays-in-firebase.html

And I heard more people say to avoid arrays and I see the problem with array in Firebase, but what is the alternative, the article says this structure: {foo: {counter: 1}, bar: {counter: 1}, baz: {counter: 1}};

Is that really a better structure? I think it gets messy and I don't even know how I would achieve this structure starting with something like this:$scope.newList = {};. Is it really a problem doing it with an array. Are arrays really evil in Firebase? Thanks in advance for an explanation or a better alternative.

edit

This is how the list is stored in Firebase, which does not seem very good:

---uniqueID
     ---list
        ---0
            ---done:false
            ---item:"item1"
        ---1
            ---done:false
            ---item:"item2"
        ---2
            ---done:false
            ---item:"item3"

Upvotes: 1

Views: 743

Answers (1)

Frank van Puffelen
Frank van Puffelen

Reputation: 600130

The $firebaseArray class, which you're already using, provides a mapping between Firebase's ordered collections (which use push ids for their keys) and AngularJS's array (which use regular arrays).

So in your controller's constructor instead of creating a local array for itemList, create a two-way synchronized $firebaseArray:

$scope.newList = $firebaseArray(new Firebase("https://xxxxxx.firebaseio.com"));

The blog post you're referring to served as the basis for quite a few changes to AngularFire since then. I highly recommend that you work through the AngularFire development guide. It will take at most a few hours and will answer many more questions than just this one (which is covered in the section on synchronized arrays).

Update

Thanks for the update. I now get what you're trying to do. So you initially want to keep the list of items client-side only, and then all at once save it to Firebase.

In that case, I'd write sendToDb like this:

$scope.sendToDb = function () {
  var ref = new Firebase("https://xxxxxx.firebaseio.com");
  var listRef = ref.push();
  $scope.newList.forEach(function(item) {
    var itemRef = listRef.push({ item: item.item, done: item.done });
    console.log('Added item with key: '+itemRef.key());
  });
}

This uses the regular Firebase JavaScript SDK. But since AngularFire is built on top of that, they will co-exist without problems.

So instead of pushing the array in one go, I simply loop over the items in it and push each of them.

Working fiddle here: https://jsfiddle.net/frankvanpuffelen/vnh5dbwq/11/

Upvotes: 1

Related Questions