Passing info using vuex and firebase firestore

Eze Henry
Eze Henry
Nov 6 · 9 min read

Definitions

Vue.js is a powerful framework for building JavaScript-based single page web-applications and is often considered to combine the best of both, React and Angular.

Firebase is a cloud development platform by Google which offers various services for building modern web & mobile applications. E.g. the Firebase Firestore service enables you to store and sync data in real-time. The Cloud Functions feature enabled you to run mobile back-end code without managing servers.

Vuex is the official state management system of vue and serves as the single source of truth for a vue.js application

Great to have

  1. Knowledge of javascript
  2. knowledge of vuetify or any other styling framework of choice
  3. knowledge of vue.js
  4. Node.js (compulsory since we would be using the vue cli so if you do not have it installed you can visit here ).

Lets begin!😊

We would be using the vue cli so if you do not have the vue cli installed you can install it by running this command in your terminal.

npm install -g @vue/cli

After installing the vue cli the next step would be to create our project which can be done by using the command:

vue create 'Name_Of_Your_Project'

You will be prompted to pick a preset. You can either choose the default preset which comes with a basic Babel + ESLint setup, or select “Manually select features” to pick the features you need.

For our case, we are going to select “Manually select features” and choose vue-router option and vuex since we will be using it during this tutorial. For the other features, do as you want, as it won’t really matter for the rest of the tutorial.You can choose multiple features by pressing space instead of enter , When you are done selecting feautures you can press enter.

choose router and vuex option

At the end, you will be asked if you want to save this preset for future projects and after that, your project will be initialized.

Then, enter the new ‘project name' directory, and run npm run serve

npm run serve

If and only if you couldn’t install either vuex or vue-router you can manually install it by running

npm install vuex --save

The above installation is for vuex and below is for vue-router

npm install vue-router

With that done we would be using vuetify for styling, to install vuetify run the command

$ vue add vuetify

Step Two: Firebase Integration

we would first be creating or setting up firebase which we would use as our back-end.

Create a new project on Firebase

To use Firebase, you first need to create a new project on the firebase console. If you don’t have any account created, create one, then go to console.firebase.google.com.

Firebase console

Click on Add project . Then you should have a popup to create a new project. Choose the name you want. You can call it what ever you want.

Create a new project

Then, you should arrive on your project home page.

project home page on Firebase

Congrats ! Your Firebase project is created. Now, to integrate it in our app, click on Add Firebase to your web app.

A popup with a code snippet should appear. Copy the code inside the second script balise. It should look like:

// Initialize Firebaselet config = {
apiKey: "YOUR_API_KEY",
authDomain: "YOUR_PROJECT_ID.firebaseapp.com",
databaseURL: "https://YOUR_PROJECT_ID.firebaseio.com",
projectId: "YOUR_PROJECT_ID",
storageBucket: "YOUR_PROJECT_ID.appspot.com",
messagingSenderId: "YOUR_MESSAGING_SEND_ID"
};firebase.initializeApp(config);

Now, let’s back to our vue project. We need to add the Firebase module to our project. To do so:

$ npm install ——save firebase

Once the installation is done, let’s import Firebase module to our app. Open the main.js file, and initialize Firebase with the configuration code we copied earlier.

import Vue from 'vue'import store from '@/store'import App from './App.vue'import vuetify from './plugins/vuetify';import router from './router'import firebase from 'firebase/app'import 'firebase/firestore'import 'firebase/auth'import Vuetify from 'vuetify'Vue.config.productionTip = false;Vue.use(Vuetify);new Vue({store,router,vuetify,render: h => h(App)}).$mount('#app')// Your web app's Firebase configurationvar firebaseConfig = {apiKey: "YOUR_API_KEY",
authDomain: "YOUR_PROJECT_ID.firebaseapp.com",
databaseURL: "https://YOUR_PROJECT_ID.firebaseio.com",
projectId: "YOUR_PROJECT_ID",
storageBucket: "YOUR_PROJECT_ID.appspot.com",
messagingSenderId: "YOUR_MESSAGING_SEND_ID"
};// Initialize Firebasefirebase.initializeApp(firebaseConfig);firebase.analytics();export const auth = firebase.auth(); //authenticationexport const db = firebase.firestore(); //firestore

Step three(creating the front end):

Now we would create a registration page which we would be using to collect data for our application. Since we already have vuetify installed we would be using vuetify for styling. Down here is the template for the registration page

<template><v-content><v-card max-width="600" class="mx-auto background"><v-container class="mt-12 pl-12 pr-12 pt-6 pb-12"><v-form ref="form" action="submit" @submit="reg" v-model="valid"><v-text-field :rules="nameRules" label="First Name" v-model="name" required></v-text-field><v-text-field :rules="nameRules" label="Email" v-model="email" required></v-text-field><v-autocomplete :items="gender" label="Gender" v-model="selectedGender" required></v-autocomplete><v-text-field:rules="passRules"label="password"v-model="password"type="password"required></v-text-field><v-flex><v-btn color="primary" :loading="loading" type="submit">register</v-btn></v-flex></v-form></v-container></v-card></v-content></template>

While down here is the script for the registration page.

<script>export default {name: "register",data: () => {return {
valid: false,
nameRules: [v => !!v || "Name is required"],
passRules: [v => !!v || "Password is required"],
name: "",
loading: false,
email: "",
selectedState: "",
selectedGender: "",
password: "",
gender: ["male", "female"]};},methods: {
reg(e) {
e.preventDefault();
}}};</script>

You must have noticed you cannot see your registration page you just created , well that’s cool.Now we would have to go into the router to write some code.In the code we would be writing we are trying to make the registration page the landing page.

import Vue from "vue";import Router from "vue-router";import register from './views/register.vue'import profile from './views/profile.vue'Vue.use(Router);const router = new Router({mode: "history",base: process.env.BASE_URL,routes: [{path: "/profile",component: profile,meta: {requiresAuth: false}},{path: "/",component: register,meta: {requiresAuth: false}}]});export default router;

3.2 Create User on Firebase with the SignUp component

Let’s go back to our Registration component and implement what we need to create users on Firebase.

To create a new user, we will need to get back the email and the password typed in our form inside our component controller. To do so, we are going to use the v-model directive of Vue 2.

You can use the v-model directive to create two-way data bindings on form input and textarea elements. It automatically picks the correct way to update the element based on the input type. Although a bit magical, v-model is essentially syntax sugar for updating data on user input events, plus special care for some edge cases.from Vue 2 documentation: https://vuejs.org/v2/guide/forms.html

Once we retrieved the email and the password of the new user we want to create, we are going to use the Firebase function called createUserWithEmailAndPassword.

This Firebase function does exactly what the name says, it create a new user with an email and a password. You can know more about this function in the official Firebase documentation here: https://firebase.google.com/docs/reference/js/firebase.auth.Auth#createUserWithEmailAndPassword

Let’s add all that in our Register component:

<script>import { auth } from './main'export default {name: "register",data: () => {return {valid: false,nameRules: [v => !!v || "Name is required"],passRules: [v => !!v || "Password is required"],name: "",loading: false,email: "",selectedGender: "",password: "",gender: ["male", "female"]};},methods: {reg(e) {e.preventDefault();this.loading = !this.loading;auth.createUserWithEmailAndPassword(this.email, this.password).then(result => {let vueApp = this; //because *this* is not available in the storethis.$store.dispatch("createUserProfile", {//createUserProfile is an action we are yet to activate //dispatch is used to activate actions. we are dispatching this values to the store actionsvueApp,user: result.user});});}}};</script>

We dispatched an action in the reg function . Actions are used to commit mutations while mutations are used to alter state.

Now lets get to our store. In the store folder generated by vue cli there exists an index.js file in it we would be writing the following code.

import Vue from "vue";import Vuex from "vuex";import firebase from "firebase/app";
import 'firebase/firestore'
Vue.use(Vuex);const store = new Vuex.Store({state: {currentUser: null,userProfile: null,},mutations: {setCurrentUser: (state, val) => {state.currentUser = val;},setUserProfile(state, val) {state.userProfile = val;}},actions: {createUserProfile({ commit }, { vueApp, user }) {//the students dataconst userData = {name: vueApp.name,gender: vueApp.selectedGender,email: vueApp.email,userId: user.uid};//adding to firestore collection and creating the gainsville //collection. PS: it creates by default if the collection does not //existdb.collection("users")
.doc()
.set(userData) // passing the user data to firestore
.then(() => {
commit("setUserProfile", userData); //commiting user data to the storevueApp.$router.push("/profile");}).catch((e) => {console.log(e)})},}});export default store;

After we dispatched the action createUserProfile in our registration component we wrote to our firestore database .

Now to spread the data we would be fetching the data from our database.

We would be using the onAuthStateChange function for this purpose. onAuthStateChange is the function used to get the currently signed in user.

Now we would update our store to look like this

import Vue from "vue";import Vuex from "vuex";
import firebase from "firebase/app";
import 'firebase/firestore'
Vue.use(Vuex);
auth.onAuthStateChanged(user => {
//if user exists commit setscurrentUser else null
user
? (async () => {
store.dispatch("getUserProfile", user.uid);
})(): null;});const store = new Vuex.Store({state: {currentUser: null,userProfile: null,},mutations: {setCurrentUser: (state, val) => {state.currentUser = val;},setUserProfile(state, val) {//mutations can carry two parameters //state and a payload in this case val is a payloadstate.userProfile = val;}},actions: {createUserProfile({ commit }, { vueApp, user }) {//the students dataconst userData = {name: vueApp.name,gender: vueApp.selectedGender,email: vueApp.email,userId: user.uid};//adding to firestore collection and creating the gainsville //collection. PS: it creates by default if the collection does not //existdb.collection("users")
.doc()
.set(userData) // passing the user data to firestore
.then(() => {
commit("setUserProfile", userData); //commiting user data to the //store
vueApp.$router.push("/profile");}).catch((e) => {//to handle errorsconsole.log(e)})},getUserProfile({ commit }, uid) {// the action for drawing the user
//from database
db.collection("users")//signifies the collection to be checked.where("userId", "==", uid) //checking if the userid is equal to the user id in firestore.get() //function to fetch the data from firestore.then(query => { //querying the databasequery.forEach(doc => {commit("setCurrentUser", doc.data()); //commiting the mutation //setCurrentUser mutations are used to alter state });});},}});export default store;

Since we are done with the lets get to the page where our informations are beign passed .

We would be starting with the template

<template><v-content><span class="border  mt-6"><div class="ml-6  bord">Surname: <span class="space"> {{ currentUser.name }}</span></div><v-divider></v-divider><div class="ml-6  bord">Gender: <span class="space">{{ currentUser.gender }} </span></div><v-divider></v-divider><div class="ml-6  bord">Mother's Name: <span class="space"> {{ currentUser.email }} </span></div></span></v-content></template>
<style scoped>
hr{margin-top: 10px;margin-bottom: 10px;}.space{margin-left: 5%;}</style>

The {{ }} is called interpolation it’s a way to insert values from an instance.

Next we would be writing the code for our script.

<script>
import { mapState } from "vuex";
export default {name: "Profile",computed: {...mapState(["currentUser"])// Used to get the current user from //state in store}};</script>

Summary:

Vuex has a single source of truth where informations to be used round the app is placed . This single source of truth is called state. Mutations are used to change or alter state in most cases it recieves two parameters state which is used to access state and payload which is commited from actions. Actions are used to commit mutations. In actions asynchronous operations can be carried out while in mutations it can’t.

Thanks for reading🙌😊

Eze Henry

Written by

Eze Henry

Javascript | Vue.js | vuetify | bootstrap | firebase | CSS | Vuepress . http://github.com/Godofjs

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade