Search code examples
javascriptnode.jstwitter-bootstrapbootstrap-modalejs

How to use bootstrap modal for update the data?


I am working on e-commerce app using ejs template and nodejs as backend . In that I have admin role for administrative work . I create Bootstrap modal for update the order status . But I am able to only update the first order , if I try to any other order only first order gets update . Can anyone please help me to sort out this problem .

allOrders.ejs (list of orders & modal)

<%- include("../partials/header") %> <%- include("../partials/navbar") %>

<div class="container-fluid">
  <h3 class="text-center mt-2">All Orders</h3>
  <table class="table table-bordered border-primary mt-4 mb-3">
    <thead>
      <tr>
        <th scope="col">ID</th>
        <th scope="col">Order Date</th>
        <th scope="col">Order Updated Date</th>
        <th scope="col">Status</th>
        <th scope="col">Amount</th>
        <th scope="col">Actions</th>
      </tr>
    </thead>
    <% for(let order of allOrders ){ %>
    <tbody>
      <tr>
        <td><%= order._id %></td>
        <td><%= order.date %></td>
        <td><%= order.updatedAt %></td>
        <td><%= order.status %></td>
        <td><%= order.amount %></td>
        <td className="bg-secondary">
          <!-- Button trigger modal -->
          <button
            type="button"
            class="btn btn-primary"
            data-bs-toggle="modal"
            data-bs-target="#exampleModal"
          >
            Update
          </button>

          <!-- Modal For Edit Status-->
          <div
            class="modal fade"
            id="exampleModal"
            tabindex="-1"
            aria-labelledby="exampleModalLabel"
            aria-hidden="true"
          >
            <div class="modal-dialog modal-dialog modal-lg">
              <div class="modal-content">
                <div class="modal-header">
                  <h5 class="modal-title" id="exampleModalLabel">
                    Update Order Status
                  </h5>
                  <button
                    type="button"
                    class="btn-close"
                    data-bs-dismiss="modal"
                    aria-label="Close"
                  ></button>
                </div>
                <form
                  class="m-5"
                  action="/admin/<%= currentUser._id %>/order/<%=order._id%>?_method=PATCH"
                  method="POST"
                  novalidate
                >
                  <div class="mb-3">
                    <label for="orderId" class="form-label">Order ID</label>
                    <input
                      type="text"
                      class="form-control"
                      disabled
                      value="<%= order._id %>"
                    />
                    <label class="form-label">Current Status</label>
                    <input
                      type="text"
                      class="form-control"
                      disabled
                      value="<%= order.status %>"
                    />
                    <div class="mb-4">
                      <label for="updateStatus" class="form-label"
                        >Update Staus
                      </label>
                      <select
                        class="form-select form-control"
                        name="status"
                        value="status"
                      >
                        <option name="Processing" value="Processing">
                          Processing
                        </option>
                        <option name="Prepared" value="Prepared">
                          Prepared
                        </option>
                        <option name="Dispatched" value="Dispatched">
                          Dispatched
                        </option>
                        <option name="Delivered" value="Delivered">
                          Delivered
                        </option>
                      </select>
                    </div>
                  </div>
                  <button type="submit" class="btn btn-primary save">
                    Save Status
                  </button>
                </form>
                <div class="modal-footer">
                  <button
                    type="button"
                    class="btn btn-secondary"
                    data-bs-dismiss="modal"
                  >
                    Cancle
                  </button>
                </div>
              </div>
            </div>
          </div>
        </td>
      </tr>
    </tbody>
    <% } %>
  </table>
</div>
<%- include("../partials/footer") %>

routes for order

const express = require("express");
const router = express.Router();
const { isLoggedIn } = require("../middlewere");
const Order = require("../models/order");

router.get("/admin/:id/allorders", isLoggedIn, async (req, res) => {
  try {
    const allOrders = await Order.find({}).sort({ date: -1 });
    res.render("admin/allOrders", { allOrders });
  } catch (error) {
    req.flash("error", "Cannot Find Orders");
    res.render("error");
  }
});

router.patch("/admin/:id/order/:orderId", isLoggedIn, async (req, res) => {
  try {
    await Order.findByIdAndUpdate(req.params.orderId, req.body);
    req.flash("success", "Order Updated Successfully");
    res.redirect(`/admin/${req.params.id}/allorders`);
  } catch (error) {
    req.flash("error", "Cannot Update Order");
    res.render("error");
  }
});

module.exports = router;

I am able to fetch all orders but in modal it always shows first order details . I check code from Devtool (https://codeshare.io/8pyknv) also it showing correct info . But modal not showing it .


Solution

  • The problem exists inside the for loop. In your loop you have a button with an attribute data-bs-target="#exampleModal". That means all rows in your table will have the same button which triggers the modal with id exampleModal. All these button will call the same modal.

    Apart from this, each order generates a modal with a specific id exampleModal. So all modals have the same id. That's why you always open the first modal. Each modal must have a unique id

    To fix this problem, you should give unique ids to modals, for example

        <div
            class="modal fade"
            id="Modal<%= order._id %>"
            tabindex="-1"
            aria-labelledby="exampleModalLabel"
            aria-hidden="true"
        >
    

    and each button should call its own modal,

             <button
                type="button"
                class="btn btn-primary"
                data-bs-toggle="modal"
                data-bs-target="#Modal<%= order._id %>"
              >