When I add a value to the array and console.log it the first value gets removed and the array restarts always leaving the array with one value. How can I add multiple values by clicking the same button each time?
function calcBudget(){
//expenseCostValue is an input in a form.
const expenseValue = expenseCostValue.value;
const itemList = [];
itemList.push(expenseValue);
console.log(itemList);
You're probably redefining your array every time. Put the const itemList = [] outside of the click event handler. and just run itemList.push(expenseValue) inside the click event handler.
You must change the scope of your Array
function calcBudget() {
const expenseValue = expenseCostValue.value;
const itemList = []; // → remove the array
console.log(itemList);
}
const itemList = []; // we declare it out of our function
function calcBudget() {
const expenseValue = expenseCostValue.value;
itemList.push(expenseValue);
console.log(itemList);
}
I hope I have been helpful
Related
Currently trying to build a javascript form that converts the inputs into JSON. I've managed to create objects that allow multiple keys/values to be entered however I'm struggling to get my head around the logic and code for nesting a child object within an object.
let objects = [];
document.addEventListener('DOMContentLoaded', () => {
document.getElementById('btn2').addEventListener('click', function(e) {
e.preventDefault();
let infoBoxOne = document.getElementById('key').value // store the key into a variable
let infoBoxTwo = document.getElementById('value').value // store the value into a variable
const lastObject = objects[objects.length-1] // finds the last object in the objects array
const objectValues = Object.entries(lastObject) // gets all the keys and values
const lastKeyValuePair = values[values.length-1]; // stores the last key and value entered into a variable
})
})
So my initial idea was to find the last key/value within the last object that was added and use something like Object.create() or push() to insert the data. Is there an easier way of achieving this?
edit: here's a jsfiddle showing what I have exactly so far https://jsfiddle.net/9jrzLxnm/
Secone edit: idea of what I'm trying to achieve
{
{
"firstObject":'FirstObject'
},
{
"lastObject": {
"infoBoxOne": "JlastObject",
},
}
}
Ok firstly you have to set the desired location to place a child object as an object itself.. then the rest is intuitive
My example is on jsfiddle
document.addEventListener('DOMContentLoaded', () => {
document.getElementById('btn2').addEventListener('click', function(e) {
e.preventDefault();
let childKey = document.getElementById('key').value // store the key into a variable
let childValue = document.getElementById('value').value // store the value into a variable
const lastObject = objects[objects.length-1] // finds the last object in the objects array
const values = Object.entries(lastObject) // gets all the keys and values
const [key,value] = values[values.length-1]; // stores the last key and value entered into a variable
lastObject[key]={} //turning place to put child into an object
lastObject[key][childKey]=childValue //placing the nested child
document.forms[0].reset();
listToJson();
})
})
I have managed to create the array with the names that I need. These names are pushed or removed from the array based on user’s clicks on various html elements(buttons).
I am attempting to use the values collected within the array to call changes upon html elements that have class names corresponding/matching the names within the array.
I have managed to create a function that activates a window alert that allows me to see and verify that I am able to cycle through all elements collected within the array. But I got stuck. I couldn’t figure out how to use the individual values/names within the array to call the specific classes of html elements.
I have tried:
for (var a = 0; a < array.length; a++) {
document.getElelemntsByClassName(“.”+array[a]).classList.add(“new”);
//and//
document.querySelectorAll(“.”+array[a]).classList.add(“new”);
//none of them worked. So I wasn’t able to get through to the specific html elements.//
window.alert(“.”+array[a]);
//This responds properly. I can get multiple alerts, one at the time, with all the names I am expecting to see.//
}
Thank you in advance for your help.
I believe you want to use an object instead of an array, since indexes on an array will change as you remove items. That said, you may not even need the object, depending on what you want to do with the element. In the snippet below, I added classNames as an object to treat it as an associative array, for example:
// This is shared between two functions
const LIST_ITEM_SELECTOR = '.js-list-item'
// Get top-level elements
const listElement = document.querySelector('.js-list')
const listItemTemplate = document.querySelector('.js-list-item-template')
const addButton = document.querySelector('.js-add-button')
const logButton = document.querySelector('.js-log-button')
// Replaces "array" from your example
const classNames = {}
// Removes the list item from the list element (also delete from classNames)
const handleDelete = e => {
const parentListItem = e.currentTarget.closest(LIST_ITEM_SELECTOR)
const listItemId = parentListItem.dataset.id
delete classNames[listItemId]
parentListItem.remove()
}
// Updates after each "Add"
let nextId = 0
const handleAdd = () => {
// Build new element from the template
const newListItem = listItemTemplate.content
.cloneNode(true)
.querySelector(LIST_ITEM_SELECTOR)
// Add class to the element and the "classNames" object
const className = `id-${nextId}`
newListItem.classList.add(className)
classNames[nextId] = className
// Add data-id
newListItem.dataset.id = nextId
// Update text
newListItem.querySelector('.js-text').textContent = `Item Text ${nextId}`
// Add delete event listener to the nested x button
newListItem.querySelector('.js-x-button').addEventListener('click', handleDelete)
// Append the newListItem to the end of the list
listElement.appendChild(newListItem)
// Prep the nextId for the next "Add" click
nextId += 1
}
addButton.addEventListener('click', handleAdd)
logButton.addEventListener('click', () => {
console.dir(classNames)
})
<button class="js-add-button">Add</button>
<ul class="js-list"></ul>
<template class="js-list-item-template">
<li class="js-list-item">
<span class="js-text">Item Text</span>
<button class="js-x-button">x</button>
</li>
</template>
<button class="js-log-button">Log Out Data</button>
I am trying to create an admin panel where you add the words inside the input and then you add these words to an array which updates his value and adds it to the localStorage.
I've tried to add an event listener to a button but when i click it the first time it adds the value but when i click it second time it's adding the same value.
let input = document.querySelector('.word-input');
let inputValue = input.value;
let btn = document.querySelector('.btn');
let p1 = document.querySelector('#p2');
let form = document.querySelector('form')[0];
form.addEventListener('submit', function() {
arr.push(inputValue);
})
localStorage.setItem('a', arr);
I expect the values inserted to the input get inserted to the localStorage also but it adds the same value every time.
It keeps inserting the same value because you created let inputValue = input.value; but you should take the input value everytime the event gets triggered.
In addition, you should put your localStorage.setItem into the event since you want to add the value to your array and then save the array into the localStorage.
Finally, you should stringify your array to save it as a string into your localStorage since you cannot save arrays into localStorage.
form.addEventListener('submit', function() {
arr.push(input.value);
localStorage.setItem('a', JSON.stringify(arr));
})
Your inputValue variable is only set on initial load.
form.addEventListener('submit', function() {
let inputValue = input.value;
arr.push(inputValue);
})```
The following code deletes all children of a certain element, besides these listed inside the saved variable.
let rightCol = document.querySelector("#rightCol");
let saved = rightCol.querySelectorAll('._4-u2._3-96._4-u8');
let savedArr = [];
saved.forEach(()=>{
savedArr.push(saved);
});
rightCol.innerHTML = ''; // Delete all children before retrieving "saved" ones.
for (var i = 0; i < savedArr.length; i++) {
rightCol.appendChild(savedArr[i]);
};
The code fails with this error:
TypeError: Argument 1 of Node.appendChild does not implement interface Node.
Why the code fails?
The code you presented have 2 errors:
querySelectorAll should be executed on document.
you are pushing entire array in for each loop.
here is the working copy
let rightCol = document.querySelector("#rightCol");
let saved = document.querySelectorAll('._4-u2._3-96._4-u8');
let savedArr = [];
saved.forEach((s)=> {
savedArr.push(s);
});
rightCol.innerHTML = ''; // Delete all children before retrieving "saved" ones.
for (var i = 0; i < savedArr.length; i++) {
rightCol.appendChild(savedArr[i]);
};
You are pushing your collection array for each element in your selection return instead of the elements
Where your code state .each(()=> on the next line, the argument to push should be this
On each iteration of forEach you are adding the entire saved array to savedArr. You should instead add each item using the parameter passed into the forEach callback.
e.g.
saved.forEach((s)=> {
savedArr.push(s);
});
Not sure why you're copying the array over to another array here though..
I am trying to create an array of objects that contain two pieces of information relating to an order:
Product Stock Code
Product Quantity
Currently I am doing it like this:
$(".orderBtn").click(function(event){
//Show the order Box
$(".order-alert").show();
event.preventDefault();
//Create the Array
var productArray = [];
//Get reference to the product clicked
var stockCode = $(this).closest('li').find('.stock_code').html();
//Get reference to the quantity selected
var quantity = $(this).closest('li').find('.order_amount').val();
var key = "stockCode";
var obj = {
'stockCode' : stockCode,
'quantity' : quantity
};
productArray.push(obj);
$.cookie('order_cookie', JSON.stringify(productArray), { expires: 1, path: '/' });
console.log(productArray);
if(quantity == 0){
console.log("Quantity must be greater than 0")
}
I would expect that each time the order button is clicked that the new object would be added to the array of existing objects but instead It just outputs the array with 1 object, the object I've just added.
Is there something I am missing?
Move your array declaration outside of the function into the global scope.
What happens in your case is that each time you call the function a new array is created(function scope) and therefore only one result is produced.
Read this about scopes\hoistings.
var productArray = [];
$(".orderBtn").click(function(event){
//Show the order Box
$(".order-alert").show();
event.preventDefault();
//Create the Array
//Get reference to the product clicked
var stockCode = $(this).closest('li').find('.stock_code').html();
//Get reference to the quantity selected
var quantity = $(this).closest('li').find('.order_amount').val();
var key = "stockCode";
var obj = {
'stockCode' : stockCode,
'quantity' : quantity
};
productArray.push(obj);
$.cookie('order_cookie', JSON.stringify(productArray), { expires: 1, path: '/' });
console.log(productArray);
if(quantity == 0){
console.log("Quantity must be greater than 0")
}
declare as global variable
var productArray = [];
$(".orderBtn").click(function(event){
// do here
//productArray.push("anyObject");
});
You are recreating / overwriting the productArray every time the button is clicked. Try moving the var productArray = [] to outside of the click handler
Not so, because your
var productArray = [];
is within the function that sets the cookie, so it's getting defined afresh then having one element added each time the function is called.
You'd need to define productArray outside of the function (as a global variable?) so that it retains its previous value, and new objects are added to it
With var productArray = []; you're declaring a new array on every click. Move that line outside the click handler and the code should start working.