Frontend is refusing to remove items from the shopping cart, while the backend is functioning properly in doing so

I've been working on a shopping cart project using Vanilla JS. The interface handles DOM logic, while the backend deals with array manipulation.

The issue I'm facing is with a button that's supposed to remove items from the cart. Despite passing my tests, the code doesn't work as expected.

I attempted to link each cart item to a unique id, incrementing as more items are added. I then tried to access each item individually using addEventListener('click'), call the removeItem() method, and render the cart outside the loop. Unfortunately, it didn't work, and I'm stuck.

cart.js

class Cart {
  constructor() {
    this.cartArray = [];
    this.total = 0;
  }

  add(item) {
    this.cartArray.push(item);
  }

  removeItem(item) {
      var position = this.cartArray.lastIndexOf(item);
      this.cartArray.splice(position, 1);
  }

  calculateTotal() {
    var reducedTotal = this.cartArray.reduce((previous, current) => {
      return this.total = previous + current.price;
    }, 0);
    return reducedTotal;
  }
}

interface.js - handles all DOM components

function initialize() {
  var itemList = "<table border='1|1'>";
  var shoppingCartList = document.getElementById("shoppingCartList");
  var total = document.getElementById("total");

  var eachParagraph = document.getElementsByClassName('delete-item');

  var cart = new Cart();

  function showItems() {
    for (var i = 0; i < items.length; i++) {
        itemList += "<tr>";
        itemList += "<td>" +  items[i].name + "</td>";
        itemList += "<td>" + items[i].category + "</td>";
        itemList += "<td> " + items[i].price + "</td>";
        itemList += "<td> " + items[i].stock  + "</td>";
        itemList += ` <td> <button id=${items[i].id}>add to cart</button> </td>`
        itemList += "</tr>";
    }
    itemList += "</table>";
    document.getElementById("itemsList").innerHTML = itemList;
  }

  function renderCart() {
    var print = "";
    var indexOfItem = 0;
    cart.cartArray.forEach(function(element, index) {
      print +=  `<p id=${index} class=${index}>` +  element.name + element.price 
      + `<button id=${indexOfItem}>Remove from cart</button> </p>`
      indexOfItem++;
    }
    return print;
  }

  function renderTotal(){
    cart.calculateTotal();
    return "£" + cart.total;
  }

  function removeItemButtonFunctionality() {
    cart.cartArray.forEach(function(element, index) {
      shoppingCartList.addEventListener('click', () => {
        cart.removeItem(element);
      });
    });
    renderCart();
  }

  function addToButtonFunctionality() {
    items.forEach( function(element, index) {
      document.getElementById(index).addEventListener('click', () => {
        cart.add(element);
        shoppingCartList.innerHTML = renderCart();
        total.innerHTML = renderTotal();
      });
    });
  }

  showItems();
  addToButtonFunctionality();
  removeItemButtonFunctionality();
}

window.addEventListener("DOMContentLoaded", initialize);

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <h1>Shopping retailer</h1>
</head>
<body>

  <div id="itemsList"></div>
<br>

<h3>Total:</h3>
<div id="total">
</div> 

  <h3>Shopping Cart:</h3>

  <p id="shoppingCartList"></p>

  <script src="src/items.js"></script>
  <script src="src/cart.js"></script>
  <script src="./interface.js"></script>
</body>
</html>

Answer №1

There are several issues with the code provided. Firstly, it seems that some ids are being repeated on certain elements which can cause problems when trying to access elements using getElementById. It is advisable to make each id unique by prefixing it with a keyword that describes the element.

Secondly, the remove button elements are not rendered when the removeItemButtonFunctionality is executed at the end of the initialize function. Event handlers should be added dynamically as items are being added.

While not a critical issue, it is recommended to modify the code so that the renderCart function actually renders the cart instead of returning a string and relying on another function to do so. For instance, within the removeItemButtonFunctionality, there is no action taken after calling renderCart().

The same approach should be applied to the renderTotal function as well.

To address these issues, the code can be refactored as follows:

function renderCart() {
  shoppingCartList.innerHTML = '';
  cart.cartArray.forEach(function(element) {
    shoppingCartList.innerHTML += `<p id="cart${element.id}">${element.name} ${element.price}<button id="remove${element.id}">Remove from cart</button></p>`;
    var removeButton = document.getElementById('remove' + element.id);
    removeButton.addEventListener('click', function() {
      cart.removeItem(element);
      renderCart();
      renderTotal();
    });
  })
}

The renderTotal function:

function renderTotal(){
  total.innerHTML = "£" + cart.calculateTotal();
}

The addToButtonFunctionality function should only trigger the render functions:

function addToButtonFunctionality() {
  items.forEach( function(element, index) {
    document.getElementById(index).addEventListener('click', () => {
      cart.add(element)
      renderCart();
      renderTotal();
    })
  })
}

Finally, at the end of the function, simply call:

showItems()
addToButtonFunctionality()

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Looking for a jquery plugin that allows you to easily toggle between showing and hiding elements

I'm in need of some guidance on finding a slide window plugin in jQuery. My goal is to create a feature similar to Yahoo Mail, where users can hide the advertisement pane shown on the right side by clicking a button. I would greatly appreciate any as ...

Retrieve the specific day of the previous complete week within a designated month using JavaScript

Is there a way to determine the last full week of any given month? For example, I need to find the Wednesday of the last full week in April each year. Here is the desired output: April 24, 2019, April 22, 2020, April 28, 2021, April 27, 2022, and so on. v ...

A runtime error occurred in ScriptResource.axd at line var f = ($telerik.isIE) ? document.createElement('<iframe name="' + this.get_id() + '">');

I am encountering an error during runtime in the ScriptResource.axd file, which is causing a major issue for me as I am unable to modify the code directly to fix it. The error seems to be specific to this line: ScriptResource.axd runtime error on line var ...

Resetting input field based on callback function

In my simple script, I have two pages - script.php and function.php. The script.php page contains an input field with the ID #code, a link with the ID #submit, and a jQuery function. $('#submit').click(function () { $.ajax({ url: 'f ...

What could be causing my ES6 code to fail compilation post npm install?

Check out my npm module built with es6 on Github here. Within the package.json file, there are scripts designed to ensure proper building of the es6 modules. When using npm publish and npm install within the module's directory, everything works fine. ...

What is preventing the JQuery dialog from opening?

When I try to trigger a dialog box by pressing the enter key, it is not working as expected. Instead of opening the dialog, it just hides the text. Can someone help me understand what might be causing this issue? <!doctype html> <html lang="en" ...

When the page is scrolled to 50 pixels, a modal pop-up will appear

I attempted to use cookies to store a value when the user clicks on a popup to close it, ensuring that the popup does not show again once closed. However, I am encountering an issue where the popup continues to open whenever I scroll, even after closing it ...

CORS - Preflight request response fails access control verification

I've been attempting to send a GET request to a server with the same domain as my local host, but I keep encountering the following error: The preflight request response fails the access control check: The requested resource does not have an ' ...

What sets apart the <script> tag with a type attribute from the standard <script> tag in HTML?

Similar Question: Is it necessary to include type=“text/javascript” in SCRIPT tags? While working on my HTML project, I noticed that the JavaScript code within script tags is evaluated even if the type attribute is not explicitly set to "j ...

Refresh a page in AngularJS with only a single click

I am currently working with angularjs and I am trying to figure out how to refresh the page only once when it loads. Here is what I have attempted so far: <script> app.cp.register('userProfileController', function ($window) { debugger; ...

What is the best way to upload a local image using JavaScript for TensorFlow?

I am having trouble loading a data.jpg file to be used by tensorflow mobilenet. When I try to require the file normally, I encounter an error message: So, my question is how can I load an image in my JavaScript code for use? I have tried various methods of ...

Can minification of JS be achieved in a Jekyll environment?

Currently, I am in the process of developing a project with Jekyll and one of the requirements is to minify HTML, CSS, and JS. I was wondering if Jekyll has built-in features for JS minification. It may seem like a simple question, but since I am new to ...

Having difficulty transitioning a function with a promise from JavaScript to TypeScript

I am currently in the process of transitioning my existing NodeJS JavaScript code to TypeScript for a NodeJS base, which will then be converted back to JavaScript when running on NodeJS. This approach helps me maintain clear types and utilize additional fe ...

Sending a multitude of variables using strings, evaluating them through various functions, and incorporating a variety of methods

To put it simply, my goal is to utilize an object literal that allows me to pass an unknown quantity of variables in any order to a function. While this may seem straightforward in principle, within my code, this object literal is passed to a second functi ...

Retrieve the element that is currently being hovered over within the same nested selector

I am facing a challenge in selecting the currently hovered element with a nested selector. The ".frmElement" class is used as the selector. When I hover over the ".frmElement" element at a certain level, all the previous selector elements display the hover ...

Having trouble launching the freshly developed Angular app

I'm encountering an issue with my newly created app - I can't seem to launch it. Error: The loader “C:/C#/Angular/my-app/src/app/app.component.css” is not providing a string as expected. https://i.sstatic.net/6Xjwd.png https://i.sstatic.ne ...

Struggling to make my background image adapt to screen size changes and morph correctly

I am struggling to create a simple square background image with a navbar that adjusts responsively on different screen sizes. While I have been able to get the image and navbar set up, the image is not expanding the way I want it to. I envision the image f ...

Is there a method in Kalendae js that automatically triggers the closing of the calendar after a date has been selected?

Currently, I am using Kalendae from https://github.com/ChiperSoft/Kalendae and I have to say it is fantastic. The best part is that I don't have to worry about dependencies. By default, the calendar pops up when a text box is selected and updates the ...

Having issues with accessing data from Informix database in PHP due to an undefined index?

I am encountering the following error multiple times per row: Notice: Undefined index: enviopre in /opt/lampp/htdocs/pruebax/pruebaxone.php on line 34 Notice: Undefined index: enviofra in /opt/lampp/htdocs/pruebax/pruebaxone.php on line 35 Notice: Undef ...

Creating dynamic email templates in Node.js

I am working on a project using the MEAN stack and I need to implement email functionality. I have created separate email templates, but I want to include a common header and footer in all of them. Route.js router .route('/api/user/register&a ...