Click on an element and delete it from an array - javascript

itemElement.onclick=function(){
//remove element from view
this.parentNode.removeChild(this);
//find the element that was clicked on in the array
//which should be itemElement(aka this)????
var index=itemArray.indexOf(this);
//remove it from the array
itemArray.splice(index,1);
//console.log to check
console.log(itemArray);
}
That is my code I am currently using to delete items from a list. I want the user to be able to click on the item in their list they want to delete, delete it from the view and then delete it from an array of items. Deleting the element from the view is working fine, but for some reason its only deleting the last element added to the array, not the actual element that was clicked on. So if the user makes a list that has Bob,Tom,Rob and then clicks on Tom, Tom is no longer displayed in the list but Rob will be deleted from the array.
Here is that whole block of code
const addButton =<HTMLButtonElement>document.querySelector("#addButton");
const saveButton = document.querySelector("#saveButton");
const itemsSection = document.querySelector("#itemsSection");
const itemArray: Array<string> = [];
let itemElement;
let newItem: string;
let itemText: string;
//add new item to shopping list
addButton.onclick=function addItem(){
//add each item to the list
itemElement = document.createElement("li");
newItem = (<HTMLInputElement>document.querySelector("#newItem")).value;
itemText = document.createTextNode(newItem);
itemElement.appendChild(itemText);
itemsSection.appendChild(itemElement);
document.querySelector("#newItem").value="";
//push each item to our array to store in local storage
itemArray.push(newItem);
console.log(itemArray);
itemElement.onclick=function deleteItem(){
var index=itemArray.indexOf(this);
this.parentNode.removeChild(this);
itemArray.splice(index,1);
console.log(itemArray);
}
}
As you can see im using typescript

Your code is failing to find the element in the array:
index=itemArray.indexOf(this);
This is setting index to -1 because the item is not found:
The indexOf() method returns the first index at which a given element can be found in the array, or -1 if it is not present.
When you then call
itemArray.splice(index,1);
You're always removing the last element of the array, because that's how splice works when passed negative numbers:
start
Index at which to start changing the array. If greater than the length of the array, actual starting index will be set to the length of the array. If negative, will begin that many elements from the end.
You need to debug why itemArray.indexOf(this); is not finding the item (and we need to see more code to help you with that) and you should say:
if(index >=0)
itemArray.splice(index,1);
else
console.log("Could not find index"); // or better error handling ;-)
Try changing:
//push each item to our array to store in local storage
itemArray.push(newItem);
to:
//push each item to our array to store in local storage
itemArray.push(itemElement);
If that doesn't work, try adding an attribute to itemElement containing the index of the element in itemArray, so that you can know which element to remove without having to rely on indexof() and DOM objects. Something like this totally untested version of your code:
const addButton =<HTMLButtonElement>document.querySelector("#addButton");
const saveButton = document.querySelector("#saveButton");
const itemsSection = document.querySelector("#itemsSection");
const itemArray: Array<string> = [];
let itemElement;
let newItem: string;
let itemText: string;
//add new item to shopping list
addButton.onclick=function addItem(){
//add each item to the list
itemElement = document.createElement("li");
newItem = (<HTMLInputElement>document.querySelector("#newItem")).value;
itemText = document.createTextNode(newItem);
itemElement.appendChild(itemText);
itemsSection.appendChild(itemElement);
document.querySelector("#newItem").value="";
// ***here** store the index of the element:
itemElement.id = "itemIndex_" + (itemArray.push(newItem) -1);
console.log(itemArray);
itemElement.onclick=function deleteItem(){
// get my index from my ID rather than indexOf:
var index=parseInt(this.id.split('_')[1]);
this.parentNode.removeChild(this);
itemArray.splice(index,1);
console.log(itemArray);
}
}

Related

set Interval only seems to happen once when appending a text node to a div [duplicate]

I have a simple forEach loop in which I'm trying to append list items to an unordered list. However, when I run the script, I'm only seeing one list item being added. Can anyone explain why this is happening?
JS
let bookElement = document.getElementsByClassName("book");
let navElement = document.getElementsByTagName("nav")[0];
let unorderedList = document.createElement("UL");
let listItems = document.createElement("LI");
let book1 = new Book();
let book2 = new Book();
let booksArray = [book1, book2];
createNavigation(booksArray, navElement, unorderedList, listItems);
function createNavigation(booksArray, navElement, unorderedList, listItems){
console.log(booksArray)
booksArray.forEach(function(book){
unorderedList.appendChild(listItems);
})
navElement.appendChild(unorderedList);
}
HTML
<body>
<nav></nav>
<div class="book"></div>
</body>
The log in the function is returning that there are two objects in the array.
You only ever create one list item.
You then append it in multiple places.
Since an element can't exist in multiple places at the same time, each time you append it (after the first) you move it.
Use let listItems = document.createElement("LI"); inside your loop.
Yes, there are two objects in the array, but you're adding the same element to the unorganised list twice. So, the second time it's added, the browser sees that the element is already there and doesn't add it again.
A better approach would be to simply create a new li element in each iteration of the loop:
function createNavigation(booksArray, navElement, unorderedList){
console.log(booksArray)
booksArray.forEach(function(book){
let listItems = document.createElement("LI");
unorderedList.appendChild(listItems);
})
navElement.appendChild(unorderedList);
}
Notice that I've removed the listItems parameter as the value passed into it is now unused.
You can take your program a step further, now, by doing something along these lines:
function createNavigation(booksArray, navElement, unorderedList){
console.log(booksArray)
booksArray.forEach(function(book){
let listItems = document.createElement("LI");
listItems.innerHTML = book.title;
unorderedList.appendChild(listItems);
})
navElement.appendChild(unorderedList);
}
That will create a list of book titles, assuming you have titles stored in a title property in your Book constructor.

How to call/edit all html elements with class names that are found inside an array?

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>

Join two indexes of an array and return the target element, not the object

I have defined two variables, one is the last element of an array, the second is the first element of a child array. Individually each variable return the element but when I chain/join(?) them it returns the object.
How can I target the desired element using the variables I have set?
//define element
let lineNumber = document.getElementsByClassName('lineNumber');
//get last item in array
let lastLine = lineNumber[lineNumber.length - 1];
//define element
let addButton = document.getElementsByClassName('addLine');
//target specific instance in array (
addButton = addButton[0];
//how do I join the two?
let lastButton = lastLine
+ addButton;
lastButton.style = "visibility: visible;";
console.log(lastLine); //this show the element
console.log(addButton); //this shows the element
console.log(lastButton ); //this shows the object, should be the first `add button` of the last item on the `lastline` array.
From the lastLine that you've selected, call querySelector on it to get to the first .addLine inside it:
const addButton = lastLine.querySelector('.addLine');
If you want to retrieve all .addLines inside, use querySelectorAll instead:
const addButtonsInsideLastLine = lastLine.querySelectorAll('.addLine');

appendChild() fails when trying to append a value stored in an array

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..

Deleting an element in json array using Javascript

I want to delete the element from json array using nodejs. My json file match.json is as follows.
[{"id":"1234","time":"3"}]
from this I want to delete the first element so that the json file looks like this:
[]
I tried the following code,its printing an empty array in the console but it is not removing the elements from the match.json file
for(var i=0;i<w;i++)
{
for(var j=0;j<m;j++){
if((words[i].id==match[j].id) && (words[i].time==match[j].time))
{
var f1=0;
//var id1=match[j].id;
var linkadd=words[i].link;
delete match[j];
console.log(match);
}
}
}
Use match.splice(i, 1) instead of delete match[i]
var arr = JSON.parse(Match_json_data);
// remove 1st element
var indexOfItemToRemove = 0;
var noOfItemsToRemove = 1;
arr.splice(indexOfItemToRemove, noOfItemsToRemove);
Reference: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/splice?v=control
This should work:
let myJsonString = '[{"id":"1234","time":"3"}]';
let myEditedJsonString = JSON.stringify(JSON.parse(myJsonString).shift());
to remove the element..you can use splice.. The element will be removed.
{
var f1=0;
//var id1=match[j].id;
var linkadd=words[i].link;
match.splice(i, 1);
console.log(match);
}
If you use delete match[i], the list becomes [undefined]. So use splice.
So basically delete does not delete the element, rather it sets the element as undefined.
const items = [{"id":"1234","time":"3"}]
console.log('before removing item ==> ', items)
items.splice(0 /*index to be removed*/, 1/*no. of items to be removed*/)
console.log('after removing item ==> ', items)
If you want to always take out the first element and update the array the use the following code.
var arr =[{"id":"1234","time":"3"}]
arr.reverse().pop()
If you want to get a subset of the array you can slice the array but it will not update the array but create a new array.
arr.slice(STARTING_ADDRESS,NO_OF_ELEMENTS_TO_SLICE)
NOTE: This will return a new array, So if you want to update the old array then you need to assign it to the old array.
arr = arr.slice(STARTING_ADDRESS,NO_OF_ELEMENTS_TO_SLICE)

Categories