5

I am building a simple car database app. When a user adds a new car it creates the below JSON data with blank fields for the gallery:

{
    "name": "Cars",
    "gallery": [{
        "img": "http://",
        "title": "BMW"
    }, {
        "img": "http://",
        "title": "Lexus"
    }, {
        "img": "http://",
        "title": "Ferrari"
    }],
    "pageId": "23",
    "storeURL": "/app/cars/gallery"
}

Now what I want to do in the app is if a user adds a new gallery image it should add new child after the last gallery picture. So after Ferrari it should insert a new object. I cannot seem to do this as every tutorial leads to a dead end and also the official Google docs specify that set() will replace all data so if you use update() it will add and in this case it does not add.

This code deletes all data:

function add(){
  var data = [
    {
      title: 'Mercedes',
      img: 'http://'
    }
  ]
  var postData = {
    pageGallery: data
  };
  var updates = {};
  updates['/app/cars/'] = postData;
  firebase.database().ref().update(updates);
  console.log('New car added');

}

And if I change and add the child:

firebase.database().ref().child('gallery').update(updates);

It does not do anything to do the data. Please can you help?

TheBlackBenzKid
  • 26,324
  • 41
  • 139
  • 209

2 Answers2

16

See this blog post on the many reasons not use arrays in our Firebase Database. Read it now, I'll wait here...

Welcome back. Now that you know why your current approach will lead to a painful time, let's have a look at how you should model this data. The blog post already told you about push IDs, which are Firebase's massively scalable, offline-ready approach to array-like collections.

As our documentation on reading and writing lists of data explains, you can add items to a list by calling push().

So if this creates a car:

function addStore(){
  var rootRef = firebase.database().ref();
  var storesRef = rootRef.child('app/cars');
  var newStoreRef = storesRef.push();
  newStoreRef.set({
    name: "Cars",
    "pageId": "23",
    "storeURL": "/app/cars/gallery"
  });
}

Then to add an image to the gallery of that store:

var newCarRef = newStoreRef.child('gallery').push();
newCarRef.set({
  title: 'Mercedes',
  img: 'http://'
})

This will add a new car/image to the end of the gallery (creating the gallery if it doesn't exist yet).

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • 1
    Firstly, thanks for the comment. Very humbled to hear from a real Google developer. Regarding the answer you are correct; I will try to use the Firebase best practices when using keys. Thanks! (I still like the array old school approach however) – TheBlackBenzKid Oct 16 '16 at 07:05
3

If somebody wants it With Error Handling :

          var rootRef = firebase.database().ref();
          var storesRef = rootRef.child('Lorelle/Visitors');
          var newStoreRef = storesRef.push();
          newStoreRef.set($scope.CarModal,
            function(error) {
              //NOTE: this completion has a bug, I need to fix.
              if (error) {
                   console.log("Data could not be saved." + error);
                   Materialize.toast('Error: Failed to Submit' + error, 2000);
              } else {
                 console.log("Data saved successfully.");
                 Materialize.toast('Data Submitted, Thank You.', 2000);

                   }
                });
             }
Hitesh Sahu
  • 41,955
  • 17
  • 205
  • 154
  • 1
    You can replace $scope.CarModal with JSON object { name: "Cars", "pageId": "23", "storeURL": "/app/cars/gallery" } and it would work perfectly. Pure JS is rare this days. – Hitesh Sahu Sep 27 '17 at 08:42