Open In App

Address Book using MEAN

Last Updated : 18 Apr, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

It is important to have an efficient way to manage contacts for personal and professional life. Building an address book application can be a rewarding project, allowing you to learn the ins and outs of full-stack web development while creating a useful tool. In this article, we’ll explore how to build an address book application using the MEAN stack, comprising MongoDB, Express.js, Angular, and Node.js.

Project Preview:

preview image of address book using mean

PREVIEW IMAGE FOR CREATE ADDRESS

Prerequisites:

Approach to Create Address Book using MEAN Stack

Backend:

  • Set up a new node js project
  • Set up the server using express with CORS as the middleware in file server.js
  • Create the app instance using const app = express()
  • Create controllers folder which will define the API methods
  • Create models folder to create the database schema for address-book and user
  • Create router folder and mention all the routes related to user login, register, creating, retrieving, updating and deleting the address in an address book
  • Set up local Mongo DB database
  • Set up the connection to local Mongo DB in server.js file
  • Create collections within the database to store and retrieve the data from database
  • Two collections are created – address-book, user
  • Implement the core logic of creating, retrieving, updating and deleting the address
  • Test the API endpoints using postman

Frontend:

  • Create a new angular project
  • Create components folder and seperate components for seperate routes
  • Create HTML, CSS and ts files for all the components
  • Create service to establish communication between frontend and backend routes
  • Create various routes in app.routes.ts folder
  • Test the frontend application in browser at https://localhost:3000

Steps to Create Project

Step 1: Create the main folder for complete project

mkdir address-book
cd address-book

Step 2: Initialize the node.js project

npm init -y

Step 3: Install the required dependencies

npm install express mongoose jsonwebtoken bcryptjs nodemon cors body-parser

Folder Structure (Backend):

Screenshot-2024-04-15-080820

PROJECT STRUCTURE IMAGE FOR BACKEND

The updated dependencies in package.json file of backend will look like:

"dependencies": {
"@auth0/angular-jwt": "^5.2.0",
"bcryptjs": "^2.4.3",
"body-parser": "^1.20.2",
"cors": "^2.8.5",
"express": "^4.19.2",
"jsonwebtoken": "^9.0.2",
"mongoose": "^8.3.0",
"nodemon": "^3.1.0"
}

Example: Create the required files as seen on the project structure and add the following codes.

Node
// controller/addressController.js

const Address = require("../model/Address");
const jwt = require("jsonwebtoken");
const secretKey = "jwtSecret";

exports.getAllAddress = async (req, res) => {
    let userId;
    try {
        jwt.verify(
            req.headers["authorization"].substring(7),
            secretKey,
            (error, decodedToken) => {
                if (error) {
                    res.status(401).json({
                        success: false,
                        message: error.message,
                    });
                } else {
                    userId = decodedToken.user.id;
                }
            }
        );
        const addresses = await Address.find();
        res.status(200).json(addresses);
    } catch (error) {
        res.status(500).json({
            success: false,
            message: error.message,
        });
    }
};

exports.getAddressById = async (req, res) => {
    try {
        const id = req.params.id;
        const address = await Address.findById(id);
        res.status(200).json(address);
    } catch (error) {
        res.status(500).json({
            success: false,
            message: error.message,
        });
    }
};

exports.createAddress = async (req, res) => {
    try {
        let address = {};
        const {
            firstname,
            lastname,
            email,
            phone,
            addressline,
            state,
            pincode,
            country,
            dob,
        } = req.body;
        if (
            req.headers["authorization"] &&
            req.headers["authorization"].startsWith("Bearer ")
        ) {
            jwt.verify(
                req.headers["authorization"].substring(7),
                secretKey,
                (error, decodedToken) => {
                    if (error) {
                        res.status(401).json({
                            success: false,
                            message: error.message,
                        });
                    } else {
                        address = new Address({
                            user: decodedToken.user.id,
                            firstname,
                            lastname,
                            email,
                            phone,
                            addressline,
                            state,
                            pincode,
                            country,
                            dob,
                        });
                    }
                }
            );
            await address.save();
            res.status(200).json({
                success: true,
                address: address,
            });
        }
    } catch (error) {
        res.status(500).json({
            success: false,
            message: error.message,
        });
    }
};

exports.updateAddress = async (req, res) => {
    try {
        const { id } = req.params;
        const {
            firstname,
            lastname,
            email,
            phone,
            addressline,
            state,
            pincode,
            country,
            dob,
        } = req.body;
        const address = await Address.findByIdAndUpdate(
            id,
            {
                firstname,
                lastname,
                email,
                phone,
                addressline,
                state,
                pincode,
                country,
                dob,
            },
            { new: true }
        );
        res.status(201).json({
            success: true,
            address: address,
        });
    } catch (error) {
        res.status(500).json({
            success: false,
            message: error.message,
        });
    }
};

exports.deleteAddress = async (req, res) => {
    try {
        const { id } = req.params;
        await Address.findByIdAndDelete(id);
        res.status(200).json({
            success: true,
            message: "Address Deleted Successfully",
        });
    } catch (error) {
        res.status(500).json({
            success: false,
            message: "Error while deleting address",
        });
    }
};
Node
// controller/authController.js

const User = require("../model/User");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");

exports.register = async (req, res) => {
    try {
        const { username, email, password } = req.body;
        let user = await User.findOne({ email });
        if (user) {
            return res.status(400).json({
                message: "User Already Exist",
                success: false,
            });
        }
        user = new User({
            username: username,
            email: email,
            password: password,
        });
        const salt = await bcrypt.genSalt(10);
        user.password = await bcrypt.hash(password, salt);
        await user.save();
        const token = generateJwtToken(user.id);
        res.status(201).json({
            success: true,
            token: token,
            message: "User registered successfully",
        });
    } catch (error) {
        res.status(500).json({
            message: "Server error! New user registration failed",
            success: false,
        });
    }
};

exports.login = async (req, res) => {
    try {
        const { email, password } = req.body;
        const user = await User.findOne({ email });
        if (!user) {
            return res.status(400).json({
                message: "Invalid credentials",
                success: false,
            });
        }
        const isMatched = await bcrypt.compare(password, user.password);
        if (!isMatched) {
            return res.status(400).json({
                message: "Invalid credentials",
                success: false,
            });
        }
        const token = generateJwtToken(user.id);
        res.status(200).json({
            success: true,
            message: "User logged in successfully",
            token: token,
        });
    } catch (error) {
        return res.status(500).json({
            success: false,
            message: "Internal Server Error, Login unsuccessful",
        });
    }
};

function generateJwtToken(userID) {
    const payload = {
        user: {
            id: userID,
        },
    };
    return jwt.sign(payload, "jwtSecret", { expiresIn: 3600 });
}

exports.getUserDetailsFronUserId = async (req, res) => {
    try {
        const { id } = req.params;
        const user = await User.findById(id);
        return res.status(200).json(user);
    } catch (error) {
        res.status(500).json({
            success: false,
            message: error.message,
        });
    }
};
Node
// model/Address.js

const mongoose = require('mongoose');

const addressSchema = new mongoose.Schema({
    user: {
        type: mongoose.Schema.ObjectId,
        ref: "User",
        required: true
    },
    firstname: {
        type: String,
        required: true
    },
    lastname: {
        type: String,
        required: true
    },
    email: {
        type: String,
        required: true
    },
    phone: {
        type: String,
        required: true
    },
    addressline: {
        type: String,
        required: true
    },
    state: {
        type: String,
        required: true
    },
    pincode: {
        type: String,
        required: true
    },
    country: {
        type: String,
        required: true
    },
    dob: {
        type: Date,
        required: true
    }
});

module.exports = mongoose.model('Address', addressSchema);
Node
// model/User.js

const mongoose = require('mongoose');

const userSchema = new mongoose.Schema({
    username: {
        type: String,
        required: true
    },
    email: {
        type: String,
        required: true,
        uniques: true
    },
    password: {
        type: String,
        required: true
    }
});

module.exports = mongoose.model('User', userSchema);
Node
// route/addressRoutes.js

const express = require("express");
const router = express.Router();
const addressController = require("../controller/addressController");

router.get("/getAllAddress", addressController.getAllAddress);

router.get("/getAddressById/:id", addressController.getAddressById);

router.post("/createAddress", addressController.createAddress);

router.put("/updateAddress/:id", addressController.updateAddress);

router.delete("/deleteAddress/:id", addressController.deleteAddress);

module.exports = router;
Node
//route/authRoutes.js

const express = require("express");
const router = express.Router();
const authController = require("../controller/authController");

router.post("/register", authController.register);

router.post("/login", authController.login);

router.get("/:id", authController.getUserDetailsFronUserId);

module.exports = router;
Node
// server.js

const express = require("express");
const cors = require("cors");
const mongoose = require("mongoose");
const authRoutes = require("../backend/route/authRoutes");
const addressRoutes = require("../backend/route/addressRoutes");

const app = express();
app.use(cors());
app.use(express.json());

mongoose
    .connect("mongodb://localhost:27017/address-book", {
        family: 4,
    })
    .then(() => console.log("Mongo DB connected"))
    .catch((err) => console.log(err));

app.use("/api/auth", authRoutes);
app.use("/api/address", addressRoutes);

const PORT = 5000;
app.listen(PORT, () => console.log(`Server started on port ${PORT}`));

Step 4: To start the backend run the following command.

nodemon server.js

Step 5: Install the angular CLI

npm install -g @angular/cli

Step 6: Create a new angular project

ng new frontend

Step 7: Create components for different functionalities in angular

Syntax - ng generate component <component-name>
ng generate component user
ng generate component address-create
ng generate component address

Step 8: Create services for communication between frontend and backend

Syntax - ng generate service <service-name>
ng generate service auth
ng generate service address
ng generate service shared

Folder Structure(Frontend):

Screenshot-2024-04-15-081600

PROJECT STRUCTURE FOR FRONTEND

The updated dependencies in package.json file of frontend will look like:

"dependencies": {
"@angular/animations": "^17.2.0",
"@angular/common": "^17.2.0",
"@angular/compiler": "^17.2.0",
"@angular/core": "^17.2.0",
"@angular/forms": "^17.2.0",
"@angular/platform-browser": "^17.2.0",
"@angular/platform-browser-dynamic": "^17.2.0",
"@angular/platform-server": "^17.2.0",
"@angular/router": "^17.2.0",
"@angular/ssr": "^17.2.3",
"@auth0/angular-jwt": "^5.2.0",
"express": "^4.18.2",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"zone.js": "~0.14.3"
}

Example: Create the required files as seen in project structure and add the following codes.

HTML
<!-- address.compoennt.html -->

<div class="container">
  <a class="link-button" (click)="showAddFormFunction()">Create New Address</a>
  <h2>List of Address</h2>
  <div
    *ngIf="displayedAddressList.length > 0; else noAddress"
    class="table-container"
  >
    <table class="address-table">
      <thead>
        <tr>
          <th>First Name</th>
          <th>Last Name</th>
          <th>Email ID</th>
          <th>Phone</th>
          <th>Address Line</th>
          <th>State</th>
          <th>PIN Code</th>
          <th>Country</th>
          <th>Date of Birth</th>
          <th>Actions</th>
        </tr>
      </thead>
      <tbody>
        <tr *ngFor="let address of displayedAddressList">
          <td>{{ address.firstname }}</td>
          <td>{{ address.lastname }}</td>
          <td>{{ address.email }}</td>
          <td>{{ address.phone }}</td>
          <td>{{ address.addressline }}</td>
          <td>{{ address.state }}</td>
          <td>{{ address.pincode }}</td>
          <td>{{ address.country }}</td>
          <td>{{ address.dob }}</td>
          <td>
            <button class="btn" (click)="getAddressById(address._id)">
              Get Adress
            </button>
            <button
              class="btn"
              (click)="populateUpdateForm(address)"
              *ngIf="address.user === getUserId()"
            >
              Update
            </button>
            <button
              class="btn delete-btn"
              (click)="confirmDelete(address._id)"
              *ngIf="address.user === getUserId()"
            >
              Delete
            </button>
          </td>
        </tr>
      </tbody>
    </table>
  </div>

  <ng-template #noAddress>
    <div class="no-address-container">
      <p>No Address Available</p>
    </div>
  </ng-template>

  <div *ngIf="showUpdateForm" class="update-form-container">
    <button class="close-button" (click)="cancelUpdate()">X</button>
    <h2>Update Address</h2>
    <form class="update-form" (ngSubmit)="updateAddress(addressUpdated._id)">
      <div>
        <label for="updateFirstName">First Name:</label>
        <input
          type="text"
          id="updateFirstName"
          name="updateFirstName"
          [(ngModel)]="addressUpdated.firstname"
          required
        />
      </div>
      <div>
        <label for="updateLastName">Last Name:</label>
        <input
          type="text"
          id="updateLastName"
          name="updateLastName"
          [(ngModel)]="addressUpdated.lastname"
          required
        />
      </div>
      <div>
        <label for="updateEmail">Email ID:</label>
        <input
          type="email"
          id="updateEmail"
          name="updateEmail"
          [(ngModel)]="addressUpdated.email"
          required
        />
      </div>
      <div>
        <label for="updatePhone">Phone Number:</label>
        <input
          type="number"
          id="updatePhone"
          name="updatePhone"
          [(ngModel)]="addressUpdated.phone"
          required
        />
      </div>
      <div>
        <label for="updateAddressLine">Address Line:</label>
        <input
          type="text"
          id="updateAddressLine"
          name="updateAddressLine"
          [(ngModel)]="addressUpdated.addressline"
          required
        />
      </div>
      <div>
        <label for="updateState">Address Line:</label>
        <input
          type="text"
          id="updateState"
          name="updateState"
          [(ngModel)]="addressUpdated.state"
          required
        />
      </div>
      <div>
        <label for="updatePincode">Address Line:</label>
        <input
          type="number"
          id="updatePincode"
          name="updatePincode"
          [(ngModel)]="addressUpdated.pincode"
          required
        />
      </div>
      <div>
        <label for="updateCountry">Address Line:</label>
        <input
          type="text"
          id="updateCountry"
          name="updateCountry"
          [(ngModel)]="addressUpdated.country"
          required
        />
      </div>
      <div>
        <label for="updateDOB">Date Of Birth:</label>
        <input
          type="date"
          id="updateDOB"
          name="updateDOB"
          [(ngModel)]="addressUpdated.dob"
          required
        />
      </div>
      <div>
        <button type="submit">Update Address</button>
        <button type="button" (click)="cancelUpdate()">Cancel</button>
      </div>
    </form>
  </div>

  <div
    *ngIf="!showUpdateForm && addressById._id"
    class="view-address-container"
  >
    <button class="close-button" (click)="closeView()">X</button>
    <h2>View Address</h2>
    <form class="view-address-form">
      <div>
        <label for="viewFirstName">First Name:</label>
        <input
          type="text"
          id="viewFirstName"
          name="viewFirstName"
          [(ngModel)]="addressById.firstname"
          required
        />
      </div>
      <div>
        <label for="viewLastName">Last Name:</label>
        <input
          type="text"
          id="viewLastName"
          name="viewLastName"
          [(ngModel)]="addressById.lastname"
          required
        />
      </div>
      <div>
        <label for="viewEmail">Email ID:</label>
        <input
          type="email"
          id="viewEmail"
          name="viewEmail"
          [(ngModel)]="addressById.email"
          required
        />
      </div>
      <div>
        <label for="viewPhone">Phone Number:</label>
        <input
          type="number"
          id="viewPhone"
          name="viewPhone"
          [(ngModel)]="addressById.phone"
          required
        />
      </div>
      <div>
        <label for="viewAddressLine">Address Line:</label>
        <input
          type="text"
          id="viewAddressLine"
          name="viewAddressLine"
          [(ngModel)]="addressById.addressline"
          required
        />
      </div>
      <div>
        <label for="viewState">State:</label>
        <input
          type="text"
          id="viewState"
          name="viewState"
          [(ngModel)]="addressById.state"
          required
        />
      </div>
      <div>
        <label for="viewPincode">PIN Code:</label>
        <input
          type="text"
          id="viewPincode"
          name="viewPincode"
          [(ngModel)]="addressById.pincode"
          required
        />
      </div>
      <div>
        <label for="viewCountry">Country:</label>
        <input
          type="text"
          id="viewCountry"
          name="viewCountry"
          [(ngModel)]="addressById.country"
          required
        />
      </div>
      <div>
        <label for="viewDOB">Date Of Birth:</label>
        <input
          type="date"
          id="viewDOB"
          name="viewDOB"
          [(ngModel)]="addressById.dob"
          required
        />
      </div>
      <div>
        <a href="/getAllAddress" class="link-button" (click)="closeView()"
          >Get All Address</a
        >
      </div>
    </form>
  </div>
</div>
HTML
<!-- address-create.compoentn.html -->

<div class="container">
  <div class="create-form-container">
    <h2>Create New Address</h2>
    <form class="create-form" (ngSubmit)="createAddress()">
      <div>
        <label for="firstName">First Name:</label>
        <input
          type="text"
          id="firstName"
          name="firstName"
          [(ngModel)]="addressCreated.firstname"
          required
        />
      </div>
      <div>
        <label for="lastName">Last Name:</label>
        <input
          type="text"
          id="lastName"
          name="lastName"
          [(ngModel)]="addressCreated.lastname"
          required
        />
      </div>
      <div>
        <label for="email">Email:</label>
        <input
          type="email"
          id="email"
          name="email"
          [(ngModel)]="addressCreated.email"
          required
        />
      </div>
      <div>
        <label for="phone">Phone:</label>
        <input
          type="number"
          id="phone"
          name="phone"
          [(ngModel)]="addressCreated.phone"
          required
        />
      </div>
      <div>
        <label for="addressLine">Address Line:</label>
        <input
          type="text"
          id="addressLine"
          name="addressLine"
          [(ngModel)]="addressCreated.addressline"
          required
        />
      </div>
      <div>
        <label for="state">State:</label>
        <input
          type="text"
          id="state"
          name="state"
          [(ngModel)]="addressCreated.state"
          required
        />
      </div>
      <div>
        <label for="pinCode">PIN Code:</label>
        <input
          type="number"
          id="pinCode"
          name="pinCode"
          [(ngModel)]="addressCreated.pincode"
          required
        />
      </div>
      <div>
        <label for="country">Country:</label>
        <input
          type="text"
          id="country"
          name="country"
          [(ngModel)]="addressCreated.country"
          required
        />
      </div>
      <div>
        <label for="dob">Date Of Birth:</label>
        <input
          type="date"
          id="dob"
          name="dob"
          [(ngModel)]="addressCreated.dob"
          required
        />
      </div>
      <div>
        <button type="submit">Add Address</button>
        <button type="button" (click)="resetForm()">Clear</button>
        <a href="/getAllAddress" class="link-button">Get All Address</a>
      </div>
    </form>
  </div>
</div>
HTML
<!-- user.component.hmtl -->

<div class="error-message" *ngIf="errorMessage">{{ errorMessage }}</div>
<div class="success-message" *ngIf="successMessage">{{ successMessage }}</div>

<div class="container" *ngIf="loginActive">
  <h2>Login</h2>
  <form (ngSubmit)="login()">
    <div class="form-group">
      <label for="email">Email:</label>
      <input
        type="email"
        class="form-control"
        id="email"
        name="email"
        [(ngModel)]="email"
        required
      />
    </div>
    <div class="form-group">
      <label for="password">Password:</label>
      <input
        type="password"
        class="form-control"
        id="password"
        name="password"
        [(ngModel)]="password"
        required
      />
    </div>
    <button type="submit" class="btn btn-primary">Login</button>
  </form>
</div>
<div class="container" *ngIf="registerActive">
  <h2>Register</h2>
  <form (submit)="register()">
    <div class="form-group">
      <label for="username">Username</label>
      <input
        type="text"
        id="username"
        class="form-control"
        [(ngModel)]="username"
        name="username"
        required
      />
    </div>
    <div class="form-group">
      <label for="email">Email</label>
      <input
        type="email"
        id="email"
        class="form-control"
        [(ngModel)]="email"
        name="email"
        required
      />
    </div>
    <div class="form-group">
      <label for="password">Password</label>
      <input
        type="password"
        id="password"
        class="form-control"
        [(ngModel)]="password"
        name="password"
        required
      />
    </div>
    <button type="submit" class="btn btn-primary">Register</button>
  </form>
</div>
HTML
<!-- app.component.html -->

<main class="main">
  <div class="content">
    <div class="left-side">
      <h1>{{ title }}</h1>
      <div>
        <ul>
          <li><a (click)="login()" *ngIf="!isLoggedIn">Login</a></li>
          <li><a (click)="register()" *ngIf="!isLoggedIn">Register</a></li>
          <li><a (click)="logout()" *ngIf="isLoggedIn">Logout</a></li>
        </ul>
      </div>
    </div>
  </div>
</main>
<router-outlet> </router-outlet>
CSS
/* app.component.css */

.main {
    display: flex;
    flex-direction: column;
    align-items: center;
    background-color: darkslategrey;
    color: white;
}

.content {
    width: 100%;
    max-width: 1200px;
    padding: 20px;
}

.left-side {
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.left-side h1 {
    margin: 0;
    margin-left: 3%;
}

.left-side ul {
    list-style-type: none;
    padding: 0;
    margin: 0;
}

.left-side li {
    display: inline;
    margin-right: 20px;
}

.left-side li a {
    text-decoration: none;
    color: white;
    font-weight: bold;
    font-size: 1.5rem;
}

.left-side li a:hover {
    color: lightgray;
}

a {
    cursor: pointer;
}
CSS
/* address.component.css */

.container {
    max-width: 100%;
    margin: 0 auto;
    padding: 20px;
}

.address-table {
    width: 100%;
    border-collapse: collapse;
}

.address-table th,
.address-table td {
    padding: 10px;
    border: 1px solid #ccc;
    text-align: center;
}

h2 {
    text-align: center;
}

.address-table th {
    background-color: #f0f0f0;
}

.update-form-container,
.view-address-container {
    margin-top: 20px;
    padding: 20px;
    border: 1px solid #ccc;
}

.update-form,
.view-address-form {
    display: flex;
    flex-direction: column;
}

.update-form input,
.view-address-form input {
    margin-bottom: 10px;
}

.btn {
    padding: 8px 16px;
    margin-right: 10px;
    margin-bottom: 1.5vmax;
    cursor: pointer;
    background-color: #0056b3;
    color: #fff;
    border: none;
    border-radius: 4px;
}

.delete-btn {
    background-color: #dc3545;
}

.link-button {
    display: inline-block;
    padding: 8px 16px;
    background-color: #1b599a;
    color: #fff;
    text-decoration: none;
    border-radius: 4px;
    cursor: pointer;
}

.link-button-clear {
    display: inline-block;
    padding: 8px 16px;
    background-color: #dc3545;
    color: #fff;
    text-decoration: none;
    border-radius: 4px;
    cursor: pointer;
    border: none;
}

.no-address-container {
    margin-top: 20px;
    padding: 10px;
    background-color: #f8d7da;
    color: #721c24;
    border: 1px solid #f5c6cb;
    border-radius: 4px;
}

.no-address-container p {
    text-align: center;
    margin: 0;
}

/* Update Activity */

.update-form-container {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 90%;
    background-color: rgba(255, 255, 255, 1);
    padding: 3vmax;
    border-radius: 5px;
    overflow-y: auto;
}

.update-form-container h2 {
    text-align: center;
    font-size: 2rem;
}

.update-form-container .close-btn {
    position: absolute;
    top: 15px;
    right: 5px;
    font-size: 18px;
    color: #555;
    cursor: pointer;
}

.update-form-container .close-btn:hover {
    color: #333;
}

.update-form label {
    display: block;
    margin-bottom: 5px;
}

.update-form input[type="text"],
.update-form input[type="number"],
.update-form input[type="date"],
.update-form input[type="email"] {
    width: calc(100% - 12px);
    padding: 10px;
    margin-bottom: 10px;
    border: 1px solid #ccc;
    border-radius: 5px;
}

.update-form button[type="submit"],
.update-form button[type="button"] {
    width: 10%;
    padding: 10px;
    background-color: green;
    color: #fff;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    margin-right: 10px;
}

.update-form button[type="button"] {
    background-color: #dc3545;
}

.view-address-container {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 90%;
    background-color: rgba(255, 255, 255, 1);
    padding: 3vmax;
    border-radius: 5px;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}

.view-address-container h2 {
    text-align: center;
    font-size: 2rem;
}

.view-address-form label {
    display: block;
    margin-bottom: 5px;
}

.view-address-form input[type="text"],
.view-address-form input[type="number"],
.view-address-form input[type="date"],
.view-address-form input[type="email"] {
    width: calc(100% - 12px);
    padding: 10px;
    margin-bottom: 10px;
    border: 1px solid #ccc;
    border-radius: 5px;
}

.view-address-form button[type="submit"],
.view-address-form a {
    width: 10%;
    padding: 10px;
    background-color: #0056b3;
    color: #fff;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    text-align: center;
    display: inline-block;
    text-decoration: none;
}

.close-button {
    position: absolute;
    top: 20px;
    right: 10px;
    padding: 5px 10px;
    background-color: #ccc;
    border: none;
    border-radius: 5px;
    cursor: pointer;
}

.close-button:hover {
    background-color: #aaa;
}
CSS
/* address-create.component.css */

.container {
    max-width: 100%;
    margin: 0 auto;
    padding: 20px;
}

.create-form-container {
    width: 90%;
    background-color: rgba(255, 255, 255, 1);
    border-radius: 5px;
    margin: 10px auto;
}

.create-form-container h2 {
    text-align: center;
    font-size: 2rem;
}

.create-form-container {
    color: #333;
}

.create-form label {
    display: block;
    margin-bottom: 5px;
}

.create-form input[type="text"],
.create-form input[type="number"],
.create-form input[type="date"],
.create-form input[type="email"] {
    width: calc(100% - 12px);
    padding: 10px;
    margin-bottom: 10px;
    border: 1px solid #ccc;
    border-radius: 5px;
}

.create-form button[type="submit"],
.create-form button[type="button"] {
    width: auto;
    padding: 10px 20px;
    background-color: green;
    color: #fff;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    margin-right: 10px;
}

.create-form button[type="button"] {
    background-color: #dc3545;
}

.create-form a {
    width: 10%;
    padding: 10px;
    background-color: #0056b3;
    color: #fff;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    text-align: center;
    display: inline-block;
    text-decoration: none;
}
CSS
/* user.component.css */

.container {
    width: 50%;
    margin: 2rem auto;
    padding: 1.5vmax;
    padding-right: 2.5vmax;
    border: 1px solid #ccc;
    border-radius: 5px;
}

h2 {
    text-align: center;
    margin-bottom: 20px;
    font-size: 2rem;
}

.form-group {
    margin-bottom: 20px;
}

label {
    display: block;
    margin-bottom: 5px;
}

input[type="text"],
input[type="email"],
input[type="password"] {
    width: 97%;
    padding: 10px;
    border: 1px solid #ccc;
    border-radius: 5px;
}

button[type="submit"] {
    width: 20%;
    padding: 1.1vmax;
    background-color: #0056b3;
    color: #fff;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    font-weight: bold;
    font-size: 1rem;
    align-self: center;
    margin-top: 1vmax;
}

.container {
    width: 50%;
    margin: 2rem auto;
    padding: 1.5vmax;
    padding-right: 3.5vmax;
    border: 1px solid #ccc;
    border-radius: 5px;
}

h2 {
    text-align: center;
    margin-bottom: 20px;
    font-size: 2rem;
}

.form-group {
    margin-bottom: 20px;
}

label {
    display: block;
    margin-bottom: 5px;
}

input[type="email"],
input[type="password"] {
    width: 99%;
    padding: 10px;
    border: 1px solid #ccc;
    border-radius: 5px;
}

button[type="submit"] {
    width: 20%;
    padding: 1.1vmax;
    background-color: #0056b3;
    color: #fff;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    font-weight: bold;
    font-size: 1rem;
    align-self: center;
    margin-top: 1vmax;
}

.error-message {
    color: #FF0000;
    background-color: #FFEFEF;
    padding: 10px;
    border: 1px solid #FF0000;
    border-radius: 5px;
    margin-bottom: 10px;
    margin-top: 10px;
}

.success-message {
    color: green;
    background-color: rgb(186, 218, 186);
    padding: 10px;
    border: 1px solid green;
    border-radius: 5px;
    margin-bottom: 10px;
    margin-top: 10px;
}
JavaScript
// Address.component.ts

import { Component, OnInit } from "@angular/core";
import { AddressService } from "../address.service";
import { AuthService } from "../auth.service";
import { Router } from "@angular/router";
import { SharedService } from "../shared.service";
import { FormsModule } from "@angular/forms";
import { CommonModule } from "@angular/common";

@Component({
    selector: "app-address",
    standalone: true,
    imports: [FormsModule, CommonModule],
    templateUrl: "./address.component.html",
    styleUrl: "./address.component.css",
})
export class AddressComponent implements OnInit {
    isLoggedIn: boolean = false;
    addressList: any[] = [];
    displayedAddressList: any[] = [];
    addressById: any = {};
    addressUpdated: any = {};
    showUpdateForm: boolean = false;
    errorMessage: string = "";
    constructor(
        private addressService: AddressService,
        private userService: AuthService,
        private router: Router,
        private sharedService: SharedService
    ) { }
    ngOnInit(): void {
        if (typeof localStorage !== "undefined" && localStorage.getItem("token")) {
            this.getAllAddresses();
        }
    }

    ifLoggedIn(): boolean {
        this.userService.isAuthenticated().subscribe((isAuthenticated: boolean) => {
            this.isLoggedIn = isAuthenticated;
        });
        return this.isLoggedIn;
    }

    getUserId(): string | null {
        if (typeof localStorage !== "undefined") {
            const token = localStorage.getItem("token");
            if (token) {
                const tokenPayload = JSON.parse(atob(token.split(".")[1]));
                console.log(tokenPayload);
                return tokenPayload.user.id;
            }
        }
        return null;
    }

    getAllAddresses(): void {
        if (typeof localStorage !== "undefined") {
            const token = localStorage.getItem("token");
            if (token) {
                this.addressService
                    .getAllAddress(token)
                    .subscribe((addressList: any) => {
                        this.addressList = addressList;
                        this.displayedAddressList = [...this.addressList];
                    });
            }
        }
    }

    getAddressById(id: string): void {
        if (typeof localStorage !== "undefined") {
            const token = localStorage.getItem("token");
            if (token) {
                this.showUpdateForm = false;
                this.addressService
                    .getAddressById(id, token)
                    .subscribe((addressById: any) => {
                        this.addressById = addressById;
                        this.addressById.dob = this.addressById.dob.toString().slice(0, 10);
                    });
            }
        }
    }

    closeView(): void {
        this.addressById = {};
    }

    showAddFormFunction(): void {
        this.router.navigate(["/createAddress"]);
    }

    populateUpdateForm(address: any) {
        this.addressUpdated = { ...address };
        this.addressUpdated.dob = this.addressUpdated.dob.toString().slice(0, 10);
        this.showUpdateForm = true;
    }

    updateAddress(id: string): any {
        if (typeof localStorage !== "undefined") {
            const token = localStorage.getItem("token");
            if (token) {
                this.addressService.updateAddress(this.addressUpdated, token).subscribe(
                    (addressUpdated: any) => {
                        const index = this.displayedAddressList.findIndex(
                            (p) => p._id === id
                        );
                        if (index !== -1) {
                            this.addressList[index] = addressUpdated;
                            this.displayedAddressList[index] = addressUpdated;
                            this.getAllAddresses();
                            this.showUpdateForm = false;
                            this.router.navigate(["/getAllAddress"]);
                        }
                        this.cancelUpdate();
                    },
                    (error) => {
                        this.errorMessage = "Error Updating Activity";
                    }
                );
            }
        }
        return this.addressUpdated;
    }

    cancelUpdate(): void {
        this.showUpdateForm = false;
        this.addressUpdated = {};
        this.addressById = {};
    }

    confirmDelete(addressId: string): void {
        const confirmDelete = window.confirm(
            "Are you sure you want to delete this address?"
        );
        if (confirmDelete) {
            this.deleteAddress(addressId);
        }
    }

    deleteAddress(id: string): void {
        if (typeof localStorage !== "undefined") {
            const token = localStorage.getItem("token");
            if (token) {
                this.addressService.deleteAddress(id, token).subscribe(
                    () => {
                        this.addressList = this.addressList.filter(
                            (address: any) => address._id !== id
                        );
                        this.displayedAddressList = [...this.addressList];
                    },
                    (error) => {
                        this.errorMessage = "Error Deleting Address";
                    }
                );
            }
        }
    }
}
JavaScript
// Address-create.compoennt.ts

import { Component } from "@angular/core";
import { AddressService } from "../address.service";
import { AuthService } from "../auth.service";
import { Router } from "@angular/router";
import { SharedService } from "../shared.service";
import { FormsModule } from "@angular/forms";
import { CommonModule } from "@angular/common";

@Component({
    selector: "app-address-create",
    standalone: true,
    imports: [FormsModule, CommonModule],
    templateUrl: "./address-create.component.html",
    styleUrl: "./address-create.component.css",
})
export class AddressCreateComponent {
    isLoggedIn: boolean = false;
    addressCreated: any = {};
    showAddForm: boolean = false;
    errorMessage: string = "";
    constructor(
        private addressService: AddressService,
        private userService: AuthService,
        private router: Router,
        private sharedService: SharedService
    ) { }
    ngOnInit(): void { }

    createAddress(): void {
        if (typeof localStorage !== "undefined") {
            const token = localStorage.getItem("token");
            if (token) {
                this.addressService
                    .createAddress(this.addressCreated, token)
                    .subscribe((addressCreated) => {
                        this.addressCreated = addressCreated;
                        this.resetForm();
                        this.router.navigate(["/getAllAddress"]);
                    });
            }
        }
    }

    resetForm(): void {
        this.addressCreated = {};
    }
}
JavaScript
// User.component.ts

import { Component, OnInit } from "@angular/core";
import { AuthService } from "../auth.service";
import { Router } from "@angular/router";
import { SharedService } from "../shared.service";
import { FormsModule } from "@angular/forms";
import { CommonModule } from "@angular/common";

@Component({
    selector: "app-user",
    standalone: true,
    imports: [FormsModule, CommonModule],
    templateUrl: "./user.component.html",
    styleUrl: "./user.component.css",
})
export class UserComponent implements OnInit {
    username!: string;
    email!: string;
    password!: string;
    credentials: any = {};
    successMessage: string = "";
    errorMessage: string = "";
    loginActive: boolean = true;
    registerActive: boolean = false;
    constructor(
        private userService: AuthService,
        private router: Router,
        private sharedService: SharedService
    ) { }

    ngOnInit(): void {
        this.sharedService.loginEvent.subscribe(() => {
            this.loginActive = true;
            this.registerActive = false;
            this.username = "";
            this.email = "";
            this.password = "";
            this.successMessage = "";
            this.errorMessage = "";
        });
        this.sharedService.registerEvent.subscribe(() => {
            this.registerActive = true;
            this.loginActive = false;
            this.username = "";
            this.email = "";
            this.password = "";
            this.successMessage = "";
            this.errorMessage = "";
        });
    }

    login(): void {
        const credentials = {
            email: this.email,
            password: this.password,
        };
        this.userService.login(credentials).subscribe(
            (response: any) => {
                const token = response.token;
                localStorage.setItem("token", token);
                this.userService.setAuthenticationStatus(true);
                this.userService.emitLoggedInEvent();
                this.loginActive = false;
                this.registerActive = false;
                this.router.navigate(["/getAllAddress"]);
                this.successMessage = "User logged in successfully.";
                this.errorMessage = "";
            },
            (error: any) => {
                console.error("Error logging in:", error);
                this.errorMessage =
                    "Login unsuccessfull ! Please reload or try in incognito tab";
                this.successMessage = "";
            }
        );
    }

    register(): void {
        const userData = {
            username: this.username,
            email: this.email,
            password: this.password,
        };

        this.userService.register(userData).subscribe(
            (response: any) => {
                this.successMessage = response.message;
                this.errorMessage = "";
                this.loginActive = true;
                this.registerActive = false;
            },
            (error: any) => {
                this.errorMessage = "User not registered successfully";
                this.successMessage = "";
            }
        );
    }
}
JavaScript
// Address.service.ts

import { HttpClient, HttpHeaders } from "@angular/common/http";
import { Injectable } from "@angular/core";
import { Observable } from "rxjs";

@Injectable({
    providedIn: "root",
})
export class AddressService {
    private baseUrl = "http://localhost:5000/api/address";
    constructor(private httpClient: HttpClient) { }

    getAllAddress(token: string): Observable<any> {
        const headers = new HttpHeaders({
            Authorization: `Bearer ${token}`,
        });
        return this.httpClient.get<any>(`${this.baseUrl}/getAllAddress`, {
            headers,
        });
    }

    getAddressById(id: string, token: string): Observable<any> {
        const headers = new HttpHeaders({
            Authorization: `Bearer ${token}`,
        });
        return this.httpClient.get<any>(`${this.baseUrl}/getAddressById/${id}`, {
            headers,
        });
    }

    createAddress(address: any, token: string): Observable<any> {
        const headers = new HttpHeaders({
            Authorization: `Bearer ${token}`,
        });
        return this.httpClient.post<any>(`${this.baseUrl}/createAddress`, address, {
            headers,
        });
    }

    updateAddress(address: any, token: string): Observable<any> {
        const headers = new HttpHeaders({
            Authorization: `Bearer ${token}`,
        });
        return this.httpClient.put<any>(
            `${this.baseUrl}/updateAddress/${address._id}`,
            address,
            { headers }
        );
    }

    deleteAddress(id: string, token: string): Observable<void> {
        const headers = new HttpHeaders({
            Authorization: `Bearer ${token}`,
        });
        return this.httpClient.delete<void>(`${this.baseUrl}/deleteAddress/${id}`, {
            headers,
        });
    }
}
JavaScript
// Auth.service.ts

import { HttpClient } from "@angular/common/http";
import { EventEmitter, Injectable } from "@angular/core";
import { BehaviorSubject, Observable } from "rxjs";

@Injectable({
    providedIn: "root",
})
export class AuthService {
    private baseUrl = "http://localhost:5000/api/auth";
    constructor(private httpClient: HttpClient) { }

    register(userData: any): Observable<any> {
        return this.httpClient.post(`${this.baseUrl}/register`, userData);
    }

    login(credentials: any): Observable<any> {
        return this.httpClient.post(`${this.baseUrl}/login`, credentials);
    }

    private isAuthenticatedSubject = new BehaviorSubject<boolean>(false);

    isAuthenticated(): Observable<boolean> {
        return this.isAuthenticatedSubject.asObservable();
    }

    setAuthenticationStatus(isAuthenticated: boolean): void {
        this.isAuthenticatedSubject.next(isAuthenticated);
    }

    loggedInEvent: EventEmitter<any> = new EventEmitter();
    emitLoggedInEvent() {
        this.loggedInEvent.emit();
    }
}
JavaScript
// Shared.service.ts

import { EventEmitter, Injectable } from '@angular/core';

@Injectable({
    providedIn: 'root'
})
export class SharedService {
    loginEvent: EventEmitter<void> = new EventEmitter<void>();
    registerEvent: EventEmitter<void> = new EventEmitter<void>();
    constructor() { }

    triggerLoginEvent(): void {
        this.loginEvent.emit();
    }

    triggerRegisterEvent(): void {
        this.registerEvent.emit();
    }
}
JavaScript
// app.component.ts

import { Component } from "@angular/core";
import { Router, RouterOutlet } from "@angular/router";
import { SharedService } from "./shared.service";
import { AuthService } from "./auth.service";
import { FormsModule } from "@angular/forms";
import { CommonModule } from "@angular/common";

@Component({
    selector: "app-root",
    standalone: true,
    imports: [RouterOutlet, FormsModule, CommonModule],
    templateUrl: "./app.component.html",
    styleUrl: "./app.component.css",
})
export class AppComponent {
    title = "GeeksForGeeks Address Book";
    isLoggedIn: boolean = false;
    constructor(
        private router: Router,
        private userService: AuthService,
        private sharedService: SharedService
    ) { }
    ngOnInit(): void {
        this.userService.loggedInEvent.subscribe((data: any) => {
            this.isLoggedIn = true;
        });
        if (typeof localStorage !== "undefined" && localStorage.getItem("token")) {
            this.isLoggedIn = true;
        }
    }

    login(): void {
        this.sharedService.triggerLoginEvent();
        this.router.navigate(["/"]);
    }

    register(): void {
        this.sharedService.triggerRegisterEvent();
        this.router.navigate(["/"]);
    }

    logout(): void {
        this.userService.setAuthenticationStatus(false);
        this.isLoggedIn = false;
        localStorage.removeItem("token");
        this.router.navigate(["/"]);
    }
}
JavaScript
// app.routes.ts

import { Routes } from "@angular/router";
import { AddressComponent } from "./address/address.component";
import { AddressCreateComponent } from "./address-create/address-create.component";
import { UserComponent } from "./user/user.component";

export const routes: Routes = [
    { path: "", component: UserComponent },
    { path: "getAllAddress", component: AddressComponent },
    { path: "getAddressById/:id", component: AddressComponent },
    { path: "createAddress", component: AddressCreateComponent },
    { path: "updateAddress/:id", component: AddressComponent },
    { path: "deleteAddress/:id", component: AddressComponent },
    { path: "**", redirectTo: "/" },
];
JavaScript
// app.module.ts

import { InjectionToken, NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { JwtHelperService, JWT_OPTIONS } from '@auth0/angular-jwt';
import { RouterModule } from '@angular/router';
import { routes } from './app.routes';
import { AddressComponent } from './address/address.component';
import { AddressCreateComponent } from './address-create/address-create.component';
import { UserComponent } from './user/user.component';
@NgModule({
    declarations: [
        AppComponent,
        UserComponent,
        AddressComponent,
        AddressCreateComponent,
    ],
    imports: [
        BrowserModule,
        FormsModule,
        RouterModule.forRoot(routes),
    ],
    exports: [RouterModule],
    providers: [{ provide: JWT_OPTIONS, useValue: JWT_OPTIONS }, JwtHelperService],
    bootstrap: [AppComponent]
})
export class AppModule { }

To start the angular application run the following command.

ng serve

Output:

Address book using Mean

Address Book using MEAN



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads