Search code examples
javascriptnode.jsexpresshttpfetch

Send request to server to send product detail page when product card is clicked


I am creating a product page that show all available product in the form of card.

This screenshot shows how products is displayed on the products page

I want a functionality that whenever user click's on any product card from the available product cards a request is to be made to server to open product showcase page with complete product detail

Screenshot shows the file I need to render in responce

I tried some method to do that, but none worked well.

The code for product card is:

<div class="product-display-c">
    <div class="product-card-holding-c">
        <!--  -->
        <% for (let i=0; i < data.length; i++) {%>
            <div id="<%= data[i].id%>" class="product-card-c">
                <div class="product-image-c">
                    <img class="product-card-image" src="<%= data[i].images[0]%>"
                         alt="random image" />
                </div>
                <div class="product-detail-c">
                    <p class="product-name">
                        <%= data[i].p_name%>
                    </p>
                    <p class="product-sp">Rs. <%= data[i].selling_price%>
                    </p>
                    <p class="product-mrp">M.R.P: Rs. 
                       <span><%= data[i].mrp%></span>
                    </p>
                    <p class="product-discount">
                        <%= data[i].mrp - data[i].selling_price%> off
                    </p>
                    <p class="product-quality">Quality verified</p>
                </div>
            </div>
        <% }%>
    </div>
</div>

This code create cards as per data received from database.

After that I wrote Javascript code to send request to server to open productshowcase page with complete product detail. The code is like this:

document.querySelectorAll('.product-card-c').forEach((div) => {
  div.addEventListener('click', function(event) {
    console.log(event.target.closest('.product-card-c').id);
    const selectedId =event.target.closest('.product-card-c').id;
    fetch(`/products/${selectedId}`)
          .then(response => console.log(response.text()))
  });
});

this code send the id of clicked card to the server. The server side code to handle this is like app.get('/products/:id', async function(req, res) { try { const selectedId = await db.query(SELECT * FROM products WHERE id=${req.params.id}); res.render("productshowcase.ejs", {product :selectedId.rows}); } catch (err) { console.log(err); } });

I don't know what is the issue but nothing happen when i click the card.

Although the server response when i try to hit browser url section with url localhost:3000/products/2 the server open productshowcase page without CSS apllied to it and with lots of error in console like "Failed to load resource: the server responded with a status of 404 (Not Found) great-value-trademart.png:1 Failed to load resource: the server responded with a status of 404 (Not Found) header.js:1

   Failed to load resource: the server responded with a status of 404 (Not Found)

1:1 Refused to execute script from 'http://localhost:3000/products/jscript/header.js' because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled. category-2.jpg:1

Failed to load resource: the server responded with a status of 404 (Not Found)"

I am totally stuck. Can anyone help me to find where the error is?

Thanks in advance.

I tried searching for the correct method to send request to the server but failed to find the right one


Solution

  • EJS is a server-side template engine, which means the HTML is created on the server and typically sent back as a HTTP response. What you are trying to do is make a fetch request which will get that rendered HTML and store it as text when you do .then(response => console.log(response.text())). After that nothing happens. The HTML won't magically append itself to the DOM or replace the existing HTML on your page.

    When using fetch it's to typically get data from the sever usually as JSON and from that JSON payload you can loop through is properties and append/replace HTML elements to the DOM. You would need to write code to do that. Alternatively you could just send a url back as the response and redirect the browser to navigate to the new url.

    My honest advice if sticking with EJS would be

    Option 1:

    Warp each card in an <a> tag with the id of each product appended to the href attribute. That way when your user clicks on a card the browser sends a standard GET request to /products/:id and is redirected appropriately.

    This means you can delete all of that document.querySelectorAll('.product-card-c').forEach code.

    An example would be:

    <div class="product-display-c">
       <div class="product-card-holding-c">
          <!--  -->
          <% for (let i=0; i < data.length; i++) {%>
           <a href="/products/<%= data[i].id%>">  <!-- add this a tag  -->
             <div id="<%= data[i].id%>" class="product-card-c">
                <div class="product-image-c">
                   <img class="product-card-image" src="<%= data[i].images[0]%>" alt="random image" />
                </div>
                <div class="product-detail-c">
                   <!-- rest of your code -->
                </div>
             </div>
            </a>
          <% }%>
       </div>
    </div>
    

    Option 2:

    Don't change any HTML code and instead of sending a fetch request use your click handler to navigate to the new url like so:

    document.querySelectorAll('.product-card-c').forEach((div) => {
      div.addEventListener('click', function(event) {
        console.log(event.target.closest('.product-card-c').id);
        const selectedId =event.target.closest('.product-card-c').id;
        window.location.assign(`http://localhost:3000/products/${selectedId}`); //< add this
      });
    });