Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62
Subscribe to my email list now at http://jauyeung.net/subscribe/
The Vuefire library lets us add Firebase database manipulation capabilities right from our Vue app.
In this article, we’ll look at how to use Vuefire and Vuexfire to add support for Cloud Firestore database manipulation into our Vue app.
Querying the Database
We can query the database and synchronize it with the Vuex store with Vuexfire.
Sorting
To sort the data that we get from the Firebase database, we can call orderBy
to sort the data.
db.js
import firebase from "firebase/app";
import "firebase/firestore";
export const db = firebase
.initializeApp({ projectId: "project-id" })
.firestore();
const { Timestamp, GeoPoint } = firebase.firestore;
export { Timestamp, GeoPoint };
main.js
import Vue from "vue";
import App from "./App.vue";
import { firestorePlugin } from "vuefire";
import { vuexfireMutations, firestoreAction } from "vuexfire";
import Vuex from "vuex";
import { db } from "./db";
Vue.use(Vuex);
Vue.use(firestorePlugin);
Vue.config.productionTip = false;
const store = new Vuex.Store({
state: {
books: []
},
mutations: {
...vuexfireMutations
},
actions: {
bindBooksRef: firestoreAction((context) => {
return context.bindFirestoreRef(
"books",
db.collection("books").orderBy("title", "desc")
);
})
},
getters: {
books: (state) => {
return state.books;
}
}
});
new Vue({
store,
render: (h) => h(App)
}).$mount("#app");
App.vue
<template>
<div>{{books}}</div>
</template>
<script>
import { mapGetters, mapActions } from "vuex";
export default {
data() {
return {};
},
methods: {
...mapActions(["bindBooksRef"])
},
computed: {
...mapGetters(["books"])
},
mounted() {
this.bindBooksRef();
}
};
</script>
In the bindBookRef
action, we called the bindFirestoreRef
method to bind the books
state to our books
database collection.
The orderBy
method sorts the title
field value in descending order.
Then state.books
returns an array of books
object with title
sorted in descending order.
Since we called mapGetters
to map the getters to computed properties, we’ll see this displayed in the template.
Filtering
We can also filter items with the where
method.
For example, we can write:
main.js
import Vue from "vue";
import App from "./App.vue";
import { firestorePlugin } from "vuefire";
import { vuexfireMutations, firestoreAction } from "vuexfire";
import Vuex from "vuex";
import { db } from "./db";
Vue.use(Vuex);
Vue.use(firestorePlugin);
Vue.config.productionTip = false;
const store = new Vuex.Store({
state: {
books: []
},
mutations: {
...vuexfireMutations
},
actions: {
bindBooksRef: firestoreAction((context) => {
return context.bindFirestoreRef(
"books",
db.collection("books").where("wordCount", ">", 200)
);
})
},
getters: {
books: (state) => {
return state.books;
}
}
});
new Vue({
store,
render: (h) => h(App)
}).$mount("#app");
We called where
to only return the documents with wordCount
bigger than 200.
Then this is what we’ll see in the states and getters.
Writing to the Database
We have to use the Firebase SDK to write to our Firebase database.
For example, we can write:
main.js
import Vue from "vue";
import App from "./App.vue";
import { firestorePlugin } from "vuefire";
import { vuexfireMutations, firestoreAction } from "vuexfire";
import Vuex from "vuex";
import { db } from "./db";
Vue.use(Vuex);
Vue.use(firestorePlugin);
Vue.config.productionTip = false;
const store = new Vuex.Store({
state: {
books: [],
book: {}
},
mutations: {
...vuexfireMutations
},
actions: {
bindBooksRef: firestoreAction((context) => {
return context.bindFirestoreRef("books", db.collection("books"));
}),
updateBook: firestoreAction(async ({ state }, { bookId, title }) => {
const bookSnapshot = await db.collection("books").doc(bookId).get();
const book = bookSnapshot.data();
const newBook = { ...book, title };
await db.collection("books").doc(bookId).set(newBook);
console.log("book updated");
})
},
getters: {
books: (state) => {
return state.books;
}
}
});
new Vue({
store,
render: (h) => h(App)
}).$mount("#app");
App.vue
<template>
<div>
<button @click="updateBook">update book</button>
<div>{{books}}</div>
</div>
</template>
<script>
import { mapGetters, mapActions } from "vuex";
export default {
data() {
return {};
},
methods: {
...mapActions(["bindBooksRef"]),
updateBook() {
this.$store.dispatch("updateBook", {
bookId: "ei4jIGJjcmS7eSRKUxsw",
title: "baz"
});
}
},
computed: {
...mapGetters(["books"])
},
mounted() {
this.bindBooksRef();
}
};
</script>
In the Vuex store, we have the updateBook
action to let us get the book we want to update by its bookId
.
And we want to update the title
with it.
To do that, we get the books
collection with the collection
method.
doc
gets the document by ID.
get
gets the snapshot of the query result.
Then the data
method returns the actual data.
Once we did that, we update the title
by creating the newBook
object.
And once we did that, we call set
to update the document.
In the App
component, we called dispatch
in the updateBook
method to dispatch the updateBook
Vuex store action to do the update.
Since sync the store state with the collection with bindFirestoreRef
, the updated items should show automatically.
Conclusion
We can update the data by using methods from the Firebase SDK.
Since it’s async, we’ve to put the code in actions.
Also, we can sort and filter items when we do the binding of the collection to the state.