In previous article I had discussed how we can perform full crud operation with localStorage in javascript. Now in this article I am going to discuss about how we can make application of shopping cart with localStorage in javascript. This is like the crud operation we do in the javascript the only addon in shopping cart is add to cart functionality with increase or decrease the quantity but it is also very simple. But if you don’t know how we can perform the crud operation in javascript then it is difficult for you to understand this application because in this shopping cart with localStorage everything is going with the crud operation.

Introduction to localStorage

LocalStorage is a web storage feature in web browsers that allows websites to store data locally on a user’s device. It provides a simple key-value storage mechanism and is part of the Web Storage API. LocalStorage also keeps the data after the page refreshes so it act like our virtual database through we can perform any operation till the localStorage not get cleared. This is the image of localStorage where we can store data in the form of key value pair.

crud operation with localStorage in javascript

Tools & Technologies used in shopping cart with localStorage

  • HTML
  • CSS
  • Javascript
  • Jquery
  • Bootstrap
  • jquery DataTable plugin
  • Toast Plugin
  • jquery validation plugin

I have used the above technologies and plugins for making our application more interactive and user friendly. If you want to add any extra thing you can and if you want to know about all these plugins then you can know about plugins from here. Because it is used in this shopping cart with localStorage application therefore it is important to know that which plugins are we using while developing an application.

Working of Shopping cart

Source code for shopping cart with localStorage

The source code for above application is divided into three parts which is index.html ,script.js and products.json. Index.html contains all the CDNs and the html code for the user interaction. script.js contains all the code for handling the functionalities of shopping cart with localStorage. The third products.json is contain all the product details which is initially show in the landing page.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.3.0/font/bootstrap-icons.css">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.3/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-toast-plugin/1.3.2/jquery.toast.min.js"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jquery-toast-plugin/1.3.2/jquery.toast.min.css">
    <link rel="stylesheet" href="style.css">
    <title>Shopping cart with localStorage in javascript</title>
</head>
<body>
    <!-- nav bar -->
      <nav class="navbar navbar-expand-lg bg-body-tertiary">
        <div class="container-fluid">
          <a class="navbar-brand" href="https://webtutorialstack.com/" style="text-decoration: none;">WebTutorialStack</a>
          <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
          </button>
          <div class="collapse navbar-collapse" id="navbarNav">
            <ul class="navbar-nav">
              <li class="nav-item">
                <a class="nav-link" href="#" id="home">Home</a>
              </li>
              <li class="nav-item">
                <a class="nav-link"  href="" data-toggle="modal" data-target="#myModal">Add</a>
              </li>
              <li class="nav-item">
                <a class="nav-link" href="#" id="cart" onclick="addToTable()">Cart</a>
              </li>
            </ul>
          </div>
        </div>
      </nav>
    
      <!-- cards shown here -->
   <div class=" container my-5">
    <div id="addcarddata" class="row"></div></div>

    <!--  Add Modal -->
      <div class="modal" tabindex="-1" role="dialog" id="myModal">
        <div class="modal-dialog" role="document">
          <div class="modal-content">
            <div class="modal-header">
              <h5 class="modal-title">Modal title</h5>
              <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                <span aria-hidden="true">&times;</span>
              </button>
            </div>
            <div class="modal-body">
              <form action="" id="addform">
                <input type="text" id="add_id" name="name" style="display:none;">
                
                <div class="container">
                    <label for="name">Enter the Name of Product : </label>
                    <input type="text" id="add_name" name="name" class="form-control" required><br>
                </div>

                <div class="container">
                    <label for="price">Enter the Price of Product : </label>
                    <input type="number" id="add_price" name="price" class="form-control" required min="0" max="1000"><br>
                </div>

                <div class="container">
                    <label for="description">Description of Product : </label><br>
                    <textarea name="description" id="add_description" cols="30" rows="5" required class="form-control"></textarea><br>
                </div>
                
                <div class="container">
                    <label for="image">Upload the Image of Product : </label>
                    <input type="file" id="add_image" name="image" onchange="readURL(this)" height="200px" required><br><br>
                </div>
                <div class="container">
                    <button type="submit" class="btn btn-primary" onclick="addSomething()">Add Product</button>
                    <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
                </div>
              </form>
            </div>
          </div>
        </div>
      </div>

<!-- detail modal -->
<div class="modal fade" id="detailModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title" id="exampleModalLabel">Details of the Product</h5>
        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body">
        <form action="" id="addForm" onsubmit="return false">
          <div class="container">
              <label for="name">Name of Product : </label>
              <input type="text" id="detail_name" name="name" readonly class="form-control"><br>
          </div>

          <div class="container">
              <label for="price">Price of Product : </label>
              <input type="number" id="detail_price" name="price" readonly class="form-control"><br>
          </div>

          <div class="container">
            <label for="quantity">Quantity of Product : </label>
            <input type="number" id="detail_quantity" name="quanity" value=1 class="form-control" required><br>
          </div>

          <div class="container">
            <label for="description">Description of Product : </label><br>
            <textarea name="description" id="detail_description" cols="30" rows="5" readonly class="form-control"></textarea><br>
          </div>

          <div class="container">
              <label for="price">Image of Product : </label>
              <img src="" alt="detail of product" id="detail_image" width="150px" height="100px"><br><br>
          </div>

          <div class="container">
              <button type="submit" class="btn btn-primary" onclick="addToCart(this)">Add to Cart</button>
          </div>
        </form>
      </div>
    </div>
  </div>
</div>

  <div class="container" id="showcart">
    <div id="shopping-cart">
        <div id="hellodata">

        </div>
    </div>
  </div>
  
<script src="script.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.12.9/dist/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>

<script src="https://cdn.jsdelivr.net/npm/jquery-validation@1.19.5/dist/jquery.validate.js"></script>
<script src="https://cdn.jsdelivr.net/npm/jquery-validation@1.19.5/dist/jquery.validate.min.js"></script>
</body>
</html>

script.js

function getdata() {
    const xhttp = new XMLHttpRequest();
    xhttp.open("GET", "products.json", true);
    xhttp.onreadystatechange = function () {
        if (this.status == 200 && this.readyState == 4) {
            let data_store = JSON.parse(this.responseText);
            let data = localStorage.getItem("data");
            if (data == null || data == "") {
                localStorage.setItem("data", JSON.stringify(data_store));
                createCards();
            }
            else {
                createCards();
            }
        }
    }
    xhttp.send();
}
getdata();


function createCards() {
    let store = JSON.parse(localStorage.getItem("data"));
    let text = "";
    for (let i = 0; i < store.length; i++) {
        text = text + `<div class="col-sm-4 mb-3" id="cartdata">
                        <div class="card h-70">
                            <div class="card-body">
                               <img src="${store[i].image}" alt="image" class="card-img-top" height=300px>
                                <h5 class="card-title">${store[i].name}</h5>
                                <p class="card-text">${store[i].price}</p>
                                <h6 class="card-text">${store[i].description}</h6>
                            </div>
                            <div class="card-footer">
                                <button type="button" class="btn btn-primary" onclick="details(${store[i].id})">Buy Now</button>
                            </div>
                        </div>
                    </div>`;
    }
    document.getElementById("addcarddata").innerHTML = text;
    $("#shopping-cart").hide();
    $("#home").click(function () {
        $("#addcarddata").show();
        $("#shopping-cart").hide();
    })
    $("#cart").click(function () {
        $("#addcarddata").hide();
        $("#shopping-cart").show();
    })
}

// this will help in to choose the quantity while we click on the add to cart button
const inputField = document.getElementById('detail_quantity');
inputField.addEventListener('input', (event) => {

    inputField.addEventListener("input", () => {
        const inputValue = inputField.value;
        // Check if input value is between 1 and 10
        if (inputValue >= 1 && inputValue <= 10) {
            // Truncate input value to 2 digits
            inputField.value = inputValue.slice(0, 2);
        } else {
            // Clear input field if value is not between 1 and 10
            inputField.value = "";
        }
    });
    // 
});


function details(detailindex) {
    $("#detailModal").modal('show');
    let store = JSON.parse(localStorage.getItem("data"));
    let index = detailindex;
    function findindex() {
        for (let i = 0; i < store.length; i++) {
            if (index == store[i].id) {
                return i;
            }
        }
    }
    var x = findindex();
    var img = store[x].image;
    var name = store[x].name;
    var price = store[x].price;
    var description = store[x].description;
    document.getElementById("detail_image").src = img;
    document.getElementById("detail_name").value = name;
    document.getElementById("detail_price").value = price;
    document.getElementById("detail_description").value = description;

    localStorage.setItem("data", JSON.stringify(store));
    document.getElementById("cartdata").innerHTML = "";
    createCards();
}
function validform() {
    $("#addform").validate({
        rules: {
        }
    })

}
function quantityvalid() {
    $("#addForm").validate({
        rules: {
            detail_quantity: {
                required: true,
                rangelength: [1, 10]
            }
        }
    })
}
function addSomething() {
    let store = JSON.parse(localStorage.getItem("data"));
    let newid = (store.length) + 1;
    var newname = document.getElementById("add_name").value;
    var newprice = document.getElementById("add_price").value;
    var newdescription = document.getElementById("add_description").value;
    var newimage = document.getElementById("add_image").src;
    if (newname == "" || newprice == "" || newdescription == "" || newimage == "") {
        validform();
        return;
    }
    else {
        var newObj = {
            id: newid,
            name: newname,
            price: newprice,
            description: newdescription,
            image: newimage
        }
        store.push(newObj);
        $("#myModal").modal('hide');
        document.getElementById("add_name").value = "";
        document.getElementById("add_price").value = "";
        document.getElementById("add_description").value = "";
        localStorage.setItem("data", JSON.stringify(store));
        $.toast({
            text: 'Product has been added to the Product gallery',
            icon: 'success',
            loader: true,
            loaderBg: '#9EC600',
            // position:'top-center'
        })
        createCards();
    }
}

// /*Image Rendering */
function readURL(input) {
    if (input.files && input.files[0]) {
        var reader = new FileReader();

        reader.onload = function (e) {
            $('#add_image')
                .attr('src', e.target.result)
        };
        reader.readAsDataURL(input.files[0]);
    }
}

function addToCart(detailindex) {
    let store = JSON.parse(localStorage.getItem("data"));
    var newname = document.getElementById("detail_name").value;
    var newprice = document.getElementById("detail_price").value;
    var newquanity = document.getElementById("detail_quantity").value;
    var n_quantity = Number(newquanity)
    var newObj = {
        name: newname,
        price: newprice,
        quantity: newquanity,
        total: newprice
    };


    $("#detailModal").modal('hide');
    var cartArray = new Array();
    if (localStorage.getItem("hello")) {
        cartArray = JSON.parse(localStorage.getItem("hello"));
    }

    cartArray.push(newObj);

    var cartJSON = JSON.stringify(cartArray);
    localStorage.setItem("hello", cartJSON);
    $.toast({
        text: 'Item has been successfully added to cart',
        icon: 'success',
        loader: true,
        loaderBg: '#9EC600',
    })
    addToTable();
}


function addToTable() {
    let store2 = JSON.parse(localStorage.getItem("hello"));

    let text = "";
    text += `<button type="button" class="btn btn-danger" onclick="emptyCart()">Empty Cart</button>
    <table class=" table tbl-cart" cellpadding="20" id="tabledata">
          <thead class="bg-primary">
              <tr>
                  <th>Name</th>
                  <th>Price</th>
                  <th>Quantity</th>
                  <th>Total</th>
              </tr>
          </thead>`;
    for (let i = 0; i < store2.length; i++) {
        let item = store2[i];
        text += `<tbody id="tablebody"><tr>
      <td>${item.name}</td>
      <td>${item.price}</td>
      <td><button class="btn btn-success btn-sm" onclick="decrement(this)"><i class="bi bi-file-minus"></i>
      </button>${item.quantity}<button class="btn btn-success btn-sm" onclick="increment(this)"><i class="bi bi-file-plus"></i></button></td>
      <td>${item.total * item.quantity}</td>
      </tr>`;
    }
    let grandtotal = 0;
    for (let i = 0; i < store2.length; i++) {
        let item = store2[i];
        grandtotal += item.total * item.quantity;
    }
    text += `</tbody><tr id="clc"><th colspan="2">Grand Total</th><th></th><th>${grandtotal}</tr>
    </table><button type="button" class="btn btn-success" onclick="checkout()">checkOut</button>`;
    document.getElementById("hellodata").innerHTML = text;

}

function checkout() {
    let store2 = JSON.parse(localStorage.getItem("hello"));
    $.toast({
        heading: 'Information',
        text: 'items has been placed successfully',
        icon: 'success',
        loader: true,
        loaderBg: '#9EC600',
        position: 'top-center'
    })
    localStorage.removeItem("hello");
    $("#tabledata").hide();
    $("#clc").hide();
}

function emptyCart() {
    localStorage.removeItem("hello");
    $.toast({
        heading: 'Information',
        text: 'items has been removed successfully from the cart',
        icon: 'error',
        loader: true,
        loaderBg: '#9EC600',
        position: 'top-center'
    })
    $("#tabledata").hide();
    $("#clc").hide();
}


function increment(index) {
    var incrementIndex = index;
    var parent1 = incrementIndex.parentElement.parentElement.rowIndex;
    let store2 = JSON.parse(localStorage.getItem("hello"));

    if ((store2[parent1 - 1].quantity) > 9) {
        alert("you cannot add more than 10")
        return;
    }
    else {
        (store2[(parent1 - 1)].quantity)++;
        localStorage.setItem("hello", JSON.stringify(store2))
        document.getElementById("hellodata").innerHTML = "";
        addToTable();
    }
}

function decrement(index) {
    var incrementIndex = index;
    var parent1 = incrementIndex.parentElement.parentElement.rowIndex;
    let store2 = JSON.parse(localStorage.getItem("hello"));
    if ((store2[parent1 - 1].quantity) <= 1) {
        if ((store2[parent1 - 1].quantity) == 1) {
            store2.splice(parent1 - 1, 1)
            localStorage.setItem("hello", JSON.stringify(store2))
            document.getElementById("hellodata").innerHTML = "";
            addToTable();
        }
        return;
    }
    else {
        (store2[(parent1 - 1)].quantity)--;
        localStorage.setItem("hello", JSON.stringify(store2))
        document.getElementById("hellodata").innerHTML = "";
        addToTable();
    }

}

products.json

[
    {
        "id":1,
        "name":"laptop",
        "price":"500",
        "image":"laptop.jpg",
        "description":"This is my Laptop"
    },
    {
        "id":2,
        "name":"watch",
        "price":"1500",
        "image":"watch.jpg",
        "description":"This is the watch"
    },
    {
        "id":4,
        "name":"Smart watch",
        "price":"900",
        "image":"watch.jpg",
        "description":"This is the watch"
    },
    {
        "id":5,
        "name":"Speaker",
        "price":"1500",
        "image":"speaker.jpg",
        "description":"This is the Speaker"
    },
    {
        "id":6,
        "name":"Ring Light",
        "price":"800",
        "image":"ringlight.jpg",
        "description":"This is the ring light"
    },
    {
        "id":7,
        "name":"Mobile",
        "price":"4000",
        "image":"mobile.jpg",
        "description":"This is the my mobile"
    },
    {
        "id":8,
        "name":"Laptop",
        "price":"5000",
        "image":"laptop.jpg",
        "description":"This is my best laptop"
    },
    {
        "id":9,
        "name":"Ipad",
        "price":"6000",
        "image":"ipad.jpg",
        "description":"My apple Ipad"
    },
    {
        "id":10,
        "name":"Apple Watch",
        "price":"1500",
        "image":"apple.jpg",
        "description":"This is the my apple watch"
    }
]

Conclusion

Above is the code for shopping cart application and also i have uploaded the video to show how this application works. If you want to download the whole code in the zip file then you can download the whole code from the given link.