I have a basic Javascript local implementation of a like button and a number that increments every time the button is clicked. The section that contains the like button and the number is rendered by EJS.
HTML
<section id="post-section"> <% posts.forEach(function(post) { %> <article class="post-container"> <div class="post-title-container"> <a href="/post/<%=post.title%>"><%=post.title%></a> </div> <div class="post-card-container"> <img class="post-user-image" src="/img/user.png" alt="Imagem do utilizador"> <p class="post-user-name"><%=post.name%></p> <% if (post.content.length > 100) { %> <span class="post-body"><%=post.content.substring(0, 100) + " ..."%></span> <% } else { %> <span class="post-body"><%=post.content%></span> <% } %> <span class="post-date"> <%=post.date%> </span> <span class="post-like"> <i class="far fa-heart"></i> </span> <p class="post-like--count"> 0 </p> </div> </article> <hr> <% }); %> </section>
JavaScript
window.onload = function () { postLikeCount(); } function postLikeCount() { let likeCount = document.querySelectorAll('.post-like--count'); let postLikeButtons = document.querySelectorAll('.post-like .far.fa-heart'); postLikeButtons.forEach(function (postLikeButton) { postLikeButton.addEventListener('click', function () { postLikeButton.classList.toggle('fas'); likeCount.forEach(function (like) { let number = like.textContent; if (postLikeButton.classList.contains('fas')) { number++; like.textContent = number; } else { number--; like.textContent = number; } }); }); }); }
My issue is, the number increments correctly when the ‘click’ event is fired, however, it doesn’t only increment on the button that was clicked, if I have multiple posts (as seen in the HTML), it will also increment the number on those buttons.
While debugging, the behavior seems correct. likeCount returns me a NodeList with the size of whatever is the amount of buttons on that page, and when looping, like also gives correct behavior as it grabs a single element, yet, every element gets incremented.
Advertisement
Answer
I think you have too much nesting in your code and your selector do not target a specific element but all the ones having the same classes.
You could simplify this way:
function postLikeCount() { document .querySelectorAll(".post-like .far.fa-heart") .forEach(function (postLikeButton) { postLikeButton.addEventListener('click', function () { // this is the clicked element this.classList.toggle("fas"); // read its sibling count let number = this.parentNode.nextElementSibling.innerText; if (this.classList.contains("fas")) { number++; this.parentNode.nextElementSibling.innerText = number; } else { number--; this.parentNode.nextElementSibling.innerText = number; } }); }); }