简体   繁体   中英

How can I make this click counter work properly?

I'm making a Marvel API project. I added a Like button so it could count the likes, but everytime I click any like button the only counter adding numbers is the first one. Can anyone tell me how I do this properly?

在此处输入图片说明

The problem is because the ID is being made by a for, so how could I solve this?

This is my JS code (on the js file of my project) :

success: function(data)
{
    footer.innerHTML = data.attributionHTML;
    var string = "";
    string += "<div class='row'>";

    for (var i = 0; i < data.data.results.length; i++)
    {
        var element = data.data.results[i];                   
        string += '<div class="col-md-3" align="center">';                 
        string += "<img src='" + element.thumbnail.path + "/portrait_fantastic." + element.thumbnail.extension + "'/>";                       
        string += '<button class="btn btn-success" onClick="testo()"><i class="fas fa-thumbs-up"></i> | <a id="likes">0</a></button>';
        string += "<h3>" + element.title + "</h3>";                                                  
        string += "</div>";

        if ((i + 1) % 4 == 0) 
        {
            string += "</div>";
            string += "<div class='row'>";
        }
    }

    marvelContainer.innerHTML = string;
}

And this is my onclick function (It is on my html file because it wont work on my js file)

<script>
var likes=0;
function testo()
{
    likes += 1;
    document.getElementById("likes").innerHTML = likes;
}
</script>

That is because all your buttons are being generated with the same id="likes" and then you are changing the HTML with document.getElementById("likes").innerHTML = likes; for your code to work properly you will need to use a different approach, maybe adding a data-* attribute to your buttons and then change the likes by the data-* atribute using .getAttribute('data-id-something').innerHTML instead of document.getElementById("likes").innerHTML . Or even better in this case you can give the buttons a class name and handle it with: document.getElementsByClassName("like-btn")

You can check the last option in this example:

  var init = function(data){ var string =""; string += "<div class='row'>"; for(var i = 0; i<4; i++) { // var element = data.data.results[i]; string += '<div class="col-md-3" align="center">'; string += "<img src='/portrait_fantastic.jgeg'/>"; string += '<button class="btn btn-success" onClick="testo('+i+')"><i class="fas fa-thumbs-up"></i> | <span class="like-btn">0</span></button>'; string += "<h3>Element title</h3>"; string += "</div>"; if((i+1) % 4 ==0) { string += "</div>"; string += "<div class='row'>"; } } document.getElementById("marvelContainer").innerHTML = string; } init(); 
 <script> var likes=0; function testo(id) { var btn = document.getElementsByClassName("like-btn"); likes = parseFloat(btn[id].innerHTML); likes += 1; btn[id].innerHTML = likes; } </script> <div id="marvelContainer"></div> 

I hope it will help you...

  • Gave the buttons a class, as that is what is going to be clicked.
  • Changed the link element to a span. Having a link in a button doesn't make much sense, as you can't "not" click the button and click the link.
  • Removed the inline onclick for the link and added an event listener logically on all the buttons.
  • The click logic finds the nested span in the button
    • It takes the data attribute on the span, turns it into an integer, and increments it
    • It then updates the data attribute value for the next click
    • And finally it updates the visible text that the user can see

EDIT

  • Changed it to bind the click event listener on the span as well and stop propagation on the click event. Actually clicking the span was causing the click event to register for the span, and not the button.

 // fake out some data for the element generation var data = { data: { results: [ { thumbnail: { path: '/path1', extension: 'jpg', title: 'Element1' } } ,{ thumbnail: { path: '/path2', extension: 'png', title: 'Element2' } } ,{ thumbnail: { path: '/path3', extension: 'gif', title: 'Element3' } } ] } }; // fake out the container the elements are built to var marvelContainer = document.querySelector('#container'); var string = "<div class='row'>"; for (var i = 0; i < data.data.results.length; i++) { var element = data.data.results[i]; string += '<div class="col-md-3" align="center">'; string += "<img src='" + element.thumbnail.path + "/portrait_fantastic." + element.thumbnail.extension + "'/>"; // put a class on the button // also removed the id and inline onclick // change the id on the link to a class // also initialized the data-likes on the link to zero string += '<button class="btn btn-success likes-button"><i class="fas fa-thumbs-up"></i> | <span class="likes" data-likes="0">0</span></button>'; string += "<h3>" + element.title + "</h3>"; string += "</div>"; if ((i + 1) % 4 == 0) { string += "</div>"; string += "<div class='row'>"; } } marvelContainer.innerHTML = string; document.querySelectorAll('.likes-button, .likes').forEach(function(likeButton){ likeButton.addEventListener('click', incrementLikes); }); function incrementLikes (e) { e.stopPropagation(); // find the inner likes element of the button var likes = e.target.querySelector('.likes') || e.target; // increment the likes var incrementedLikes = parseInt(likes.dataset.likes) + 1; // update the data attribute for next click, and update the text likes.dataset.likes = incrementedLikes.toString(); likes.innerText = incrementedLikes; } 
 <div id="container"> </div> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM