Table of contents
Learn how to build add-to-cart functionality in Node.js using MongoDB, Express, and Mongoose for e-commerce applications.
In e-commerce platforms, the ability to add items to a shopping cart is fundamental. This functionality allows users to select products and keep track of them until they proceed to checkout. In this article, we will delve into a Node.js controller that handles adding items to a cart. The controller is part of an Express application and utilizes MongoDB for data storage.
Key Components
- Imports and Models
const mongoose = require("mongoose");
const Cart = require("../../../../models/Cart.model/Cart.model");
const Product = require("../../../../models/Products.model/Products.model");
const User = require("../../../../models/User.model/User.model");
const ApiError = require("../../../../utils/ApiError");
const ApiResponse = require("../../../../utils/ApiResponse");
const asyncHandler = require("../../../../utils/asyncHandler");
mongoose: A library for MongoDB object modeling.
Cart, Product, User: Mongoose models representing collections in the database.
ApiError: A custom error handling utility.
ApiResponse: A utility to create standardized API responses.
asyncHandler: A utility to handle asynchronous functions and errors.
Controller Function Definition
const createAddTOCartController = asyncHandler(async (req, res) => {
The
createAddTOCartController
function is defined usingasyncHandler
to manage asynchronous operations and error handling efficiently.Extracting Request Data
const userId = req.user.userId; const { productId, quantity = 1 } = req.body;
The function extracts
userId
,productId
, andquantity
from the request. If the quantity is not provided, it defaults to 1.Validating Product ID
if (!mongoose.Types.ObjectId.isValid(productId)) { throw new ApiError(400, "Invalid order id. Please provide a valid order id."); }
This validation ensures that the
productId
is a valid MongoDB ObjectId.Checking for Missing Fields
if (!productId) { throw new ApiError(400, "Missing required fields: productId and quantity"); }
An error is thrown if the
productId
is missing from the request.Finding Product and User
const product = await Product.findById(productId); const user = await User.findById(userId);
The function queries the database to find the product and user by their respective IDs.
Handling Product Not Found
if (!product) { throw new ApiError(404, "Product not found"); }
An error is thrown if the product does not exist in the database.
Finding or Creating Cart
let cart = await Cart.findOne({ userId }); if (!cart) { cart = new Cart({ userId, items: [] }); }
The function looks for an existing cart for the user. If no cart is found, it creates a new one.
Updating Cart Items
const existingItem = cart.items.find((item) => item.productId.toString() === productId); if (existingItem) { existingItem.quantity += quantity; } else { user.carts.push(cart._id); await user.save({ validateBeforeSave: false }); cart.items.push({ productId, quantity, name: product?.title, price: product?.regular_price, sku: product?.SKU, }); }
If the item already exists in the cart, its quantity is updated. Otherwise, a new item is added to the cart, and the cart ID is linked to the user's cart array.
Saving the Cart
await cart.save();
The updated cart is saved to the database.
Creating HATEOAS Links
const host = req.apiHost; const links = [ { rel: "view_cart", href: `${host}/carts`, method: "GET", description: "View Cart", }, { rel: "orders", href: `${host}/orders`, method: "GET", description: "Orders", }, ];
HATEOAS (Hypermedia as the Engine of Application State) links provide navigational links to related resources, enhancing API usability.
Returning the Response
return res.status(201).json(new ApiResponse(201, { cart, links }, "Item added to cart"));
A success response is sent to the client, including the updated cart and HATEOAS links.
Exporting the Controller
module.exports = createAddTOCartController;
The controller is exported for use in other parts of the application.
Conclusion
This Node.js controller provides a robust and efficient way to manage adding items to a shopping cart. By validating inputs, handling errors gracefully, and maintaining a seamless interaction with the database, the controller ensures a smooth user experience. The inclusion of HATEOAS links further enhances API navigation, making it easier for clients to interact with related resources. This approach not only streamlines the cart management process but also builds a solid foundation for scalable and maintainable e-commerce applications.
This is the actual article repository code link: https://github.com/muhammadranju/e-commerce-api/blob/main/src/api/v1/cart/controller/create.js
This is the main github repository links: https://github.com/muhammadranju/e-commerce-api