I want a click event in the table when I am generating a dynamic table. I tried it like this.
var cartItem=[{"id":2,"title":"Mens Casual Premium Slim Fit T-Shirts ","price":22.3,"description":"Slim-fitting style, contrast raglan long sleeve, three-button henley placket, light weight & soft fabric for breathable and comfortable wearing. And Solid stitched shirts with round neck made for durability and a great fit for casual fashion wear and diehard baseball fans. The Henley style round neckline includes a three-button placket.","category":"men's clothing","image":"https://fakestoreapi.com/img/71-3HjGNDUL._AC_SY879._SX._UX._SY._UY_.jpg","rating":{"rate":4.1,"count":259}}]
function getcartDetails() {
document.getElementById("cartItemShow").innerHTML = "";
for (var get in cartItem) {
var tr = document.createElement("tr");
var tdTitle = document.createElement("td");
var tdImage = document.createElement("td");
var tdDel = document.createElement("td");
var img = document.createElement("img");
var button = document.createElement("button");
// ===============================================
img.src = cartItem[get].image;
img.width = 70;
tdTitle.innerHTML = cartItem[get].title;
button.innerText="delete";
//button.span.onclick = "delete()"; i want apply an event
//===================================================
tdImage.appendChild(img);
tdDel.appendChild(button);
tr.appendChild(tdTitle);
tr.appendChild(tdImage);
tr.appendChild(tdDel);
console.log("this is id :" get);
document.getElementById("cartItemShow").appendChild(tr);
}
}
getcartDetails()
/*function delete(){
alert("hello")
}*/
<div >
<button data-bs-toggle="collapse" data-bs-target="#showTable">[<span id="itemCount"></span>] Your cart</button>
<table id="showTable">
<thead>
<tr>
<th scope="col">Title</th>
<th scope="col">Image</th>
<th scope="col">action</th>
</tr>
</thead>
<tbody id="cartItemShow"></tbody>
</table>
</div>
But I am unable to add on click event. Expected Output: After clicking on the delete button, it should appear an alert message with string "hello".
CodePudding user response:
Set a click eventListener on button
:
button.addEventListener("click", () => {
alert("Hello, World!");
});
Full code:
var cartItem=[{"id":2,"title":"Mens Casual Premium Slim Fit T-Shirts ","price":22.3,"description":"Slim-fitting style, contrast raglan long sleeve, three-button henley placket, light weight & soft fabric for breathable and comfortable wearing. And Solid stitched shirts with round neck made for durability and a great fit for casual fashion wear and diehard baseball fans. The Henley style round neckline includes a three-button placket.","category":"men's clothing","image":"https://fakestoreapi.com/img/71-3HjGNDUL._AC_SY879._SX._UX._SY._UY_.jpg","rating":{"rate":4.1,"count":259}}]
function getcartDetails() {
document.getElementById("cartItemShow").innerHTML = "";
for (var get in cartItem) {
var tr = document.createElement("tr");
var tdTitle = document.createElement("td");
var tdImage = document.createElement("td");
var tdDel = document.createElement("td");
var img = document.createElement("img");
var button = document.createElement("button");
// ===============================================
img.src = cartItem[get].image;
img.width = 70;
tdTitle.innerHTML = cartItem[get].title;
button.innerText="delete";
button.addEventListener("click", () => {
alert("Hello, World!");
});
//button.span.onclick = "delete()"; i want apply an event
//===================================================
tdImage.appendChild(img);
tdDel.appendChild(button);
tr.appendChild(tdTitle);
tr.appendChild(tdImage);
tr.appendChild(tdDel);
console.log("this is id :" get);
document.getElementById("cartItemShow").appendChild(tr);
}
}
getcartDetails()
/*function delete(){
alert("hello")
}*/
<div >
<button data-bs-toggle="collapse" data-bs-target="#showTable">[<span id="itemCount"></span>] Your cart</button>
<table id="showTable">
<thead>
<tr>
<th scope="col">Title</th>
<th scope="col">Image</th>
<th scope="col">action</th>
</tr>
</thead>
<tbody id="cartItemShow"></tbody>
</table>
</div>
CodePudding user response:
so, the main reason you get an error is that you are trying to use delete operator as a function.
First, you have to change the function delete to something else, since delete is an operator in Javascript, in my case, I changed it to deleteMe()
second, is change
//button.span.onclick = "delete()"; i want apply an event
to
button.onclick = function (){deleteMe();} //i want apply an event
the reason I have put that in the anonymous function is that I don't want to be triggered after loading the page.
the rest of your code is working well.
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Bootstrap CSS -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<link href="css/jquery-ui.min.css" rel="stylesheet">
<script src="js/jquery-3.6.0.min.js"></script>
<script src="js/jquery-ui.min.js"></script>
<title>Stack25</title>
</head>
<body>
<div >
<button data-bs-toggle="collapse" data-bs-target="#showTable">[<span
id="itemCount"></span>] Your cart
</button>
<table id="showTable">
<thead>
<tr>
<th scope="col">Title</th>
<th scope="col">Image</th>
<th scope="col">action</th>
</tr>
</thead>
<tbody id="cartItemShow"></tbody>
</table>
</div>
<script src="js/popper.min.js"></script>
<script src="js/bootstrap.min.js"></script>
<script>
var cartItem = [{
"id": 2,
"title": "Mens Casual Premium Slim Fit T-Shirts ",
"price": 22.3,
"description": "Slim-fitting style, contrast raglan long sleeve, three-button henley placket, light weight & soft fabric for breathable and comfortable wearing. And Solid stitched shirts with round neck made for durability and a great fit for casual fashion wear and diehard baseball fans. The Henley style round neckline includes a three-button placket.",
"category": "men's clothing",
"image": "https://fakestoreapi.com/img/71-3HjGNDUL._AC_SY879._SX._UX._SY._UY_.jpg",
"rating": {"rate": 4.1, "count": 259}
}]
function getcartDetails() {
document.getElementById("cartItemShow").innerHTML = "";
for (var get in cartItem) {
var tr = document.createElement("tr");
var tdTitle = document.createElement("td");
var tdImage = document.createElement("td");
var tdDel = document.createElement("td");
var img = document.createElement("img");
var button = document.createElement("button");
// ===============================================
img.src = cartItem[get].image;
img.width = 70;
tdTitle.innerHTML = cartItem[get].title;
button.innerText = "delete";
//button.span.onclick = "delete()"; i want apply an event
button.onclick = function (){deleteMe();} //i want apply an event
//===================================================
tdImage.appendChild(img);
tdDel.appendChild(button);
tr.appendChild(tdTitle);
tr.appendChild(tdImage);
tr.appendChild(tdDel);
console.log("this is id :" get);
document.getElementById("cartItemShow").appendChild(tr);
}
}
getcartDetails();
function deleteMe(){
alert("hello");
}
// function delete(){
// alert("hello");
// }
</script>
</body>
</html>
CodePudding user response:
you can accomplish that by adding class to the button element button.setAttribute("class", "delete");
also i will add data-id attribute to define the id value of clicked delete button in table
button.dataset.id = cartItem[get].id;
and add click event on this class jquery
$(document).on('click', '.delete', function() {
alert("delete : " this.dataset.id)
});
or using native JS
var elements = document.getElementsByClassName("delete");
var deleteRow = function() {
alert("delete : " this.dataset.id)
};
for (var i = 0; i < elements.length; i ) {
elements[i].addEventListener('click', deleteRow, false);
}
your code after edits :
<div ><div >
<button data-bs-toggle="collapse" data-bs-target="#showTable">[<span id="itemCount"></span>] Your cart</button>
<table id="showTable">
<thead>
<tr>
<th scope="col">Title</th>
<th scope="col">Image</th>
<th scope="col">action</th>
</tr>
</thead>
<tbody id="cartItemShow"></tbody>
</table>
</div>
<script>
var cartItem=[{"id":2,"title":"Mens Casual Premium Slim Fit T-Shirts ","price":22.3,"description":"Slim-fitting style, contrast raglan long sleeve, three-button henley placket, light weight & soft fabric for breathable and comfortable wearing. And Solid stitched shirts with round neck made for durability and a great fit for casual fashion wear and diehard baseball fans. The Henley style round neckline includes a three-button placket.","category":"men's clothing","image":"https://fakestoreapi.com/img/71-3HjGNDUL._AC_SY879._SX._UX._SY._UY_.jpg","rating":{"rate":4.1,"count":259}}]
function getcartDetails() {
document.getElementById("cartItemShow").innerHTML = "";
for (var get in cartItem) {
var tr = document.createElement("tr");
var tdTitle = document.createElement("td");
var tdImage = document.createElement("td");
var tdDel = document.createElement("td");
var img = document.createElement("img");
var button = document.createElement("button");
// ===============================================
img.src = cartItem[get].image;
img.width = 70;
tdTitle.innerHTML = cartItem[get].title;
button.innerText="delete";
button.setAttribute("class", "delete");
button.dataset.id = cartItem[get].id;
//button.span.onclick = "delete()"; i want apply an event
//===================================================
tdImage.appendChild(img);
tdDel.appendChild(button);
tr.appendChild(tdTitle);
tr.appendChild(tdImage);
tr.appendChild(tdDel);
console.log("this is id :" get);
document.getElementById("cartItemShow").appendChild(tr);
}
}
getcartDetails()
$(document).on('click', '.delete', function() {
alert("delete : " this.dataset.id)
});
CodePudding user response:
A couple of things to keep in mind.
delete
is a reserved keyword. So you have to rename your function. Give it a name so that you instantly know what it does and what is being deleted.- Looping over arrays should be done with
for
,forEach
orfor...of
.for...in
is used to loop over objects. See this thread to understand the difference betweenfor...of
andfor...in
.
I'm assuming that you want to know which button is clicked. Therefor set value
of the button
equal to the id
of the cartItem
. This way you can get the id
from the clicked button.
You could add an event listener for every button, but it's better (more performant) to use event delegation. This is a method of using a single event listener to capture the events of the children. In this case you'd a single click event listener to an element high up the DOM and uncover which element has been clicked. If one of our buttons is clicked, then execute the deleteCartItem
function.
var cartItems = [{
"id": 2,
"title": "Mens Casual Premium Slim Fit T-Shirts ",
"price": 22.3,
"description": "Slim-fitting style, contrast raglan long sleeve, three-button henley placket, light weight & soft fabric for breathable and comfortable wearing. And Solid stitched shirts with round neck made for durability and a great fit for casual fashion wear and diehard baseball fans. The Henley style round neckline includes a three-button placket.",
"category": "men's clothing",
"image": "https://fakestoreapi.com/img/71-3HjGNDUL._AC_SY879._SX._UX._SY._UY_.jpg",
"rating": {
"rate": 4.1,
"count": 259
}
}];
// Delete cart item with id.
function deleteCartItem(id) {
alert(`Delete item id: ${id}`);
}
// Listen for all delete button clicks.
document.addEventListener('click', ({ target }) => {
console.log(target);
if (target.tagName === 'BUTTON' && target.classList.contains('delete-cart-item')) {
deleteCartItem(target.value);
}
});
function getcartDetails() {
document.getElementById("cartItemShow").innerHTML = "";
for (const cartItem of cartItems) {
var tr = document.createElement("tr");
var tdTitle = document.createElement("td");
var tdImage = document.createElement("td");
var tdDel = document.createElement("td");
var img = document.createElement("img");
var button = document.createElement("button");
// ===============================================
img.src = cartItem.image;
img.width = 70;
tdTitle.innerHTML = cartItem.title;
button.value = cartItem.id;
button.className = 'delete-cart-item';
button.innerText = "delete";
//===================================================
tdImage.appendChild(img);
tdDel.appendChild(button);
tr.appendChild(tdTitle);
tr.appendChild(tdImage);
tr.appendChild(tdDel);
console.log("this is id :" cartItem.id);
document.getElementById("cartItemShow").appendChild(tr);
}
}
getcartDetails()
<div >
<button data-bs-toggle="collapse" data-bs-target="#showTable">[<span id="itemCount"></span>] Your cart</button>
<table id="showTable">
<thead>
<tr>
<th scope="col">Title</th>
<th scope="col">Image</th>
<th scope="col">action</th>
</tr>
</thead>
<tbody id="cartItemShow"></tbody>
</table>
</div>
CodePudding user response:
Use event delegation. Instead of attaching listeners to every button add one listener to the parent element (in this case the tbody
element), and have that capture all the events from its child elements as they "bubble up" the DOM, and have that listener call a function to update the table.
I've used a slightly more modern approach to building the rows in my answer that you may find useful. Links to all the relevant MDN documentation are at the end of the answer.
const data = [{"id":1,"title":"Fjallraven - Foldsack No. 1 Backpack, Fits 15 Laptops","price":109.95,"description":"Your perfect pack for everyday use and walks in the forest. Stash your laptop (up to 15 inches) in the padded sleeve, your everyday","category":"men's clothing","image":"https://fakestoreapi.com/img/81fPKd-2AYL._AC_SL1500_.jpg","rating":{"rate":3.9,"count":120}},{"id":2,"title":"Mens Casual Premium Slim Fit T-Shirts ","price":22.3,"description":"Slim-fitting style, contrast raglan long sleeve, three-button henley placket, light weight & soft fabric for breathable and comfortable wearing. And Solid stitched shirts with round neck made for durability and a great fit for casual fashion wear and diehard baseball fans. The Henley style round neckline includes a three-button placket.","category":"men's clothing","image":"https://fakestoreapi.com/img/71-3HjGNDUL._AC_SY879._SX._UX._SY._UY_.jpg","rating":{"rate":4.1,"count":259}},{"id":3,"title":"Mens Cotton Jacket","price":55.99,"description":"great outerwear jackets for Spring/Autumn/Winter, suitable for many occasions, such as working, hiking, camping, mountain/rock climbing, cycling, traveling or other outdoors. Good gift choice for you or your family member. A warm hearted love to Father, husband or son in this thanksgiving or Christmas Day.","category":"men's clothing","image":"https://fakestoreapi.com/img/71li-ujtlUL._AC_UX679_.jpg","rating":{"rate":4.7,"count":500}},{"id":4,"title":"Mens Casual Slim Fit","price":15.99,"description":"The color could be slightly different between on the screen and in practice. / Please note that body builds vary by person, therefore, detailed size information should be reviewed below on the product description.","category":"men's clothing","image":"https://fakestoreapi.com/img/71YXzeOuslL._AC_UY879_.jpg","rating":{"rate":2.1,"count":430}},{"id":5,"title":"John Hardy Women's Legends Naga Gold & Silver Dragon Station Chain Bracelet","price":695,"description":"From our Legends Collection, the Naga was inspired by the mythical water dragon that protects the ocean's pearl. Wear facing inward to be bestowed with love and abundance, or outward for protection.","category":"jewelery","image":"https://fakestoreapi.com/img/71pWzhdJNwL._AC_UL640_QL65_ML3_.jpg","rating":{"rate":4.6,"count":400}}];
// Get the `tbody` element
const cartItemShow = document.getElementById('cartItemShow');
// Add an event listener to it. It watches out for all the
// events that bubble up from its child elements
cartItemShow.addEventListener('click', handleClick, false);
// This function checks to see if the element that
// was clicked on was the delete button. If it was
// it gets the id from the button's dataset, and uses
// that to create a selector which cartItemShow can use
// to remove a row with the same id
function handleClick(e) {
if (e.target.matches('.delete')) {
const { id } = e.target.dataset;
const selector = `tr[data-id="${id}"]`;
cartItemShow.querySelector(selector).remove();
}
}
function buildRows(data) {
// `map` over the array, and for each item...
const html = data.map(item => {
// Destructure the id, title, and image
// from the item object
const { id, title, image } = item;
// Then return some HTML in the form of a
// template literal/string. It looks neater
// than creating lots of DOM elements, and is
// easier to understand. I'm adding the id to both
// the row element as well as the button. When the
// button is clicked the `handleClick` function
// will be called, and the row with the same id
// will be removed from the table
return `
<tr data-id=${id}>
<td>${title}</td>
<td><img src="${image}" /></td>
<td>
<button
data-id=${id}
type="button"
>
Delete
</button>
</td>
</tr>
`;
// Make sure you `join` up the array
// that `map` returns at the end of the iteration
}).join('');
// Add the HTML string to the table body
cartItemShow.insertAdjacentHTML('beforeend', html);
}
buildRows(data);
img { width: 100px; height: 100px }
td { width: 33%; text-align: center; }
.delete:hover { cursor: pointer; background-color: #fffff0; }
<div >
<button data-bs-toggle="collapse" data-bs-target="#showTable">[<span id="itemCount"></span>] Your cart</button>
<table id="showTable">
<thead>
<tr>
<th scope="col">Title</th>
<th scope="col">Image</th>
<th scope="col">action</th>
</tr>
</thead>
<tbody id="cartItemShow"></tbody>
</table>
</div>
Additional documentation