Frontend engineers today can easily build interfaces and implement their functionalities without the headache of integrating a backend or application programming interface (API). In this tutorial, we’ll demonstrate how to build a Vue.js application with create, read, update, delete (CRUD) functionalities and store data with Cloud Firestore. If you wish, you can also deploy this application to Firebase Hosting.
Firebase is a backend-as-a-service (BaaS) offering by Google that features databases, an ML kit, cloud functions, authentication, hosting, cloud storage, and more. Firebase abstracts the complexity of building a robust and scalable backend system, enabling developers to focus on building the client side of applications.
For our CRUD application, we’ll focus on using Cloud Firestore for data storage. Cloud Firestore is a NoSQL database that stores data in the form of documents, which are arranged into collections and support client- or server-side integration. Cloud Firestore documents contain various fields that can hold any data type and support very fast read or write.
Vue.js is a lightweight framework for building interactive user interfaces and single-page applications. We’ll use a design library called Element UI, which provides components to help developers build faster user interfaces.
To follow along with this tutorial, you’ll need:
npm install -g firebase-tools
)
firebase login
npm install -g @vue/cli
)
vue --version
To get started with Firebase, create a Firebase project by following the steps below. (Note: Firebase projects are linked to Google Cloud Platform project.)
</>
Setting up a Vue.js project will create the files and install the dependencies required to build a user interface. Execute the following command.
vue create crud-app
Configure your Vue.js project on the interactive screen that shows up. Simply select the default (Babel, ESLint) preset, which is the default configuration.
When done, you should see a new crud-app
directory.
Change into the crud-app
directory using cd crud-app
or open the folder in your code editor.
To set up Element UI within the created Vue.js project using its Vue.js plugin, execute the following command to install Element UI in the crud-app
directory.
vue add element
Configure the setup as follows:
Fully import
N
locale
, select en
We’re now done setting up Vue.js and Element UI.
To start the development server, execute the following.
npm run serve
You should see an output similar to this on your browser:
Before you can use Cloud Firestore, you need to set up the Firebase client on the Vue.js project.
Install the Firebase JS client and update your dependencies within the crud-app
directory.
npm install firebase --save
Create a new file with the name firebaseConfig.js
within the src
directory with similar contents.
// src/firebaseConfig.js
import firebase from "firebase";
// Your web app's Firebase configuration
var firebaseConfig = {
apiKey: "AIzaSyC9J2hIQ1XQFZZZZZZZZZZZZZZZZZ",
authDomain: "employee-crud-ZZZZZZZZZ.firebaseapp.com",
databaseURL: "https://employee-crud-ZZZZZZ.firebaseio.com",
projectId: "employee-crud-XXXXXXXX",
storageBucket: "employee-crud-ZZZZZ.appspot.com",
messagingSenderId: "8761301111111",
appId: "1:87613015171:web:e60ee5139c5ZZZZZZZ"
};
// Initialize Firebase
export default firebase.initializeApp(firebaseConfig);
Replace the firebaseConfig
object with what you copied earlier during the Firebase app setup.
Let’s review some methods used for individual CRUD operations in the Vue.js app. Below are some truncated snippets to help explain individual methods.
You’ll need to import the initialized Firebase app and create an instance of Cloud Firestore.
import firebase from "./firebaseInit";
const db = firebase.firestore();
The method below creates a new document on the Cloud Firestore collection.
createEmployee(name, date) {
db.collection("employees")
.add({ date: date, name: name })
.then(() => {
console.log("Document successfully written!");
})
.catch((error) => {
console.error("Error writing document: ", error);
});
}
The values of name
and date
would be saved as a new document within the employees
collection.
This method is used to fetch all documents from the Cloud Firestore collection.
readEmployees() {
let employeesData = [];
db.collection("employees")
.get()
.then((querySnapshot) => {
querySnapshot.forEach((doc) => {
employeesData.push({
id: doc.id,
name: doc.data().name,
date: doc.data().date,
});
console.log(doc.id, " => ", doc.data());
});
return employeesData
})
.catch((error) => {
console.log("Error getting documents: ", error);
});
}
This loops through all documents in the Cloud Firestore collection and writes their data, along with id
, to the employeesData
variable.
The update method is used to edit an existing document on the Cloud Firestore collection.
updateEmployee(id, name, date) {
db.collection("employees")
.doc(id)
.update({
name: name,
date: date,
})
.then(() => {
console.log("Document successfully updated!");
})
.catch((error) => {
console.error("Error updating document: ", error);
});
}
The document with the passed id
will be updated on the Cloud Firestore collection with the new values for name
and date
as passed during the method call.
The delete method erases a document that exists on the Cloud Firestore collection.
deleteEmployee(id) {
db.collection("employees")
.doc(id)
.delete()
.then(() => {
console.log("Document successfully deleted!");
})
.catch((error) => {
console.error("Error removing document: ", error);
});
}
The document with the passed id will be deleted on the Cloud Firestore collection.
Vue.js uses single-file components, which allows you to build an entire user interface, including the layout, functionalities, and styles, in one .vue file.
For this tutorial, you’ll only need to modify the App.vue
file.
Element UI provides a lot of reusable components, which makes building interfaces much faster. For our purposes, we’ll use a basic data table to list all the documents coming from the database.
A pop-over input is used to create and edit documents, while a button is used to trigger deletion.
<!-- src/App.vue -->
<template>
<div>
<el-popover
placement="bottom"
title="New Employee"
width="200"
trigger="click"
>
<el-input
placeholder="John Doe"
v-model="name"
@blur="createEmployee(name, date)"
></el-input>
<el-button round slot="reference" type="success"
>Add New Employee</el-button
>
</el-popover>
<el-table
:data="
employeesData.filter(
(data) =>
!search || data.name.toLowerCase().includes(search.toLowerCase())
)
"
style="width: 100%;"
>
<el-table-column label="Date" prop="date"> </el-table-column>
<el-table-column label="Name" prop="name"> </el-table-column>
<el-table-column align="right">
<template slot="header" :slot-scope="scope">
<el-input v-model="search" size="mini" placeholder="Type to search" />
</template>
<template slot-scope="scope">
<el-popover
placement="bottom"
title="Edit Employee"
width="200"
trigger="click"
>
<el-input
placeholder="John Doe"
v-model="scope.row.name"
@blur="updateEmployee(scope.row.id, scope.row.name, date)"
></el-input>
<el-button size="mini" slot="reference">Edit</el-button>
</el-popover>
<el-button
size="mini"
type="danger"
@click="deleteEmployee(scope.row.id)"
>Delete</el-button
>
</template>
</el-table-column>
</el-table>
</div>
</template>
As explained earlier, our functions are all within the methods()
section. The variables in use are also listed in the data()
. Since we want to read all the documents once the application loads, we called the readEmployees()
methods inside the mounted()
lifecycle hook.
<!-- src/App.vue -->
<script>
import firebase from "./firebaseInit";
const db = firebase.firestore();
export default {
data() {
return {
name: "",
date: new Date().toISOString().slice(0, 10),
employeesData: [],
search: "",
};
},
methods: {
createEmployee(name, date) {
if (name != "") {
db.collection("employees")
.add({ date: date, name: name })
.then(() => {
console.log("Document successfully written!");
this.readEmployees();
})
.catch((error) => {
console.error("Error writing document: ", error);
});
this.name = "";
}
},
readEmployees() {
this.employeesData = [];
db.collection("employees")
.get()
.then((querySnapshot) => {
querySnapshot.forEach((doc) => {
this.employeesData.push({
id: doc.id,
name: doc.data().name,
date: doc.data().date,
});
console.log(doc.id, " => ", doc.data());
});
})
.catch((error) => {
console.log("Error getting documents: ", error);
});
},
updateEmployee(id, name, date) {
db.collection("employees")
.doc(id)
.update({
name: name,
date: date,
})
.then(() => {
console.log("Document successfully updated!");
this.readEmployees();
})
.catch((error) => {
// The document probably doesn't exist.
console.error("Error updating document: ", error);
});
},
deleteEmployee(id) {
db.collection("employees")
.doc(id)
.delete()
.then(() => {
console.log("Document successfully deleted!");
this.readEmployees();
})
.catch((error) => {
console.error("Error removing document: ", error);
});
},
},
mounted() {
this.readEmployees();
},
};
</script>
Firebase allows you to deploy static files. But first, you must build your assets.
Within the crud-app
directory, run the following command.
npm run build && cd dist
Next, initialize Firebase and complete the following steps.
firebase init
.
To deploy, execute the following command.
firebase deploy
You should now have the basic tools you need to build a simple application using Vue.js for the client side and Firebase for data storage and hosting. You can find the full source code on GitHub and also access a demo of the app.
To learn more, check out the following resources.
Originally published by Timothy Olaleke at https://blog.logrocket.com
#vue-js #firebase #web-development #javascript