Only the first created button works in JS - javascript

Trying to make the "close-circle" button work. this function will create the button multiple times if there are multiple items, each of them is created with a specific id, and once it is clicked, will delete all the data based on that id. Somehow ONLY the first created button works, the rest just do nothing. I believe there is something wrong with the way of creating the addEventListener.
if (inCartItem) {
productsContainer.innerHTML = '';
// item means each item in the object which is the inCartItem
Object.values(inCartItem).map(item => {
productsContainer.innerHTML += `
<div class ="product-incart">
<ion-icon id ="${item.Id}CloseBtm" name="close-circle"></ion-icon>
<img src="${item.src}">
<span>${item.Productname}</span>
</div>
<div class="price-incart">$${item.Price}</div>
<div class="quantity">
<ion-icon name="caret-back-outline"></ion-icon>
<span>${item.inCart}</span>
<ion-icon name="caret-forward-outline"></ion-icon>
</div>
<div class="total">
$${item.inCart * item.Price},00
</div>
`
console.log(item.Id);
document.getElementById(item.Id + "CloseBtm").addEventListener("click", ("click", () => { removeAll(item); }));
})

Related

adding quantity through buttons to a shopping cart item - Javascript

I am working on a personal project, just practicing on my own and getting to know and familiarized with the language.I am trying to learn by doing so I am creating a shopping cart and I came across a situation that I can not find a proper solution.
I have a list on my shopping cart already rendered of n items. When I 'click' on a plus button to add quantity to an item, it only adds to the quantity to the item that is first on the list and the 'price' of the second item.
Thank you in advance!
function renderCarrito(){
// carritoEl.innerHTML = "";
while(carritoEl.firstChild){
carritoEl.removeChild(carritoEl.firstChild)
};
carrito.forEach((item) =>{
carritoEl.innerHTML += `
<li class="buyItem">
<img src=${item.image}>
<div class="productCartInfo">
<h5 class="prdTitle">${item.title}</h5>
<h6>${item.price}</h6>
<div class="qnty">
<div>
<button class="mbtn">-</button>
<span class="countOfProduct">${item.cantidad}</span>
<button class="pbtn">+</button>
</div>
<div><i class="fas fa-times-circle dltProduct" data-id="${item.id}"></i></div>
</div>
</div>
</li>
`
const plusBtn = document.querySelectorAll('.pbtn');
const minusBtn = document.querySelectorAll('.mbtn');
const count = document.querySelector('.countOfProduct');
plusBtn.forEach(pbtn =>{
pbtn.addEventListener('click', () => {
item.cantidad++;
count.innerHTML = item.cantidad;
carritoSumaTotal();
})});
})
carritoSumaTotal();
}
``

How can I remove the parent div of a looped element?

Im trying to remove the parent div of a text, that is looped for every flash.
I tried getting the Element by Id but it only deletes the first flashed text.
This is the code:
{% for message in get_flashed_messages() %}
<div class="todolistitems">
<b id="todoitem">{{ message }}</b>
<button onClick="testremove()" id="deletetodo"><i class="material-icons">done</i></button>
<br>
</div>
<script>
var msg = document.getElementById("todoitem")
function testremove() {
msg.parentNode.remove();
}
</script>
{% endfor %}
Here's a way to handle this.
First, don't use the same ID more than once. But, there's no need to use them at all here. We can listen to document for a click event and then test to see if it's a delete button. If so, remove the element associated with that button. How to find that element? Easiest to group them together inside a div container and then use the ever-handy .closest(parentSelector) method. When we listen for the delete click, we need to consider that depending on where in that button the user clicks, the target of the event will either be the button or the icon within
window.addEventListener('DOMContentLoaded', () => {
document.addEventListener('click', e => {
if (['material-icons', 'btn-delete'].some(c => e.target.classList.contains(c))) {
let targ = e.target.closest('.todo-item')
console.log(targ)
targ.parentNode.removeChild(targ)
}
})
})
<div class="todolistitems">
<div class='todo-item'>
<b class='msg'>todo1</b>
<button class='btn-delete'><i class="material-icons">done</i></button>
</div>
<div class='todo-item'>
<b class='msg'>todo2</b>
<button class='btn-delete'><i class="material-icons">done</i></button>
</div>
<div class='todo-item'>
<b class='msg'>todo3</b>
<button class='btn-delete'><i class="material-icons">done</i></button>
</div>
</div>

All buttons effect only the first button, but not themselves

card.vue is the template with the toggleLike method and the button tag
<template>
<div
class="p-24 grid grid-cols-1 sm:grid-cols-1 md:grid-cols-3 lg:grid-cols-3 xl:grid-cols-3 gap-12"
>
<div
v-for="movie in movies"
:key="movie.imdbID"
>
<card :movieData="movie" />
</div>
</div>
</template>
I have dynamically generated buttons, but whichever I click, every time the first one gets "selected" or diselected (depends on its previous state).
I want to toggle them independently.
<button #click="toggleLike()" class="mr-2">
<i id="but" class="fa-thumbs-up" :class="{ fas: isLiked, far: !isLiked }"></i>
toggleLike() {
if(this.movieData.likes == 0) {
$('#but').removeClass('far');
$('#but').addClass('fas');
this.movieData.likes+1;
}
else {
$('#but').removeClass('fas');
$('#but').addClass('far');}
return this.$store.dispatch("updateMovieLikes", {
imdbID: this.movie.imdbID,
});
},
You should put more code on how you structure your generated buttons, is that an array? If it is then your isLiked should be an array
<div v-for="movie in movies">
<button #click="toggleLike(movie)" class="mr-2">
<i id="but" class="fa-thumbs-up" :class="movie.likes === 0 ? 'fas' : 'far'"></i>
</button>
</div>
methods: {
toggleLike(movie) {
movie.likes = movie.likes === 0 ? 1 : 0;
this.$store.dispatch("updateMovieLikes", {
imdbID: this.movie.imdbID,
});
}
}
Edit: Just a tip you dont need jquery in vue
Welcome to SO, You could actually shift-away from jquery with vue. You already made a dynamic class binding on your but element therefore you can remove the jquery class handling on your method.
template:
<button #click="toggleLike()" class="mr-2">
<i class="fa-thumbs-up" :class="isLiked ? 'fas' : 'far'"></i>
</button>
method:
toggleLike() {
// Add here how you handle the toggling of isLiked data
if (this.movieData.likes === 0) this.movieData.likes++;
return this.$store.dispatch("updateMovieLikes", {
imdbID: this.movie.imdbID,
});
},
Note.
I'm not sure how you generate the buttons dynamically, can you show it on your question? (can't comment yet). You should also show how do you handle the toggling of your isLiked data.

Javascript event-listener not working when trying to link to another page

I'm currently trying to display an individual.html page based off what the user clicks on a products.html page. For example, clicking on product1 would show the individual page for product1 and clicking on product2 would show the individual page for product2 etc...
I currently have a UI class in my app.js file which holds the logic for displaying information.
There is a function in there called displayIndividualProject() which has an event listener that says, "If a card is clicked (if (event.target.classList.contains('img-container'))), then inject this HTML structure into the individual.html" page. However, after I click on it, it's not injecting the sequence.
Also, displayIndividualProduct is meant for the individual.html page while displayProducts is meant for the product.html page.
Here is what part of my UI class looks like:
const individualProductsDOM = document.querySelector('.single-product');
class UI{
displayIndividualProduct(){
document.addEventListener("click", event => {
if (event.target.classList.contains('img-container'))
individualProductsDOM.innerHTML =
`
<div class='section-title'>
<h2>${product.title}</h2>
</div>
<div class='indi-img-container'>
<img src=${product.image} data-id='${product.id} alt="">
</div>
<div class="product-footer">
<h3>Estimated Cost: $ <span class='item-total'>0</span></h3>
<button class='bag-btn-2' data-id='${product.id}'>
<i class='fas fa-shopping-cart'></i>
add to cart
</button>
</div>
`
})
individualProductsDOM.innerHTML += `injected`;
}
displayProducts(products){
let result = '';
products.forEach(product => {
result += `
<article class="product" data-id='${product.id}'>
<div class='img-container'>
<a href='/individual.html'>
<img src=${product.image} alt="product" class='product-img' data-id='${product.id}'>
<button class='bag-btn' data-id='${product.id}'>
<i class='fas fa-shopping-cart'></i>
add to cart
</button>
</a>
</div>
<h3>${product.title}</h3>
<h4>$${product.price}/roll</h4>
</article>
`
});
//insert the products into the productsDOM
productsDOM.innerHTML = result;
}
}
and this is being called at the bottom of my JS through ui.displayIndividualProduct();
document.addEventListener("DOMContentLoaded", () => {
const ui = new UI();
const products = new Products();
// setup app
ui.setupAPP();
//get all products
products.getProducts().then(products => {
//first display, then save, and then connect the add cart buttons
ui.displayProducts(products);
Storage.saveProducts(products);
}).then( () => {
ui.getBagButtons();
});
ui.displayIndividualProduct();
});
any help would be appreciated!

Target only 1 button in Angular

Im getting the values in a div from the DB and displaying using ng-repeat:
<div ng-controller = "myTest">
<div ng-repeat="name in names">
<h4>{{name.name}}</h4>
<button ng-class="{'active': isActive}" ng-click="test()" >me</button>
</div>
</div>
In my controller I have:
$scope.test= function(){
$scope.isActive = !$scope.isActive;
}
I have defined a class isActive in my css and that is applied/removed to the button on click. There are 5 results so 5 divs are created cause of ng-repeat and 5 buttons(1 for each respective div). The problem is that every button (all 5 of them) is getting that class. I want the class to be applied/removed only to the button clicked. How can I achieve this?
You can try something like this :
<div ng-controller="myTest">
<div ng-repeat="name in names">
<h4>{{name.name}}</h4>
<button ng-class="{ active : name.isActive }"
ng-click="name.isActive = !name.isActive">me</button>
</div>
</div>
Hope this will help.
You need to keep track of each button status.
One way will be to passing the name or anything that uniquely identify the button to your function:
<div ng-controller = "myTest">
<div ng-repeat="name in names">
<h4>{{name.name}}</h4>
<button ng-class="{'active': buttons[name].isActive}" ng-click="test(name)" >me</button>
</div>
</div>
$scope.buttons = {};
$scope.test= function(name){
$scope.buttons[name].isActive = !$scope.buttons[name].isActive;
}
I created a plunk that answers this question without modifying your source array.
Your function becomes
vm.test = function(buttonIndex) {
//Clear the class if you press the same button again
if (vm.buttonIndex === buttonIndex) {
vm.buttonIndex = undefined;
} else {
vm.buttonIndex = buttonIndex;
}
};
And your HTML is
<div ng-repeat="name in main.names track by $index">
<h4>{{name.name}}</h4>
<button ng-class="{'active': main.buttonIndex===$index}" ng-click="main.test($index)">me</button>
</div>

Categories

Resources