9. Add Contacts

In this chapter, we will add, view, and delete contacts. You can add any user to your contact by entering their email address. Once that user is in your contact, you can send them a message. But the other person will not be able to receive your message until he adds you to his contact list too.

We will display all contacts in a <table> tag on the home page. And you will be able to delete any contact you want.

Video tutorial (add contacts):

Creating a HomeComponent

Create a file named “HomeComponent.vue” in your components folder. Then add it in your main.js file as the component for base route “/”.

import HomeComponent from "./components/HomeComponent.vue"

const routes = [
    { path: '/', component: HomeComponent },
    …
];

You will still see an empty page but now your home component is rendered correctly when you access your root path i.e. “/”.

Add Contact Router Link

Router links are used for page navigation. Just like we did for the login and registration page on the navbar, open your home component file and write the following code in it to create a router link to add a new contact:

<template>
    <div class="container">
        <div class="row">
            <div class="offset-md-10 col-md-2">
                <router-link class="btn btn-primary" to="/contacts/add">Add Contact</router-link>
            </div>
        </div>
    </div>
</template>

<script>
    
    export default {
        //
    }
</script>

Check the app now, and you will see an add contact button on right.

add contact router link
add a contact router link

On clicking that link, you will see an empty because we haven’t created a component and router for it.

Creating Add Contacts Component

Create a new file named “AddContactComponent.vue” in your components folder. And write the following code in that file:

<template>
	<div class="container">
		<div class="row">
            <div class="col-md-12">
                <h1 class="text-center text-white">Add Contact</h1>
            </div>
        </div>

		<div class="row">
			<div class="offset-md-3 col-md-6">
				<form method="POST">
					<div class="form-group">
						<label class="text-white">Name</label>
						<input type="text" name="name" class="form-control" required />
					</div>

					<div class="form-group" style="margin-top: 20px; margin-bottom: 30px;">
						<label class="text-white">E-mail</label>
						<input type="email" name="email" class="form-control" required />
					</div>

					<div class="d-grid gap-2">
						<input type="submit" class="btn btn-primary btn-block" value="Add Contact" />
					</div>
				</form>
			</div>
		</div>
	</div>
</template>

<script>

	export default {
		//
	}
</script>

And then add this component in your main.js routes array:

import AddContactComponent from "./components/AddContactComponent.vue"

const routes = [
    ...

    { path: "/contacts/add", component: AddContactComponent },
];

If you check the app now, you will see a nice form for adding a new contact.

add contact
add contact

You can set the name of your own choice. Just like your phone, you can save the contact with any name you want. And an email address. Now we need it to add the user in my contacts when I fill the form and hit the “Add Contact” button.

Calling an API to Add Contact

First, attach an event listener that will call a function when a user submits the form. You need to attach that event to your add contact <form> tag:

<form method="POST" v-on:submit.prevent="addContact">

Also, you need to show a “Loading…” text to the submit button while the AJAX is in progress. And you also need to disable that submit button so the user might not press that button twice.

You can replace your submit button with the following:

<input type="submit" class="btn btn-primary btn-block" v-bind:value="isLoading ? 'Adding...' : 'Add Contact'" v-bind:disabled="isLoading" />

Then you need to replace your <script> tag with the following:

<script>
	import axios from "axios"
	import swal from "sweetalert2"

	export default {
		data() {
			return {
				"isLoading": false
			}
		},

		methods: {
			addContact: async function () {
				const form = event.target;
				const formData = new FormData(form);

				this.isLoading = true;
				const response = await axios.post(
					this.$apiURL + "/contact/save",
					formData,
					{
						headers: this.$headers
					}
				);
				
				this.isLoading = false;
				swal.fire("Add Contact", response.data.message, response.data.status);

				if (response.data.status == "success") {
					form.reset()
				}
			}
		},
	}
</script>

Now we need to create an API that will handle this request.

Creating Route to Add Contacts

Coming back to our api folder. Create a new file named “contact.js” in your modules folder. Following will be the code of the contact.js file:

const auth = require("./auth");

module.exports = {

    init: function (app, express) {
        const router = express.Router();

        router.post("/save", auth, async function (request, result) {
            const name = request.fields.name;
            const email = request.fields.email;
            const user = request.user;

            const contactUser = await db.collection("users").findOne({
                email: email
            });

            if (contactUser == null) {
                result.json({
                    status: "error",
                    message: "User not found."
                });
                return;
            }

            const userContact = await db.collection("users").findOne({
                $and: [{
                    _id: user._id
                }, {
                    "contacts._id": contactUser._id
                }]
            });

            if (userContact != null) {
                result.json({
                    status: "error",
                    message: "Contact already exists."
                });
                return;
            }

            await db.collection("users").findOneAndUpdate({
                _id: user._id
            }, {
                $push: {
                    contacts: {
                        _id: contactUser._id,
                        name: name,
                        email: email,
                        unreadMessages: 0
                    }
                }
            });

            result.json({
                status: "success",
                message: "Contact has been saved."
            });
        });

        app.use("/contact", router);
    }
};

Here is what this module does:

  1. Include authentication middleware we created earlier.
  2. Export this module with all the functions and variables in it.
    1. 2.1. Note: We do not have any variables in this module, but if we create them, they will get exported too.
  3. Creating an init() a function that will accept express instance (app) and express module as parameters.
  4. Create a router instance from the express module.
  5. Create a POST route “/save” with this router. Here is what it does:
    1. Pass from authentication middleware.
    2. Get all values from add contact form.
    3. Check if the user you are trying to add in contact has registered on this app.
    4. Check if that contact is already on your contact list.
    5. Add the contact to your contacts array.
  1. The unreadMessages will be used later when we do the chat feature.
  2. And finally, we are telling the express instance “app” that we will be using this router for all the requests that start from “/contact”.

Don’t test the app now. It will not work. Because we haven’t told our Node JS server to use this “contact” module.

Using the Module

Now that we have created our module, we need to use it in our server.js file. Otherwise, it will have no effect on our app. Open your server.js file, first include that module before starting the HTTP server:

// custom modules
const contact = require("./modules/contact");

Then call the init() function after the Mongo DB connection is made:

contact.init(app, express);

Now you can test the app. Fill out the add contact form and hit the submit button. If the user is not registered, you will see an error. But you can create another account from the registration link and try again. If all goes well, you will see a nice pop-up alert saying that the user has been added to your contacts.

add contact success
add contact success

And if you refresh your Mongo DB Compass, and expand the “contacts” array of your user’s document, you will see that it has been added to your contact as well.

contacts array mongo db
contacts array mongo DB

But you won’t be seeing it in another user’s contact because he hasn’t added you yet.

If you go to the home page, you will not see the contacts. So now we need to create a component to display all our contacts on our home page in our next tutorial.