running a for loop for multiple onclick events

I have a situation where I need to create an onclick event that performs multiple tasks.

There is a button labeled Add Item in the image below. When clicked, it should add the HTML code shown below:

var addItemHTML = '<tr class="hold-item">\
           <td><strong>'+typeField.value+': </strong></td>\
           <td><input type="text"></td>\
           <td><img class="cancel-item" src="icon/cancel.png" height="25px"></td>\
           </tr>';

Everything works fine up to this point, but now I want to be able to remove the added HTML elements one by one by clicking on each close icon, and I'm having trouble achieving this!

I've attempted to use the following JavaScript code:

  var cancelIcon = document.getElementsByClassName("cancel-icon");
  var holdElement = document.getElementsByClassName("hold-element");
 
  for(i=0;i < holdElement.length;i++){
   cancelIcon[i].onclick = function(){
     holdElement[i].remove();
   }
   
 }

Unfortunately, it doesn't seem to work. Can someone help me solve this issue?

Answer №1

Delegate!

Example

NOTE: Make sure to utilize tbody and addEventListener for the onclick event as well.

var addItemBtn = document.getElementById("add-item-btn");
var itemTable = document.getElementById("item-table");
var typeField = document.getElementById("type-field");

addItemBtn.addEventListener("click", function() {

  var addItemHTML = '<tr class="hole-element">\
               <td><strong>' + typeField.value + ': </strong></td>\
               <td><input type="text"></td>\
               <td><img class="cancel-icon" src="icon/cancel.png" height="25px"></td>\
               </tr>';

  itemTable.innerHTML += addItemHTML;
})

document.getElementById("item-table").addEventListener("click", function(e) {
  const tgt = e.target;
  if (tgt.classList.contains("cancel-icon")) tgt.closest("tr").remove();
});
.product_add {
  overflow: hidden;
}

.product_add_left_side {
  /* background: rgb(230,230,230);*/
  display: inline-block;
  float: left;
  padding: 10px;
}

.product_add_right_side {
  /*background: rgb(200,200,200);*/
  display: inline-block;
  float: left;
  padding: 10px;
}

.cancel-icon {
  transition: 0.3s;
  margin-left: 15px;
}

.cancel-icon:active {
  -webkit-transform: scale(0.9);
}
<div class="product_add">

  <div class="product_add_left_side">
    <img src="icon/image.jpg" height="220px">
  </div>

  <div class="product_add_right_side">
    <table>
      <tbody id="item-table">
        <tr>
          <td><strong>Name: </strong></td>
          <td><input type="text"></td>
        </tr>

        <tr>
          <td><strong>Unit: </strong></td>
          <td><input type="text"></td>
        </tr>

        <tr>
          <td><strong>Price: </strong></td>
          <td><input type="text"></td>
        </tr>

        <tr>
          <td><strong>In Stock: </strong></td>
          <td><input type="text"></td>
        </tr>

        <tr class="hole-element">
          <td><strong>Hello: </strong></td>
          <td><input type="text"></td>
          <td><img class="cancel-icon" src="icon/cancel.png" height="25px"></td>
        </tr>

        <tr class="hole-element">
          <td><strong>Hello: </strong></td>
          <td><input type="text"></td>
          <td><img class="cancel-icon" src="icon/cancel.png" height="25px"></td>
        </tr>
      </tbody>
    </table>

    <input type="text" id="type-field">
    <button id="add-item-btn">Add Item</button>
    <div id="demo"></div>
  </div>

</div>

<div id="load-product-js"></div>

Alternatively, it is recommended to implement a closure.

JavaScript closure inside loops – simple practical example

Furthermore, ensure consistency between 'cancel-icon' and 'cancel-item' class names.

Answer №2

It is recommended to utilize document.createElement() when creating new elements, and either use ParentNode.append() or Node.appendChild() when adding these elements to the DOM.
The benefits of using this approach include:

  • Reduced risk of invalidating HTML
  • Avoid accidental removal of existing element listeners
  • Simplified configuration of newly created elements (e.g., adding event listeners)

One drawback is that it may increase the length of your JavaScript code.

Nevertheless, employing this method of appending a new <tr> allowed me to easily reference it for removal when the cancel-button is pressed.

This means that with easy referencing, you can dynamically add rows with the desired behavior.

Note
I replaced

<td><strong></strong></td>
with <th></th> as the nested elements seemed to align with the semantic purpose of <th>.

I also attached the click-listener to a button containing the cancel icon because setting up a click-listener for elements other than <a>, <button>, or <input> can be more challenging to make accessible. You can still style the button to appear without border or background, displaying only the image as intended.

const itemTable = document.querySelector("#item-table");
const typeField = document.querySelector("#type-field");
document.querySelector("#add-item-btn").addEventListener("click", () => {
  let tr = document.createElement("tr");
  tr.classList.add("hole-element");
  
  let th = document.createElement("th");
  th.innerHTML = typeField.value + ":";
  th.setAttribute("style", "text-align: left");
  tr.append(th);
  
  let td = document.createElement("td");
  tr.append(td);
  
  let input = document.createElement("input");
  input.setAttribute("type", "text");
  td.append(input);
  
  td = document.createElement("td");
  tr.append(td);
  
  let button = document.createElement("button");
  button.classList.add("cancel-icon");
  button.addEventListener("click", () => {
    tr.remove();
  });
  td.append(button);
  
  let img = document.createElement("img");
  img.setAttribute("src", "icon/cancel.png");
  img.setAttribute("height", "25px");
  button.append(img);
  
  itemTable.append(tr);
  typeField.value = "";
});
th {text-align: left}
.cancel-icon{
  transition: 0.3s;
  margin-left: 15px;
}
.cancel-icon:active{transform: scale(0.9)}
<table id="item-table">
  <tr>
    <th>Name: </th>
    <td><input type="text"></td>
  </tr>
  <tr>
    <th>Unit: </th>
    <td><input type="text"></td>
  </tr>
  <tr>
    <th>Price: </th>
    <td><input type="text"></td>
  </tr>
  <tr>
    <th>In Stock: </th>
    <td><input type="text"></td>
  </tr>
</table>

<input type="text" id="type-field">
<button id="add-item-btn">Add Item</button>

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

Efficiently Summing Array Elements with Recursive Reduction

Find the sum of array element pairs by recursively consolidating them until only a single index remains. EXAMPLES: [1, 2, 3, 4, 5] => 48 Explanation: The next array would be [3, 5, 7, 9] because [1+2, 2+3, 3+4, 4+5] The next array would be [8, 12, 1 ...

Need help setting parsed values on jQuery Autocomplete after Keyup event?

I am using the Bing API to retrieve values by accessing this link: When I parse and append the results on keyup, it works fine. However, when I try to set the results on jQuery's autocomplete, it does not display properly. For example, you can view ...

Troubleshooting Tooltip Problem on Highcharts US Bubble Map

Using Highcharts in my React application, I have built a US Bubble Map. The version details for the libraries used are: "@highcharts/map-collection": "^2.1.0" "highcharts": "^11.1.0" "highcharts-react-official& ...

The subsequent code still running even with the implementation of async/await

I'm currently facing an issue with a function that needs to resolve a promise before moving on to the next lines of code. Here is what I expect: START promise resolved line1 line2 line3 etc ... However, the problem I'm encountering is that all t ...

Guide to inheriting and overriding text styles

I am looking for a way to customize the style of all h6 elements within reactjs/material-ui, without using themes. I have attempted the code below, among other methods: const useStyles = makeStyles({ someClass: { h6: { fontSize: &qu ...

How can I make sure addEventListener only responds to numbers and not images?

Currently, I am facing a dilemma with implementing a button that features an image on it and needs to be placed within another div. Despite successfully achieving this, I am struggling to comprehend the JavaScript code outlined in a tutorial I followed. Th ...

How can I verify if an unsupported parameter has been passed in a GET request using Express/Node.js?

Within my node.js backend, there is a method that I have: app.get('/reports', function(req, res){ var amount = req.param('amount'); var longitude = req.param('long'); var latitude = req.param('lat'); var di ...

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 ...

Changing the MIME type of a JavaScript file in a Jade/Pug environment to text/html

Hi there, I've been experimenting with jade/pug to get my node.js backend to render the front-end pages. However, I'm facing some issues when trying to include JavaScript for certain functionalities. Whenever I try to load it, I encounter this er ...

Implement ng-model on an input field that is pre-filled with a value from a different model within the Angular

One challenge I am facing involves pre-populating an input field with user information, such as their email address or first name, if that data is available. Initially, I set the value of the input field using $scope.userData. However, when I add an ng-mo ...

Issue with interaction between php and jQuery on click event

I had been facing a challenge with this issue (after checking this site) where I discovered that I forgot to use .on to delegate a click function that should be triggered when clicking on a piece of dynamically generated HTML in PHP. I have now included t ...

The ƒ character doesn't seem to be a match for the JavaScript regex

I am facing a requirement to only allow (extended) ASCII characters in my input. As a solution, I've implemented a JavaScript regex pattern like this: /^[\x20-\xff]+$/.test("helloê¿£×جáƒ") However, this doesn't work as expect ...

Building intricate hierarchical menus with Material-UI 4.9

I am currently incorporating the @material-ui/core library into my application and aiming to implement a nested menu feature. I have referred to the material.io specification which discusses nested menus, but unfortunately, the material-ui library does not ...

Updating the parameters when clicking on each pagination button: A guide

Does anyone have advice on implementing pagination? I am currently working on loading a datatable with a few records initially. Once the page is loaded, I want to be able to click on pagination buttons like next or any pagination buttons to display a new s ...

placing the grid elements side by side within the grid system

Hi there, I've been experimenting with React and the UNSPLASH API. When I search for a term, I can see a list of details in the console. After running the map function, I display the images on my screen. What I want to achieve is to have a 12-column g ...

Error: The property 'getClientRects' cannot be read because it is null

I'm brand new to learning about React and I've been attempting to incorporate the example found at: Unfortunately, I've hit a roadblock and can't seem to resolve this pesky error message: TypeError: Cannot read property 'getClient ...

Employing angular-ui-bootstrap to display pop-up notifications

I am new to using Angular and TypeScript and I am attempting to create a popup when an image is clicked. I came across a post on Stack Overflow that provides a solution using IMODALSERVICE. How to utilize angular-ui-bootstrap modals with TypeScript? Howe ...

Assistance with JSONP (Without the use of jQuery)

I've been putting in a lot of effort trying to understand how to make a JSONP request, but all the reference materials I find are full of jQuery examples. I can go through the jQuery source code, but I prefer a straightforward and simple example. I&ap ...

${resource} and ${promise} are both returning undefined values

Encountering the following error: TypeError: Cannot call method 'then' of undefined while working with the code below: App.controller('MainCtrl', ['$scope', 'Main', 'MainFilter', function($scope, Main, M ...

Discord.js Discord bot error: 'gateway' down

Hello, I could really use some assistance. Two days back, my discord bot began crashing unexpectedly. The error that keeps popping up is: events.js:367 throw err; // Unhandled 'error' event ^ Error [ERR_UNHANDLED_ERROR]: An uncau ...