This question already has answers here:
What do querySelectorAll and getElementsBy* methods return?
(12 answers)
Closed 1 year ago.
I´m trying to make a simple To-do List, and I want it to have a button to add the tasks that I want and another button to remove all tasks but when I click the delete button I get an error: "Cannot read property 'removeChild' of undefined" I don´t know why it says the parentNode is undefined.
Here is the code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<title>To do List</title>
</head>
<body>
<header>
<h1>To-do List</h1>
<div id="form">
<input type="text" name="" id="tarefa" value="Add an item!">
<button id="submit">Submit</button>
<button id="delete">Clear List</button>
</div>
</header>
<main>
<ul id="lista">
<li id="112">Test1</li>
<li>Test2</li>
</ul>
</main>
<script src="javascript.js"></script>
</body>
</html>
//Javascript file
const tarefa = document.getElementById("tarefa")
const adicionar = document.getElementById("submit")
const limpar = document.getElementById("delete")
const padre = document.getElementById("lista")
const fpp = document.querySelectorAll("li")
//Add the tasks
function enviar(e){
var coisa = document.createElement("li")
let escrito = tarefa.value;
padre.appendChild(coisa)
coisa.innerHTML = escrito
}
//Delete the tasks
function apagar(e){
fpp.parentNode.removeChild(fpp)
console.log("aaaa")
}
adicionar.addEventListener("click",enviar)
limpar.addEventListener("click",apagar)
.querySelectorAll returns a NodeList (because you're selecting all li tags, not just one), so you need to do a forEach loop. Give the context, I asume fds is supposed to be fpp (you never define fds in the code you provided), so here is the code you would need, given that assumption:
function apagar(e){
fpp.forEach(function(el) {
el.parentNode.removeChild(el)
})
}
Update
Use this so that you dont get null errors once the list is deleted the first time.
function apagar(e){
document.querySelectorAll("li").forEach(function(el) {
el.parentNode.removeChild(el)
})
}
How about
function apagar(){
padre.innerHTML = "";
}
Related
I've got this error:
index.js:29 Uncaught TypeError: clone.getElementById is not a function
at HTMLButtonElement.changeImg (index.js:29:11)
changeImg # index.js:29
It marks the line highlighted. I don't understand why. If somebody can help me I'll appreciate it.
//captura de elementos:
const btn = document.querySelector('.btn');
const templateImg = document.querySelector('.templateImg').content;
const imgContainer = document.querySelector('.imgContainer');
const fragment = document.createDocumentFragment();
let arrayImg = [
"/img/food1.jpg",
"/img/food2.jpg",
"/img/food3.jpg",
"/img/food4.jpg",
"/img/food5.jpg",
"/img/food6.jpg",
"/img/food7.jpg",
"/img/food8.jpg",
"/img/food9.jpg"
];
const changeImg = () => {
let ran = Math.floor(Math.random() * 9);
//Crear clon del template:
const clone = templateImg.firstElementChild.cloneNode(true);
console.log(clone);
console.log(arrayImg[ran]);
//capturar elemento y modificar el src:
clone.getElementById("img").src = arrayImg[ran];
fragment.appendChild(clone);
imgContainer.appendChild(fragment);
}
btn.addEventListener('click', changeImg);
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="StyleSheet" href= "style.css" type= "text/css">
<title>Cambiador de imagenes</title>
</head>
<body>
<div class="container">
h1>Food and drink in Florianopolis</h1>
<div class="imgContainer"><!--templateImg--></div>
<button type="text" class="btn" id="btn">Change</button>
</div>
<template class="templateImg">
<img id="img" src="/img/food1.jpg">
</template>
<script src="./index.js"></script>
</body>
</html>
I was trying to change the images inside the template modifying the src:
<template class="templateImg">
<img id="img" src="/img/food1.jpg">
</template>
When I use querySelector, the error is that the value I try to replace is null even though it's not, and with getElementById, I get that message that it's not a function.
you create a "clone" with this code:
const clone = templateImg.firstElementChild.cloneNode(true);
that is a image element(see in console) and you for changing image src just need to use this code:
clone.src = arrayImg[ran];
getElementById() is a method of document not of any HTML element.
What you want to use instead is querySelector which you can in fact use on elements.
I am getting a new array element from an input and adding to array but I can not print every element in a new row. I can print all elements of array in one row but can not print every element in a different row. I am using <br> after array name but does not work. What is your solution? It is like a todo list project.
var allmembers = [""];
function addnewmember() {
var newmemberr = document.getElementById("newmember").value;
allmembers.push(newmemberr);
for (var i = 0; i < allmembers.length; i++) {
document.getElementById("membername").innerHTML = allmembers[i] + "<br>";
}
}
<html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="stil.css">
</head>
<body>
<input id="newmember" placeholder="NEW MEMBER"><br>
<button type="button" onclick="addnewmember()">SEND</button>
<div id="members">MEMBERS</div>
<div id="membername"></div>
</body>
</html>
Your solution is appending a <br> to the end of the array, rather than between array items. Instead of looping over the array, just use the .join() method, which is ideal for something like this.
Additionally, using innerHTML in a loop is a big performance "no no" as it causes the browser to have to repaint and possibly reflow the DOM document repeatedly. In such cases, you should build up a string that contains the HTML you want and after the loop is done set that string as the innerHTML of the desired element in one single command. And really, the use of innerHTML should be avoided if at all possible because of security concerns as well.
See additional comments inline:
let allmembers = [];
// Get your DOM references just once, not every time the function runs
// Make references to DOM elements, rather than their propreties. This
// way, if you decide you need access to a different DOM element property
// you don't have to scan for the element again.
let newmember = document.getElementById("newmember");
let memberName = document.getElementById("membername");
function addnewmember() {
allmembers.push(newmember.value);
newmember.value = ""; // Clear out the input
// No need for a loop. Just join the arry elements
// with a <br> between them.
memberName.innerHTML = allmembers.join("<br>");
}
<html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="stil.css">
</head>
<body>
<input id="newmember" placeholder="NEW MEMBER"><br>
<button type="button" onclick="addnewmember()">SEND</button>
<div id="members">MEMBERS</div>
<div id="membername"></div>
</body>
</html>
I am doing an assignment where I make a simple API call using fetch to retrieve an image a of dog by breed. The one issue I can't resolve is that the input value never changes when I try to retrieve an image of a different breed. the default value, which is 'hound', reappears after I press submit. I know I need to attach an onchange event to my input but I am not sure how to write it or how to get the value after the onchange event is triggered. Any help would be greatly appreciated. I originally wrote this with jQuery but decided to rewrite it in vanilla Javascript so that's why there is no jQuery.
I put a '<---' on the line I am struggling with.
P.S I know my code isn't very good, I am new to this.
Javascript
function getJson(breed) {
fetch("https://dog.ceo/api/breed/" + breed + "/images/random")
.then((response) => response.json())
.then((responseJson) => displayResults(responseJson));
}
function displayResults(responseJson) {
const dogImage = responseJson.message;
let breedImage = "";
let container = document.createElement("div");
console.log(dogImage);
breedImage += `<img src="${dogImage}">`;
container.innerHTML = breedImage;
document.querySelector(".results-img").innerHTML = "";
document.querySelector(".results-img").appendChild(container);
}
function submitButton() {
let breedName = document.querySelector("#numberValue").value;
breedName.addEventListener().onchange.value; <---
document.getElementById("dog-input").addEventListener("submit", (e) => {
e.preventDefault();
getJson(breedName);
});
}
submitButton();
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Dog Api</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="container">
<form>
<input id="numberValue" type="text" value="hound" />
<button type="submit" class="submit-button">Submit</button>
</form>
<section class="results">
<h2>Look at these Dogs!</h2>
<div class="results-img"></div>
</section>
</div>
<script src="main.js"></script>
</body>
</html>
You don't need an onchange event handler. Currently you're storing the value of the input in breedName when you call submitButton. That means that breedName will never change because it is merely a reference to the value at that moment.
Instead create a reference to the element and read the value property in the submit event handler. That will get the value how it is at the time you submit.
function getJson(breedName) {
console.log(breedName);
}
function submitButton() {
const form = document.querySelector('#dog-form');
const input = document.querySelector('#numberValue');
form.addEventListener('submit', event => {
event.preventDefault();
const breedName = input.value;
getJson(breedName);
});
}
submitButton()
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Dog Api</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="container">
<form id="dog-form">
<input id="numberValue" type="text" value="hound" />
<button type="submit" class="submit-button">Submit</button>
</form>
<section class="results">
<h2>Look at these Dogs!</h2>
<div class="results-img"></div>
</section>
</div>
<script src="main.js"></script>
</body>
</html>
I trying to do simple to do list but append(); is not working and logging an error
Uncaught TypeError: ul.append is not a function
at HTMLButtonElement.takeValue
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/css/materialize.min.css">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div class="container">
<input type="text" id="field">
<button type="submit" id="btn-sub">submit</button>
<ul class="collection">
<li class="collection-item">Alvin</li>
</ul>
</div>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha256-k2WSCIexGzOj3Euiig+TlR8gA0EmPjuc79OEeY5L45g=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/js/materialize.min.js"></script>
<script src="js/main.js"></script>
JS
let btn = document.getElementById('btn-sub');
btn.addEventListener('click', takeValue);
function takeValue(e) {
e.preventDefault();
let con = document.getElementsByClassName('container');
let val = document.getElementById('field').value;
let ul = document.getElementsByClassName('collection');
let li = document.createElement('li');
li.classList.add('collection-item');
li.innerText = val;
ul.append(li);
con.prepend(ul);
}
How you can read here
Document.getElementsByClassName()
Returns an array-like object of all
child elements which have all of the given class names. When called on
the document object, the complete document is searched, including the
root node. You may also call getElementsByClassName() on any element;
it will return only elements which are descendants of the specified
root element with the given class names.
so, if you have at least a 'container':
let con = document.getElementsByClassName('container')[0];
same for your 'collection':
let ul = document.getElementsByClassName('collection')[0];
then, as you can read here
The Node.appendChild()
method adds a node to the end of the list of
children of a specified parent node. If the given child is a reference
to an existing node in the document, appendChild() moves it from its
current position to the new position (there is no requirement to
remove the node from its parent node before appending it to some other
node).
function addItem() {
let con = document.getElementsByClassName('container')[0];
let val = document.getElementById('field').value;
let ul = document.getElementsByClassName('collection')[0];
let li = document.createElement('li');
li.classList.add('collection-item');
li.innerText = val;
ul.appendChild(li);
con.prepend(ul);
}
<input id="field" value="hello" />
<div class="container">
<ul class="collection">
</ul>
</div>
<button onclick="addItem()">hit</button>
I have a problem with simple thing.
I want to add a element into html div tag using createElement Method. I have tried a lot of diferent ways but always getting the same result - nothing happens.
This is my code:
function changeReleaseDate()
{
var parentElement = document.getElementByClassName("container body-content");
var existingElement = document.getElementByClassName("btn btn-default");
var newInput = document.createElement("input");
newInput.type = "text";
newInput.className = "form-control";
parentElement.insertBefore(newInput, existingElement);
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My ASP.NET Application</title>
<link href="~/Content/Site.css" rel="stylesheet" type="text/css" />
<script src="script.js"></script>
</head>
<body>
<div class="container body-content">
<h2>Index</h2>
<button id="btn" type="button" onclick="changeReleaseDate()" class="btn btn-default">Default</button>
<hr />
<footer>
<p>©My ASP.NET Application</p>
</footer>
</div>
</body>
</html>
I also tried to use appendChild but in this case input field was placed out of div.
The problem is that getElementByClassName should be getElementsByClassName.
This method returns a HTMLCollection, so to access the first element from this list you need to use bracket with index 0:
var parentElement = document.getElementsByClassName("container body-content")[0];
var existingElement = document.getElementsByClassName("btn btn-default")[0];
Demo: http://jsfiddle.net/jak4efau/
However it's more convenient in your case to use querySelector method:
var parentElement = document.querySelector(".container body-content");
var existingElement = document.querySelector(".btn.btn-default");
Also note, that you need to take care of the case when user clicks button multiple times, you probably don't want to append multiple input fields.