Using Firebase Cloud Firestore in Vue with vue-firestore

572
SHARES
2.6k
VIEWS

Cloud Firestore is the spiritual successor to Firebase’s popular Realtime Database. While there are many key differences which you can read about here, the main ones that jump out are: a more structured data model, more robust indexed queries, and atomic batch operations.

We’ll be using the individual @firebase namespaced packages (to keep our bundle size down) as well as vue-firestore for some simple Vue bindings.

Installation

If you want to skip installation and get right to it, here’s a codesandbox with everything you need, just add your firebase config.

If starting from scratch, use the vue-cli template of your choice (webpack-simple is a good one).

Then install everything you’ll need to get this ‘fired’ up 🔥🚀

$ npm install @firebase/app @firebase/firestore vue-firestore --save

Note: we’re using the namespaced packages to avoid importing the larger firebase library.

Configure Firebase

You will need to get your project credentials from the Firebase Console by going to Add Firebase to your web app.

Once you have the credentials, create firebase.js to initialize firestore, replacing the placeholder data with your own.

firebase.js

import { firebase } from "@firebase/app";
import "@firebase/firestore";

const firebaseApp = firebase.initializeApp({
  apiKey: "xxxxxxxxxxxxxxxxxxxxxxxxxxx",
  authDomain: "your-project.firebaseapp.com",
  databaseURL: "https://your-project.firebaseio.com",
  projectId: "your-project",
  storageBucket: "your-project.appspot.com",
  messagingSenderId: "xxxxxxxxxxxx"
});

export const db = firebaseApp.firestore();

If you haven’t done so, add Cloud Firestore to your project in the Firebase Console by going to Database > Get Started > Try Firestore Beta.

Add to Vue with vue-firestore

In index.js let’s make sure Vue is using vue-firestore

index.js

import Vue from 'vue';
import App from './App';
import VueFirestore from 'vue-firestore';

// turns off the 'You are running Vue in development mode.' msg
Vue.config.productionTip = false;

Vue.use(VueFirestore);

new Vue({
  el: '#app',
  template: '<App/>',
  components: { App },
})

Now for the magic. Replace whatever is in App.vue with the following:

App.vue

<template>
  <div id="app">
    <div>
      <input type="text"
        v-model="newReptile"
        @keyup.enter="addReptile">
      <button  @click="addReptile">
        Add Reptile
      </button>
    </div>
    <ul class="reptileList">
      <li v-for="reptile in reptiles" >
        {{ reptile.name }} -
        <button @click="deleteReptile(reptile)">
          Remove
        </button>
      </li>
    </ul>
  </div>
</template>

<script>
  import { db } from './firebase';

  export default {
    name: 'app',
    data() {
      return {
        reptiles: [],
        newReptile: ''
      }
    },
    firestore() {
      return {
        reptiles: db.collection('reptiles'),
      }
    },
    methods: {
      addReptile: function() {
        this.$firestore.reptiles.add(
          {
            name: this.newReptile,
            timestamp: new Date()
          }
        );
        this.newReptile = '';
      },
      deleteReptile: function(reptile) {
        this.$firestore.reptiles.doc(reptile['.key']).delete();
      }
    }
  }
</script>

<style>
  #app {
    font-family: 'Avenir', Helvetica, Arial, sans-serif;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-align: center;
    color: #2c3e50;
    margin-top: 60px;
  }
  .reptileList {
    list-style: none;
  }
</style>

So what’s happening here? We import a reference to our db from firebase.jsand use firestore() from vue-firestore to bind our ‘reptiles’ collection in realtime. We create an addReptile method which makes use of add() so we don’t have to worry about generating document IDs. In this case we’re generating a timestamp so that sorting will be easier in the future.

Lastly, we add a deleteReptile method which takes a reptile object as input. The secret sauce here is the .key property which is required to delete (or update) a document. This is possible because the reptiles collection will be returned in this normalized format:

[
    {
        ".key": "-Jtjl482BaXBCI7brMk7",
        "name": "New York",
        "timestamp": "February 5, 2019 at 11:05:15 AM UTC-5"
    },
    {
        ".key": "-JtjlAXoQ3VAoNiJckc1",
        "name": "London",
        "timestamp": "February 5, 2019 at 11:08:28 AM UTC-5"
    }
]

Best resources to learn Vue.js and firebase

Leave a Reply

Your email address will not be published. Required fields are marked *