Search code examples
javascriptfirebasevue.jsgoogle-cloud-firestorevuefire

Why Firestore returns a Collection Reference but my program treat its as an Array?


So I made a simple app on Vue. Then I realized it would be cool to connect it with an online database so I thought I would try Firebase (i have very little backend knowledge so i wanted something fast and "simple").

The problem is in the next line:

firestore () {
      return {
        items: db.collection('items')
      }
    }

When i do that, my original array items which is located in the usual data() of any vue component, gets filled with the objects of that collection.

The problem is I only want to get the field of each object in that collection (for example, the field name of each to-do item), not the entire object. I looked and it seems there´s no easy way as doing "db.collection('items).name"

So i thought in doing a function to get that data into an array and then pass it in items:

function cleanRawData(objectToClean){
      var cleanedArr = [];

      for(let i=0; i<objectToClean.length; i++){
        cleanedArr.push(objectToClean[i].name)
      }

      return cleanedArr
}

 data () {
      return {
          
          items: [],

        }
    },
    firestore () {
      let itemObject = db.collection('items');
      return {
       items: cleanRawData(itemObject)
      }
    }

Well I dont know if If i´ve made a lot of mistakes there but the point is i want to "clean" what Firestore gives me.

The problem is i can´t even try the function because when i console.log(db.collection('items')) doesn´t give me an array of objects but a "Firestore Collection" however why then the App renders perfectly the data like if it´s being a simple array?


Solution

  • You are using Vuefire and in particular the declarative binding.

    This is why by simply doing

      firestore: {
        items: db.collection('items')
      }
    

    you populate the items array (and this array is updated anytime there is a change in the collection).


    So, depending on what you exactly want to do you may use one of the two approaches presented below:

    <template>
      <div>
        <ol>
          <li v-for="i in items">{{ i.name }}</li>
        </ol>
    
        <ol>
          <li v-for="n in names">{{ n }}</li>
        </ol>
      </div>
    </template>
    
    <script>
    import { db } from "../firebase";
    export default {
      data() {
        return {
          items: []
        };
      },
    
      firestore: {
        items: db.collection('items')
      },
      computed: {
        names() {
          return this.items.map(item => {
            return item.name;
          });
        }
      }
    };
    </script>
    

    If you just want to display the name of each item you can use the approach in the first v-for, where, for each item, we display the name property of the item.

    If you really want to generate another array with only the names, use a computed property. Note that the second v-for shows the same result when looping over the names (computed) array.