Can't save DOM element .value property to a variable - javascript

I'm trying to create a simple Javascript program that adds/removes items to an array, then displays the array by DOM manipulation.
I've created a reference called 'input', that is supposed to be the value of the HTML text input field. It's supposed to look like this:
let input = document.getElementById("text").value;
When I try to identify that variable in the console, it recognizes it as undefined. But, if I reference the variable like this:
let input = document.getElementById("text");
and call, input.value, it shows the appropriate value. For ex: "Lorem ipsum". What am I doing wrong?
I've provided a codepen link to see the output.
HTML
<div>
<form>
<input type ="text" id="text">
<button onClick="updateList(input.value)" type ="button">Add</button>
<button onClick = "reset()" type="button">Clear</button>
</form>
</div>
<div id='para'>
<!--list goes here-->
</div>
Javascript
//input.value will be used
let input = document.getElementById("text");
let groceryList = ["Grapes", "Juice", "Apples"];
//Div where output will be placed
let para = document.getElementById('para');
//Creation of ul
let unorderedList = document.createElement('ul');
para.appendChild(unorderedList);
//Creates list on DOM
const createList = groceryList.forEach((grocery) =>
{
//Creation of list item
let li = document.createElement('li');
li.innerText = grocery; // For instance, just to give us something to see
li.className = "grocery-item";
unorderedList.appendChild(li);
});
//Resets para
const reset = () => {
para.removeChild();
}
//Adds item
const updateList = (item) => {
reset();
groceryList.push(item);
return createList;
}

If you use let input = document.getElementById("text").value; you assign the initial value of your input field which is undefined at start to your variable.
This value will never change.
If you use let input = document.getElementById("text"); you set a reference to the input field to your variable and you can then retrieve the current value of this element by using input.value
I hope that my answer will be understandable because my English is really poor.

Related

Customer List Challenge (TestDome)

I'm trying to solve this challenge from TestDome and i need some help. I dont really understand how i must toggle the email and how to append the item to DOM...
!!Please without Vanilla JS only!!
Implement the showCustomers function so that it renders customers as list items. The first argument to the function, customers, is an array of objects with the name and email properties. The second argument to the function, targetList, is an unordered HTML list to which each customer should be added as a separate list item.
The name and email properties should be added as two paragraphs inside the list item. At first, the email paragraph element should not be present in the DOM. The email paragraph element should be added to the DOM after the name is clicked, and it should be removed from the DOM when the name is clicked again.
For example, the following code:
document.body.innerHTML = `
<div>
<ul id="customers">
</ul>
</div>
`;
let customers = [{name: "John", email: "john#example.com"},
{name: "Mary", email: "mary#example.com"}];
showCustomers(customers, document.getElementById("customers"));
let customerParagraph = document.querySelectorAll("li > p")[0];
if(customerParagraph) {
customerParagraph.click();
}
console.log(document.body.innerHTML);
Should render:
<div>
<ul id="customers">
<li>
<p>John</p>
<p>john#example.com</p>
</li>
<li>
<p>Mary</p>
</li>
</ul>
</div>
THIS IS MY CODE
function showCustomers(customers, targetList) {
customers.forEach(item =>{
let res = `<li>
<p> ${item.name}</p>;
<p> ${item.email}</p>;
</li>;
targetList.innerHTML = targetList.appendChild(res);
})
}
https://www.testdome.com/questions/javascript/customer-list/49798?visibility=3&skillId=2
Replace the line
targetList.innerHTML = targetList.appendChild(res);
with
targetList.innerHTML += res;.
You basically have two ways for adding elements:
increasing innerHTML contents with raw strings
appending children to DOM element
In your case res is a string so you can't use targetList.appendChild
Since you asked :
'The email paragraph element should be added to the DOM after the name is clicked, and it should be removed from the DOM when the name is clicked again'.
create list el,create p el, create event listener on p el, append email to a child element
Replace your code to
customers.forEach((item) => {
const li = document.createElement("li");
const name = document.createElement("p");
name.textContent = item.name;
name.style.cursor = "pointer";
name.addEventListener("click", (event) => {
const parent = event.target.parentElement;
if (parent.children.length == 1) {
const email = document.createElement("p");
email.textContent = item.email;
parent.appendChild(email);
} else {
parent.lastChild.remove();
}
});
li.appendChild(name);
targetList.appendChild(li);
});
function showCustomers(customers, targetList) {
customers.forEach((customer, index) => {
const node = document.createElement('li');
let nameEl = document.createElement('p');
let emailEl = document.createElement('p');
nameEl.innerText = customer.name;
emailEl.innerText = customer.email;
node.appendChild(nameEl);
nameEl.addEventListener('click', function() {
node.contains(emailEl) ? node.removeChild(emailEl) :
node.appendChild(emailEl);
});
targetList.appendChild(node)
});
}

acces eventlistener in a created button in dom

edited with all the code, sorry for my messy coding, I am begginer
hope you can help with this,
I have just created a button in the dom with a function, I gave the button a class to apply an event listener, for some reason i am not able to activate the listener, does anyone have a clue about what I am doing wrong?
//this is th initial array of items, after I am changing it to an arrayof objects
let shoppingList = ['banana','apples','cherries','oranges', 'peaches'];
const list = document.querySelector('.list');
//this is the last thing I need, create new items and allow the del button
const foo=()=>{
console.log('hi');
}
const adder =(item, index, price,name)=>{
list.innerHTML += `<div class='item${[index+1]}'>${name}, price ${price} </div>`;
item[index]= {name,price};
const delElm = document.createElement('button');//the element to remove items
delElm.className = 'remove';
delElm.innerHTML = 'X';
list.appendChild(delElm);
const btndel = document.querySelector('.remove')
console.log(btndel)
btndel.addEventListener('click', foo)
}
//assign a random price to the original array
for (let i = 0; i < shoppingList.length; i++) {
let prices = i+Math.round((((Math.random()*5)+10))*100)/100;
let name = shoppingList[i];
adder(shoppingList,i,prices,name);
}
const btnElm= document.querySelector('.press');
//function to add new elements
const addItm=()=>{
const nameElm = document.querySelector('#text');
const priceElm = document.querySelector('#price');
let name = nameElm.value;
let prices = Number(priceElm.value);
let i = shoppingList.length-1;
adder(shoppingList, i, prices,name)
console.log(shoppingList)
}
console.log(shoppingList)
btnElm.addEventListener('click', addItm)
edit with the HTML, basically, the user can add new items filling the form, each item should be posible to be removed,
<input type="text" id="text" placeholder="name item">
<input type="text" id="price" placeholder="price">
<button class="press">add</button> -->
thanks you in advance

How do I make an h1 element for each value in an array?

I have an array in JavaScript as shown in the example below. My question is: how can I have an h1 element for each value of the array when a button is clicked?
Names = []
function submit() {
let inputValue = document.getElementById("name").value;
Names.push(inputValue);
let frame = document.getElementById("frame");
frame.innerHTML = `<div><h1>${Names}</h1></div>`
}
<button onclick="submit()">Submit</button>
<input placeholder="name" id="name">
<div id="frame"></div>
How do I create separate H1 elements which contain each value from the array?
You can do it like below, by emptying the frame innerHTML every time you wish to add a new one and then iterating through the Names list and creating new h1 elements using document.createElement("h1"). The key here is to use append() to add the created element to the desired element.
Check below:
var Names = []
function submit() {
let inputValue = document.getElementById("name").value;
Names.push(inputValue);
let frame = document.getElementById("frame");
frame.innerHTML = "";
Names.forEach(function(el, i) {
let h1 = document.createElement("h1");
h1.innerHTML = Names[i];
frame.append(h1);
});
}
<button onclick="submit()">Submit</button>
<input placeholder="name" id="name">
<div id="frame"></div>
Another, and possibly better approach would be to just use append() to add the new input, like this:
var Names = []
function submit() {
let inputValue = document.getElementById("name").value;
Names.push(inputValue);
let frame = document.getElementById("frame");
let h1 = document.createElement("h1");
h1.innerHTML = inputValue;
frame.append(h1);
}
<button onclick="submit()">Submit</button>
<input placeholder="name" id="name">
<div id="frame"></div>
I think you mean whenever the user enter a name
and press submit.. the name should be added to a list with id frame right?
If yes then you just need to fix alittle problem:
frame.innerHTML = `<div><h1>${Names}</h1></div>`
this line of code is causing this issue, you are rewriting the new name on top of the old one, and what you should do is something like:
frame = old frame + new name
in code :
frame.innerHTML += `<div><h1>${Names}</h1></div>`
or
frame.innerHTML = frame.innerHTML+ `<div><h1>${Names}</h1></div>`
both lines of codes do the same thing but are written in a different way

Eloquent JS Exercise (Ch.18 Q. 2)

I was hoping someone can help me figure out what I'm doing wrong... There's this exercise in the Eloquent JS book that asks you to write some code that can suggest words/values to users as they type... The code I've written is below. What happens is that when I run the code, the div element's text content changes to the wrong value. Specifically, it's set to a string of all the elements inside the array 'terms'. I really cant figure out why this happens!
<input type="text" id="field">
<div id="suggestions" style="cursor: pointer"></div>
<script>
// Builds up an array with global variable names, like
// 'alert', 'document', and 'scrollTo'
var terms = [];
for (var name in window)
terms.push(name);
var input = document.querySelector('input');
var div = document.querySelector('#suggestions');
input.addEventListener("input", function(event){
var last = input.value.lastIndexOf(" ")+1;
var check = input.value.slice(last);
var reg = new RegExp(check);
for (var i=0; i<terms.length; i++) {
if (reg.test(terms[i])) {
var text = document.createTextNode(terms[i]);
div.appendChild(text)};
};
})
</script>
I guess you forgot to clean the div before each change in the input.
I also added a space after each word to make the output more readable.
// Builds up an array with global variable names, like
// 'alert', 'document', and 'scrollTo'
var terms = [];
for (var name in window)
terms.push(name);
var input = document.querySelector('input');
var div = document.querySelector('#suggestions');
input.addEventListener("input", function(event){
div.innerHTML = '';
var last = input.value.lastIndexOf(" ")+1;
var check = input.value.slice(last);
var reg = new RegExp(check);
for (var i=0; i<terms.length; i++) {
if (reg.test(terms[i])) {
var text = document.createTextNode(terms[i] + ' ');
div.appendChild(text)};
};
})
<input type="text" id="field">
<div id="suggestions" style="cursor: pointer"></div>
With this code, you will display the name of the properties from the window object that contains the last word from the input. Try it writting "window location document". Is it what you are looking for?

How to get html element runtime code to make generic copies? Like copy textbox with text entered into it

I want to be able to copy elements with keeping everything that user entered, modified and etc.
I don't want to parse every elem like manually set value for textboxes, manually set checked for radiobuttons and etc, I need some generic way.
Is this possible?
This is what I have as example:
<html>
<head>
<title>asd</title>
<script type = "text/javascript">
function copyElement(elem_id, to_elem_id)
{
var elem = document.getElementById(elem_id);
var container = document.getElementById(to_elem_id);
if (!elem || !container)
return;
container.innerHTML = elem.outerHTML;
}
</script>
</head>
<body>
<input type = "text" id = "test_txt" />
<input type = "button" value = "copy textbox" onclick = "copyElement('test_txt', 'for_elem_paste')" />
<span id = 'for_elem_paste'></span>
</body>
</html>
I want that copied textbox to appear with text entered in original textbox.
But this not about textboxes, I need to copy any elements. I though that innerHTML and outerHTML keep things that modified by user :/
You can clone it
function copyElement(elem_id, to_elem_id) {
var elem = document.getElementById(elem_id);
var container = document.getElementById(to_elem_id);
if (elem && container) {
var clone = elem.cloneNode(true);
clone.id = "some other id to prevent id duplication";
container.appendChild(clone);
}
else return false;
}

Categories

Resources