How can I get the value of a button when there are many multiple buttons created? Currently on my Javascript file I have it so my search history makes a button in a list with a "value" of the city that is labeled.
When I click on the button that was made I get undefined.
function recentSearch(city) {
var addCity = document.createElement("button");
addCity.setAttribute("value", city);
addCity.textContent = city;
document.getElementById("searchHistory").append(addCity);
cities.push(city);
localStorage.setItem("searches",JSON.stringify(cities));
}
If you're adding so many buttons use event delegation. Add one listener to the parent container, add your buttons, and then, in the listener function, check to see if the clicked element is a button, and log its value.
const searchHistory = document.querySelector('#searchHistory');
// Add one listener to the container that calls `handleClick`
searchHistory.addEventListener('click', handleClick, false);
function handleClick(e) {
// Destructure the nodeName and value from
// the clicked element, and log the value if the
// element is a button
const { nodeName, value } = e.target;
if (nodeName === 'BUTTON') {
console.log(value);
}
}
function recentSearch(city) {
var addCity = document.createElement('button');
addCity.value = city;
addCity.textContent = city;
searchHistory.append(addCity);
}
const cities = ['London', 'Rome', 'New York', 'Seoul', 'Kingston'];
for (const city of cities) {
recentSearch(city);
}
<div id="searchHistory"></div>
The following code will log the value of the button to the console when it is clicked.
function recentSearch(city) {
var addCity = document.createElement("button");
addCity.setAttribute("value", city);
addCity.textContent = city;
addCity.onclick = (e)=>{
console.log(e.target.getAttribute('value'));
//or whatever other code you want to do onclick
}
document.getElementById("searchHistory").append(addCity);
cities.push(city);
localStorage.setItem("searches",JSON.stringify(cities));
}
Try using data-attributes. They make your code easier to read and provide a great way to pass along data inside of elements - and you can access their data using element.dataset.<attribute_name> - in this case e.target.dataset.value (from within the buttons click listener).
cities = []
function recentSearch(city) {
// FOR DEMO ONLY::
if (!city) city = "city " + Math.ceil(Math.random() * 1000);
var addCity = document.createElement("button");
addCity.setAttribute("data-value", city);
addCity.textContent = city;
addCity.addEventListener('click', e => {
console.log(`my city is: ${e.target.dataset.value}`);
})
document.getElementById("searchHistory").append(addCity);
cities.push(city);
// localStorage.setItem("searches",JSON.stringify(cities));
}
<div id='searchHistory'>
</div>
<button onclick='recentSearch()'>Make City</button>
Related
I am writing a function for autofill, which will display a list of values to select as potential value input. The names of the input fields are dynamic so I need to pass that to the function that is executed by the event handler, but I also need to prevent default button action. The error that I've been getting is that the passed targetField gets seen as the event and I have not been able to figure out how to fix this. Would appreciate some help. This is what I have now.
function dropdownList(testlist, clicked) {
const listEl = document.createElement("ul");
listEl.classname = "autocomplete-list";
testlist.forEach(item => {
const listItem = document.createElement("li");
const valueButton = document.createElement("button");
valueButton.innerHTML = item
valueButton.addEventListener("click", valueSelect(targetField);
listItem.appendChild(valueButton);
listEl.appendChild(listItem)
})
let clickedId = `scripts-${clicked}-script`
let targetField = document.querySelector("[data-testid=" + clickedId + "]")
document.querySelector("[data-testid=" + clickedId + "]").after(listEl)
valueSelect(targetField);
}
function valueSelect(targetField) {
event.preventDefault();
const buttonEl = event.target;
targetField.value = buttonEl.innerHTML
}
This code works. Your problem was mostly with the eventListener, and with the parameters of the valueSelect function.
Note: I changed your clicked variable to be the actual element, not the element's id
document.querySelector("#myInput").addEventListener("click", (event)=>dropdownList(["a", "b", "c"], event.target))
function dropdownList(testlist, clicked) {
const listEl = document.createElement("ul");
listEl.classname = "autocomplete-list";
testlist.forEach(item => {
const listItem = document.createElement("li");
const valueButton = document.createElement("button");
valueButton.innerHTML = item
valueButton.addEventListener("click", (event)=>valueSelect(event, clicked));
listItem.appendChild(valueButton);
listEl.appendChild(listItem)
})
clicked.after(listEl)
}
function valueSelect(event, targetField) {
event.preventDefault();
const buttonEl = event.target;
targetField.value = buttonEl.innerHTML
}
<label>Test</label><input type="text" id="myInput" />
I am trying to add a button inside a pointer which print a log to the console. This is just meant to be a test, so I can actually make the marker run a method, but I can't even get it to print text.
const marker = L.marker([latitude, longitude]).addTo(map);
const button = '<br/><button type="button">Click button</button>'
const clickbutton = document.querySelector("#click");
button1.addEventListener("click", function(event) {
console.log('This button works!');
});
marker.bindPopup(button);
When I load the page, I immediately get this error:
Uncaught (in promise) TypeError: Cannot read properties of null (reading 'addEventListener')
The console says this error is caused by
button1.addEventListener("click", function(event) {
but I'm not sure why it's null. Can anyone help me out?
You are creating the button incorrectly.
It will be right this way:
const button = document.createElement('button');
button.id = 'delete';
button.textContent = 'Delete marker';
In order to add a button to the page, you need to find the desired parent element and add the button as a child element:
// replace this id with what you need
const buttonParrentId = 'button-parrent-id';
const buttonParrent = document.getElementById(buttonParrentId);
buttonParrent.appendChild(button);
Next, you can work with the button as you need:
const marker = L.marker([latitude, longitude]).addTo(map);
button.addEventListener("click", function(event) {
console.log('This button works!');
});
marker.bindPopup(button);
Result code example:
const button = document.createElement('button');
button.id = 'delete';
button.textContent = 'Delete marker';
// replace this id with what you need
const buttonParrentId = 'button-parrent-id';
const buttonParrent = document.getElementById(buttonParrentId);
buttonParrent.appendChild(button);
const marker = L.marker([latitude, longitude]).addTo(map);
button.addEventListener("click", function(event) {
console.log('This button works!');
});
marker.bindPopup(button);
More about createElement
I am building a Modal dynamically. I want to make some buttons in this modal to open a SubModal. The buttons show up in html, but clicking these buttons does nothing.
Here is my code.
const subtaskList = document.getElementById('subtaskList');
for (const subtaskIndex in task.subtasks) {
const subtaskButton = document.createElement('button');
subtaskButton.classList.add('taskModalSubtaskButton');
subtaskButton.onclick = () => {
openSubTaskModal(task.subtasks[subtaskIndex], task);
}
subtaskButton.innerText = task.subtasks[subtaskIndex].name;
subtaskList.appendChild(subtaskButton);
subtaskList.innerHTML += '<br>';
}
While troubleshooting I made an array to hold the buttons and used console.log() to see its elements. They all had the onclick function. I've clicked the buttons from the dev console by getting their class name and nothing, so I know it's not a display issue. I feel like I am misunderstanding something and any help would be appreciated.
The problem is subtaskList.innerHTML += '<br>'; it is good idea to use subtaskList.appendChild(document.createElement("br")); instead.
Here is working snippet:
function doSomething(url) {
alert(url);
}
const subtaskList = document.getElementById('subtaskList');
for (var i = 0; i < 3; i++) {
const subtaskButton = document.createElement('button');
subtaskButton.classList.add('taskModalSubtaskButton');
subtaskButton.innerText = "name" + i;
subtaskButton.onclick = (function (url) {
return function () {
doSomething(url);
};
})("URL #" + i)
subtaskList.appendChild(subtaskButton);
subtaskList.appendChild(document.createElement("br"));
}
<div id="subtaskList"></div>
Also I change a bit onclick function to send correspond index to doSomething function
The 'click' event listener is not being added to the button.
The buttons do appear correctly with the other attributes. I have searched for a while and haven't been able to find a solution.
const connectedFriendsList = document.querySelector('#connected-friends-list');
function openMessengerWith(){
var friend_id = this.value;
console.log('Opening messenger with : ', friend_id);
}
// =======================================================
// Create elements and render friends list
//
var but;
function renderFriendsList(doc){
console.log('Rendering friend...');
but = document.createElement("input");
but.setAttribute("value", doc.id);
but.setAttribute("type", 'button');
but.id = doc.id;
but.addEventListener('click', function(){
openMessengerWith();
}, false);
console.log(but);
connectedFriendsList.appendChild(but);
console.log('Friend listed.');
}
The renderFriendsList function is being called down at the bottom.
firestore.collection('Users').doc(uid).collection('Friends').get().then((snapshot) => {
snapshot.docs.forEach(doc => {
renderFriendsList(doc);
})
});
EDITED:
function openMessengerWith(value){
var friend_id = value;
console.log('Opening messenger with : ', friend_id);
}
function renderFriendsList(doc){
console.log('Rendering friend...');
var but = document.createElement("button");
but.setAttribute("value", doc.id);
but.setAttribute("type", 'button');
but.id = doc.id;
but.innerHTML = doc.id;
connectedFriendsList.appendChild(but);
attachClickEvent(doc.id);
console.log('Friend listed.');
}
function attachClickEvent(value){
var test1 = document.getElementById(value);
console.log('current obj',test1);
document.getElementById(value).addEventListener("click",
function(){
openMessengerWith(value);
});
console.log('click events attached');
}
LOG:
Here is the updated log. As you can see the buttons are created. However, the event listeners are not being attached.
Rendering friend... messagesmain.js:71
current obj <button value="6r7CllAhMhPgmrhhjx1aneBCBbc2" type="button" id="6r7CllAhMhPgmrhhjx1aneBCBbc2">6r7CllAhMhPgmrhhjx1aneBCBbc2</button>
messagesmain.js:76
click events attached messagesmain.js:56
Friend listed. messagesmain.js:48
Rendering friend... messagesmain.js:71
current obj <button value="J1EbJJ9iZKTspqiSKawZN7i5pPh2" type="button" id="J1EbJJ9iZKTspqiSKawZN7i5pPh2">J1EbJJ9iZKTspqiSKawZN7i5pPh2</button>
messagesmain.js:76
click events attached messagesmain.js:56
Friend listed. messagesmain.js:48
Rendering friend... messagesmain.js:71
current obj
<button value="xSLBN2BqVocemn0OWOKh2UGY8Pt1" type="button" id="xSLBN2BqVocemn0OWOKh2UGY8Pt1">xSLBN2BqVocemn0OWOKh2UGY8Pt1</button>
messagesmain.js:76
click events attached messagesmain.js:56
Friend listed.
If you want to get the value of input, use this is a good idea. But you need to know the reference of this.
In your code, the reference of this is window, not <input> tag.
That's why you can't get the value.
So you need to pass this.value into function openMessengerWith
but = document.createElement("input");
but.addEventListener('click', function() {
let value = this.value;
openMessengerWith(value);
}, false);
function openMessengerWith(value){
var friend_id = value;
console.log('Opening messenger with : ', friend_id);
}
connectedFriendsList.appendChild(but);
Im new to javascript and coding in general, I'm trying to make a simple to do list but cant get the delete button to delete all the checkboxes, it will only delete the last checkbox made. Thanks guys
http://jsfiddle.net/2L8y73ac/
var task = document.getElementById('textinput');
function ObjectTask() {
self = this;
self.init = function() {
self.itemText=document.createTextNode(task.value);
self.checkbox = document.createElement("input");
self.checkbox.type = "checkbox";
self.checkbox.name = task.value;
self.checkbox.id = "checkbox";
self.checkbox.value = "0";
self.checkbox.onclick = self.clickMe;
self.listItem=document.createElement("li");
self.listItem.id = task.value;
self.listItem.appendChild(self.itemText);
self.listItem.appendChild(self.checkbox);
self.deleteCheckBox = document.getElementById('deleteBtn');
self.deleteCheckBox.onclick = self.deleteMe;
document.getElementById('place').appendChild(self.listItem);
}
self.clickMe = function() {
if (self.checkbox.value === "0") {
self.checkbox.value = "1";
console.log("1");
}else {
self.checkbox.value = "0";
console.log("0");
}
}
self.deleteMe = function(){
if (self.checkbox.value == "1"){
var parent = self.listItem.parentNode;
parent.removeChild(self.listItem);
}
}
}
function taskadd() {
var taskNew = new ObjectTask();
taskNew.init();
}
I can't seem to get the adding to work either, but that doesn't matter. :)
The problem is that you assign a new click handler to the single delete button everytime when you add an item. When you click the delete button, the event handler of the last item is called, everytime (even when the item itself is already deleted).
The problem is in this piece of code:
self.deleteCheckBox = document.getElementById('deleteBtn');
self.deleteCheckBox.onclick = self.deleteMe;
deleteCheckBox is assigned the (global) delete button. After that, you assign a new onclick handler to it, overwriting the previous one.
A better approach would be to write one generic handler for the delete button, which looks up all selected checkboxes and finds the other elements belonging to it to delete them. So just like your global taskadd(), you should also have a global taskdelete() that deletes all selected tasks.