markgalante
markgalante

Reputation: 108

Adding an event listener to DOM elements pushed into an array

Apologies for the poorly-worded question. It's my first question here!

I am trying to make an application whereby one can log the scores of players from any game and see the results at the end of the game (see the code snippet below).

So far, I have managed to push players and their scores (initially empty arrays) into the main array and thereby presented these players in a list (see below):

HTML

    <h1>Score Keeper</h1>

    <input type="text" placeholder="Enter Player's Name" id="enterPlayer">
    <input type="submit" id="enterPlayerBtn" value="Enter Player">

    <div>
        <ul id="scoreConsole"></ul>
    </div>

JavaScript

var players = [];

var enterPlayer = document.querySelector("#enterPlayer"); 
var enterPlayerBtn = document.querySelector("#enterPlayerBtn");
var scoreConsole = document.querySelector("#scoreConsole"); 

//PUSHES OBJECTS INTO ARRAYS OF PLAYERS
addPlayer = () => {
    var entered = enterPlayer.value;
    players.push(
        {
            player: entered, 
            score: [] 
        }
    ); 
    enterPlayer.value = ""; 
}

//DISPLAYS PLAYERS ENTERED INTO ARRAY: 
var i=0;
createdPlayers = () => {
    var toAdd = document.createDocumentFragment();
        var newLi = document.createElement("li"); 
        newLi.className="each-player"; 
        newLi.innerHTML = players[i].player + " " + "<input type='number' placeholder='enter score' class='enterScore'>" + "<input type='submit' class='submitScoreBtn'>";   
        toAdd.appendChild(newLi);
    i++; 
    scoreConsole.appendChild(toAdd); 
}

enterPlayerBtn.addEventListener("click", () => {
 addPlayer(); 
 createdPlayers(); 
});

This gives me a list with the players' names, inputs to enter scores and buttons to log the scores. So far, so good.

But...

I am just trying to get each button to work. As you can see above, I gave each submit button classes ("submitScoreBtn"). I'm at the stage where I want to make sure that my new buttons work. Here's my code so far:

var enterScore = document.querySelectorAll(".enterScore"); 
var submitScore = document.querySelectorAll(".submitScoreBtn");

for (var x = 0; x < submitScore.length; x++){
    submitScore[x].addEventListener("click", () => {
        alert("selected"); 
    });
}

I initially was getting errors without adding a for loop. Now I don't get any errors, but I also don't get any alerts. I'm just not sure why these buttons do not work.

Please see the code snippet below.

var players = [];

var enterPlayer = document.querySelector("#enterPlayer"); 
var enterPlayerBtn = document.querySelector("#enterPlayerBtn");
var scoreConsole = document.querySelector("#scoreConsole"); 

//PUSHES OBJECTS INTO ARRAYS OF PLAYERS
addPlayer = () => {
    var entered = enterPlayer.value;
    players.push(
        {
            player: entered, 
            score: [] 
        }
    ); 
    enterPlayer.value = ""; 
}

//DISPLAYS PLAYERS ENTERED INTO ARRAY: 
var i=0;
createdPlayers = () => {
    var toAdd = document.createDocumentFragment();
        var newLi = document.createElement("li"); 
        newLi.className="each-player"; 
        newLi.innerHTML = players[i].player + " " + "<input type='number' placeholder='enter score' class='enterScore'>" + "<input type='submit' class='submitScoreBtn'>";   
        toAdd.appendChild(newLi);
    i++; 
    scoreConsole.appendChild(toAdd); 
}

enterPlayerBtn.addEventListener("click", () => {
 addPlayer(); 
 createdPlayers(); 
});

var enterScore = document.querySelectorAll(".enterScore"); 
var submitScore = document.querySelectorAll(".submitScoreBtn");

for (var x = 0; x < submitScore.length; x++){
    submitScore[x].addEventListener("click", () => {
        alert("selected"); 
    });
}
<html>
    <head>
        <title>Score</title>
    </head>
    <body>
        <h1>Score Keeper</h1>

        <input type="text" placeholder="Enter Player's Name" id="enterPlayer">
        <input type="submit" id="enterPlayerBtn" value="Enter Player">

        <div>
            <ul id="scoreConsole"></ul>
        </div>

        <script src="game.js"></script>
    </body>
</html>

Upvotes: 2

Views: 416

Answers (4)

Ram Segev
Ram Segev

Reputation: 2571

remove the for loop and add this code

document.addEventListener('click', function (event) { if ( event.target.classList.contains( 'submitScoreBtn' ) ) { alert("selected"); } }, false);

var players = [];

var enterPlayer = document.querySelector("#enterPlayer");
var enterPlayerBtn = document.querySelector("#enterPlayerBtn");
var scoreConsole = document.querySelector("#scoreConsole");

//PUSHES OBJECTS INTO ARRAYS OF PLAYERS
addPlayer = () => {
  var entered = enterPlayer.value;
  players.push({
    player: entered,
    score: []
  });
  enterPlayer.value = "";
}

//DISPLAYS PLAYERS ENTERED INTO ARRAY: 
var i = 0;
createdPlayers = () => {
  var toAdd = document.createDocumentFragment();
  var newLi = document.createElement("li");
  newLi.className = "each-player";
  newLi.innerHTML = players[i].player + " " + "<input type='number' placeholder='enter score' class='enterScore'>" + "<input type='submit' class='submitScoreBtn'>";
  toAdd.appendChild(newLi);
  i++;
  scoreConsole.appendChild(toAdd);
}
document.addEventListener('click', function(event) {
  if (event.target.classList.contains('submitScoreBtn')) {
    alert("selected");
  }
}, false);
enterPlayerBtn.addEventListener("click", () => {
  addPlayer();
  createdPlayers();
});

var enterScore = document.querySelectorAll(".enterScore");
<html>

<head>
  <title>Score</title>
</head>

<body>
  <h1>Score Keeper</h1>

  <input type="text" placeholder="Enter Player's Name" id="enterPlayer">
  <input type="submit" id="enterPlayerBtn" value="Enter Player">

  <div>
    <ul id="scoreConsole"></ul>
  </div>

  <script src="game.js"></script>
</body>

</html>

Upvotes: 1

Kaddath
Kaddath

Reputation: 6151

The easiest solution is to use variables and createElement just like you do with toAdd. This way each created entry will remember its own inputs (local variables to the function), and you can use for example the score input variable in the click handler without confusion of which number input belongs to which entry.

I removed the class for the inputs because it's not needed to select them anymore, but you can still add some for styling for example. If you want to add classes to select them all, be sure to run querySelectorAll each time, so that added elements are actually selected.

var players = [];

var enterPlayer = document.querySelector("#enterPlayer"); 
var enterPlayerBtn = document.querySelector("#enterPlayerBtn");
var scoreConsole = document.querySelector("#scoreConsole"); 

//PUSHES OBJECTS INTO ARRAYS OF PLAYERS
var addPlayer = () => {
    var entered = enterPlayer.value;
    players.push(
        {
            player: entered, 
            score: [] 
        }
    ); 
    enterPlayer.value = ""; 
}

//DISPLAYS PLAYERS ENTERED INTO ARRAY: 
var i=0;
var createdPlayers = () => {
    var toAdd = document.createDocumentFragment();
    var newLi = document.createElement("li"); 
    newLi.className="each-player"; 
    newLi.innerHTML = players[i].player + " ";
    var enterScore = document.createElement("input");
    enterScore.type = 'number';
    enterScore.placeholder = 'enter score';
    var submitScore = document.createElement("input");
    submitScore.type = 'submit';
    submitScore.addEventListener("click", () => {
        alert("selected score: " + enterScore.value); 
    });
    newLi.appendChild(enterScore);
    newLi.appendChild(submitScore);
    toAdd.appendChild(newLi);
    i++; 
    scoreConsole.appendChild(toAdd); 
}

enterPlayerBtn.addEventListener("click", () => {
    addPlayer(); 
    createdPlayers(); 
});
<html>
    <head>
        <title>Score</title>
    </head>
    <body>
        <h1>Score Keeper</h1>

        <input type="text" placeholder="Enter Player's Name" id="enterPlayer">
        <input type="submit" id="enterPlayerBtn" value="Enter Player">

        <div>
            <ul id="scoreConsole"></ul>
        </div>

        <script src="game.js"></script>
    </body>
</html>

Upvotes: 0

Shiny
Shiny

Reputation: 5055

Being as you're dynamically creating the buttons, it might be easier to simply add the function to the button's onclick.

You can still access the event object from this click by sending it as a parameter, like:

<input type='submit' onclick='submitScoreClick(event)' class='submitScoreBtn'>

var players = [];

var enterPlayer = document.querySelector("#enterPlayer"); 
var enterPlayerBtn = document.querySelector("#enterPlayerBtn");
var scoreConsole = document.querySelector("#scoreConsole"); 

//PUSHES OBJECTS INTO ARRAYS OF PLAYERS
addPlayer = () => {
    var entered = enterPlayer.value;
    players.push(
        {
            player: entered, 
            score: [] 
        }
    ); 
    enterPlayer.value = ""; 
}

//DISPLAYS PLAYERS ENTERED INTO ARRAY: 
var i=0;
createdPlayers = () => {
    var toAdd = document.createDocumentFragment();
        var newLi = document.createElement("li"); 
        newLi.className="each-player"; 
        newLi.innerHTML = players[i].player + " " + "<input type='number' placeholder='enter score' class='enterScore'>" + "<input type='submit' onclick='submitScoreClick(event)' class='submitScoreBtn'>";   
        toAdd.appendChild(newLi);
    i++; 
    scoreConsole.appendChild(toAdd); 
}

enterPlayerBtn.addEventListener("click", () => {
 addPlayer(); 
 createdPlayers(); 
});

var enterScore = document.querySelectorAll(".enterScore"); 
var submitScore = document.querySelectorAll(".submitScoreBtn");

function submitScoreClick (e) {
  alert("selected");
};
<html>
    <head>
        <title>Score</title>
    </head>
    <body>
        <h1>Score Keeper</h1>

        <input type="text" placeholder="Enter Player's Name" id="enterPlayer">
        <input type="submit" id="enterPlayerBtn" value="Enter Player">

        <div>
            <ul id="scoreConsole"></ul>
        </div>

        <script src="game.js"></script>
    </body>
</html>

Upvotes: 1

Joshua Obritsch
Joshua Obritsch

Reputation: 1293

At the point in time when this code is run:

for (var x = 0; x < players.length; x++){
    submitScore[x].addEventListener("click", (event) => {
        event.alert("selected"); 
    });
}

players.length is equal to 0. So the code is essentially never executed.

Upvotes: 1

Related Questions