Reputation: 238
I'm trying to toggle the text in a button every time it's clicked, between "READ" and "NOT READ". The buttons have been created dynamically with js and placed into an HTML table. Each button has a unique ID, but the same class name.
I've written an if statement that works for the first button that is set in the table, but the same if statement wont work for the buttons created dynamically.
I've tried lots of different variations for the if statements. I'm not sure if the best way would be to access the unique id's, but I don't know how to do that. Any help is appreciated! Thanks
Here's a repl https://repl.it/repls/SpryVisibleMining
function toggleText(){
if (readButton.innerHTML == "READ"){
readButton.innerHTML = "NOT READ";
} else if (readButton.innerHTML == "NOT READ"){
readButton.innerHTML = "READ";
} else {
null
}
}
And this is if statement that wont wont do anything
function toggleOthers() {
let toggle = document.getElementsByClassName(".readBtn")
toggle[0].addEventListener("click", () => {
if (toggle.innerHTML == "READ") {
toggle.innerHTML = "NOT READ"
} else if (toggle.innerHTML == "NOT READ") {
toggle.innerHTML = "READ"
} else {
null
}
})
}
toggleOthers()
Upvotes: 3
Views: 14537
Reputation: 20944
The problem lies in how you are listening for the click
events. Your toggleText
function is triggered whenever you click the #readed
button with the onclick
attribute. But inside the toggleText
function you add another event listener to the same button, adding a new event listener every time you click the button.
So every time you click the button you increment the amount of times you are calling toggleText
.
Remove the onclick
from the button and change the id
to a class
attribute. You said you would have multiple buttons, so having multiple buttons with the same id won't do it.
<button class="readed">READ</button>
Because you want to listen for the click
event on dynamically created elements I suggest you use Event Delegation. This means listening for the click
event on a parent element, this could be your table#shelf
element, and check which element has been clicked. If A has been clicked, then do X, if B has been clicked, then do Y.
Listen for click event on your table element.
var table = document.getElementById('shelf');
table.addEventListener("click", tableClickHandler);
In tableClickHandler
check which element has been clicked. You can do it by getting the clicked target and use the closest method to see if it really is the element you want to be clicked.
For example when you would have a <span>
in your <button>
, event.target
would be <span>
. But you want the <button>
element. closest
goes up in the DOM tree to see if it finally reaches an element that is the <button>
you want and returns it.
You can do this for any button inside of your table.
function tableClickHandler(event) {
var readed = event.target.closest('.readed');
if (readed) {
toggleText(readed);
}
}
Modify your toggleText
function so that it can take any <button>
you throw add it that you want the text toggled in. Add a button
parameter which represents the current button.
// Toggle text when clicked.
function toggleText(button) {
if (button.innerHTML == "READ") {
button.innerHTML = "NOT READ";
} else if (button.innerHTML == "NOT READ") {
button.innerHTML = "READ";
} else {
null
}
}
Upvotes: 2
Reputation: 792
You have to init an array named books, and each time you add a new book, you have to push the new book to the books array.
And also you have to set a flag as hasReadBook to the Book class.
When you are going to render your table row you have to write an if, for making the flag to string in dom.
function updateTable() {
//anythings needs to done for updating table.
//for hasReadBook flag you should do like this:
const hasReadBookString = books[i].hasReadBook ? "Read" : "Not Read";
}
And you need to make a loop on readBtn HTML collection, to know which index is going to change:
let books = [{...}];
let toggles = document.getElementsByClassName(".readBtn");
for (var i = 0; i < toggles.length; i++){
labels[i].addEventListener('click', function(e) {
books[i].hasReadBook = !books[i].hasReadBook;
})
}
updateTable();
Upvotes: 0
Reputation: 233
For example you can use this:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<button onclick="toggle(this)">not read</button>
<script>
function toggle(e) {
let txt = e.innerText;
e.innerText = txt == 'not read' ? 'read' : 'not read';
}
</script>
</body>
</html>
Let me know if it's not suitable for your use case ...
And also you can use querySelectorAll()
to get all buttons and then set this event with a for()
loop.
Upvotes: 5
Reputation: 2518
According to your repl, you also registered an onclick
-Handler on your button, too.
So calling toggleText()
while clicking the "Read/Not-Read"-button, will effectively register another onclick
-Handler. This will repeat as often as you press the button.
This will run as follows:
toggleText()
; this will register another EventListenerindex.js
)button.onclick
)Just remove it in your HTML:
<td><button id="readed">READ</button></td>
Upvotes: 0
Reputation: 92427
Try
toggleText = b=> b.innerHTML = b.innerHTML=='READ'?'NOT READ':'READ'
<button id="A" onclick="toggleText(this)">NOT READ</button>
<button id="B" onclick="toggleText(this)">NOT READ</button>
Upvotes: 0