Build a Chat App with Vuejs and Firebase Realtime Database

Build a Chat App with Vuejs and Firebase Realtime Database


We will be looking at how we can use Firebase Realtime Database and Vuejs to build a chat app. Once users are signed in, we’ll learn how to store user chats in the Firebase Realtime database which allows our chat app to update in realtime. The client application is going to be built in Vue as it’s one of the popular JavaScript frameworks but the concepts can also be applied to other JavaScript frameworks. Let’s get started.

What is Firebase?

Firebase is Google’s mobile platform that helps you quickly develop high-quality apps and grow your business. Firebase provides a suite of tools for authenticating your applications, building reactive client apps, analytics, and a host of others for managing your apps. It allows you to manage your backend for web, iOS, Android, and unity.

Firebase Features

Out of the box, Firebase comes packages with features to make you focus on building your app while it handles all server-side logic.

  • Authentication: Firebase ships with authentication out of the box with support for email/password authentication as well as social sign-ups (Facebook, Twitter, Google)
  • Realtime database: a database that updates in realtime
  • Cloud functions: cloud functions to run extra server-side logic
  • Static Hosting: static hosting for web apps
  • Cloud Storage: a place to store media assets

Firebase gives a generous free tier for Authentication and the Realtime Database. Authentication is free for the authentication providers we’ll be covering (email/password, Google and GitHub). The Realtime database allows up to 100 simultaneous connections and 1-gigabyte storage/month. A full table of pricing can be found on the Firebase website.

Getting started

Run the command below to create a Vue project.

vue create vuechatapp

when you run the command below an option will be prompt to you to manually select. Select the default.

The command below will serve our app.

cd vuechatapp
npm run serve

Create a Firebase Project

Go to Firebase console and create a new project.

image

Afterward, enter your project name, accept the terms and condition and click on create a project button.

Once the project is done, you’ll see your admin dashboard. Click project overview > project settings > add app. click on add app button, and fill in the necessary details and your firebase credentials will appear.

image

Copy it and create a fire.js file and past it there just as i have done.

import firebase from "firebase";
import "firebase/firestore";

var config = {
  apiKey: "your_key",
  authDomain: "your_project.firebaseapp.com",
  databaseURL: "https://your_project.firebaseio.com",
  projectId: "your_project",
  storageBucket: "your_project.appspot.com",
  messagingSenderId: "your_message_sending_id",
};

var fire = firebase.initializeApp(config);
export default fire;

Run the code below to connect firebase with our app.

npm install firebase

Building the App

In this project, we are going to work with App.vue component only. We won’t be creating any other component. We are going to start by creating a User sign-in page. Open App.vue and write the code below.

// Html stays here
<template>
  <div id="app">
   <!-- Login section -->
   <div class="login mt-5" v-if="!name">
    <h3 class="mt-5">Join Chat</h3>
    <label for="username">userName</label>
    <br />
    <input class="mb-3" type="text" v-model="userName" />
    <br />
    <button class="btn btn-primary" @click="updateUsername">Join Chat</button>
   </div>
   
  <div class="message-body mt-3" v-else>
      <h3>Chat</h3>
      <h5>Welcome {{ name }}!</h5>
     ...........
    </div>
 <div>
</template>

// all script stays here
<script>

</script>

// all style stays here
<style>

</style>

If we look closely, the above code is divided into three sections. The <template> , <script>, and <style>.

In the template, we can only have one parent div element or any other HTML elements but it must be one. If you add another one it throws an error.

We have a div element with an id="app" inside the template, and another div element with a class="login" inside the parent element.

In the login div element, we have an input tag, label, and a button tag and we have also bind v-if="!userName" attribute to the login div that says if no username, user can not chat.

In the input tag we bind v-model to get the value when a user types.

In the button, we bind @click event listener to a method named updateUsername() and we defined the method in our Vue instance. The method submits the value after the user is done and clicks the submits button.

// all script stays here
<script>
import fire from "./fire";
export default {
  name: "App",
  data() {
    return {
      userName: "",
      name: null,
    };
  },
  methods: {
    updateUsername() {
      this.name = this.userName;
      console.log(this.userName);
      this.userName = "";
    },
 }
}
</script>

In the <script> tag, we imported fire from fire.js file that hold the firebase configuration codes.

A data:{} property that returns a name and userName.

A methods:{} that hold the updateUsername() function.

<style>
@import url("https://fonts.googleapis.com/css?family=Roboto:300,400,500,700,400italic|Material+Icons");
#app {
  font-family: "Roboto", sans-serif;
  font-size: 18px;
}
.login {
  background: #fff;
  width: 40%;
  height: 50vh;
  margin: auto;
  padding-left: 20px;
  padding-right: 20px;
}
h3 {
  font-size: 30px;
  text-align: center;
}
input {
  width: 100%;
  border-radius: 4px;
  border: 1px solid rgb(156, 156, 156);
  padding-left: 2px;
  padding-right: 2px;
}
.message-body {
  width: 40%;
  height: 80vh;
  margin: auto;
}
.message-text {
  min-width: 10%;
  border-radius: 4px;
}
.message {
  font-size: 14px;
}
.mg-text {
  color: rgb(0, 195, 255);
  font-weight: bolder;
}
.message-body input {
  width: 80%;
  border-radius: 4px;
  border: 1px solid rgb(156, 156, 156);
  height: 6vh;
  padding-left: 2px;
  padding-right: 2px;
}
.card {
  width: 100%;
  height: 75vh;
  margin: auto;
}
.card-body {
  min-height: 50vh;
  overflow-x: scroll;
}
</style>

In the <style>, we added some styling to make the login page look fine.

If we type in our user name and we click join chat the login page we be out and we will see another page just like the picture below.

Now we want user to send a message.

In the <template> add this code below:

<template>
  <div id="app">
    <!-- Login section -->
    <div class="login mt-5" v-if="!name">
     ..................
    </div>

    <!-- Chat section -->
    <div class="message-body mt-3" v-else>
      <h3>Chat</h3>
      <h5>Welcome {{ name }}!</h5>
      <div class="card">
        <div class="card-body">
          <div
            class="border pl-2 pt-1 ml-2 message-text mb-2"
            v-for="message in messages"
            :key="message"
          >
            <span class="mg-text">{{ message.username }}</span>
            <p class="message pt-1">{{ message.text }}</p>
          </div>
        </div>
      </div>
      <input v-model="showMessage" type="text" class="mt-3 mr-2 pl-2 pr-2" />
      <button class="btn btn-primary" @click="sendMessage">Send</button>
    </div>
  </div>
</template>

In the above code, the div with card-body is where we are going to display the message once the user sends a message and we used the v-for directive to loop through the data and display the responses using data binding.

We also bind @click event listener to a method named sendMessage(), the method takes the value a user types and send it the serve.

<script>
import fire from "./fire";
export default {
  name: "App",
  data() {
    return {
      userName: "",
      name: null,
      showMessage: "",
      messages: []
    };
  },
  methods: {
    updateUsername() {
      this.name = this.userName;
      console.log(this.userName);
      this.userName = "";
    },
    sendMessage() {
      const message = {
        text: this.showMessage,
        username: this.name
      };
      fire
        .database()
        .ref("messages")
        .push(message);
      this.showMessage = "";
    }
  },
  mounted() {
    let viewMessage = this;
    const itemsRef = fire.database().ref("messages");
    itemsRef.on("value", snapshot => {
      let data = snapshot.val();
      let messages = [];
      Object.keys(data).forEach(key => {
        messages.push({
          id: key,
          username: data[key].username,
          text: data[key].text
        });
      });
      viewMessage.messages = messages;
    });
  }
};
</script>

In the <script> section, we define the sendMessage() method, the function takes the value user types and sends it to the firebase. We created ref path messages, the messages is what holds the value we push to firebase.

In the mounted:{} we only return the data we send to firebase as an object and then we render it to the DOM.

If user types a message and send it, it displays the message just as the image below.

conclusion

It was a great tutorial and we were able to understand the concepts behind building a chat app and you are free to add more functionalities.

The source code can be found on Github


Share on social media

//