简体   繁体   中英

Delete object from array on click

I need help with deleting an object from the array.

The names(array.name) from the objects are displayed in the DOM and I want to delete them using the erase X button.

In this code I can only delete one element and then stops working with no console error. Does anyone have an idea where I am wrong and why I can't call the create() function every time I click on an erase button.

Look at console.log... it shows the good position and name of the element to be deleted, but everything stops when I call create() function, try uncomment create().

 const array = [ {name: 'John'}, {name: 'David'}, {name: 'Peter'}, {name: 'Michael'} ]; const create = () => { const app = document.querySelector('.app'); app.innerHTML = ''; for(let i = 0; i < array.length; i++) { app.innerHTML += `<div class="item"><span class="erase">&#9747;</span>${array[i].name}</div>`; } } create(); const erase = document.querySelectorAll('.erase'); erase.forEach(item => { item.onclick = () => { const itemText = item.parentElement.textContent.substr(1); const itemPos = array.findIndex(item => item.name == itemText); console.log(itemText + ' ' + itemPos); console.log(array); array.splice(itemPos, 1); //create() } });
 .erase { color: red; margin-right: 20px; cursor: pointer; }.item { margin-bottom: 10px; }
 <div class="app"></div>

Or as fiddle: https://jsfiddle.net/05cwy9d2/3/

Its because when you create new elements in the dom the listeners of old elements are being removed together with the old elements. Just move the event listener registration into create method.

 const array = [ {name: 'John'}, {name: 'David'}, {name: 'Peter'}, {name: 'Michael'} ]; const create = () => { const app = document.querySelector('.app'); app.innerHTML = ''; for(let i=0;i<array.length;i++){ app.innerHTML += `<div class="item"><span class="erase">&#9747;</span>${array[i].name}</div>`; } const erase = document.querySelectorAll('.erase'); erase.forEach(item => { item.onclick = () => { const itemText = item.parentElement.textContent.substr(1); const itemPos = array.findIndex(item => item.name == itemText); console.log(itemText + ' ' + itemPos); console.log(array); array.splice(itemPos, 1); create(); } }); } create();
 .erase{ color: red; margin-right: 20px; cursor: pointer; }.item{ margin-bottom: 10px; }
 <div class="app"></div>

const array = [
  {name: 'John'},
  {name: 'David'},
  {name: 'Peter'},
  {name: 'Michael'}
]; 

const create = () => {
    const app = document.querySelector('.app');
    app.innerHTML = '';

    for(let i=0;i<array.length;i++){
      app.innerHTML += 
      `<div class="item"><span class="erase">&#9747;</span>${array[i].name}</div>`;
    }
}
create();

const erase = document.querySelectorAll('.erase');

erase.forEach(item => {

    item.onclick = () => {
      const itemText = item.parentElement.textContent.substr(1);
      const itemPos = array.findIndex(item => item.name == itemText);
    
        console.log(itemText + ' ' + itemPos);
        
        if(itemPos >-1){
            array.splice(itemPos, 1);
            item.parentElement.remove();
        }
        console.log(array);
    }
});

This works now. I have removed DOM when clicked on erase and disabled user to delete an element that has already been deleted (if index == -1).

You need to just remove the dom element

    e.target.parentNode.parentNode.removeChild(e.target.parentNode);

https://jsfiddle.net/tLk5vmy0/

I moved the eventlistener code to the create function because the need to get recreated when one event occured. You could also use the EventTarget.addEventListener() method to bind eventlisteners to every single DOM-element.

I would also prefer to use the Array.prototype.filter() method to remove the clicked value for better readability:

 let array = [ {name: 'John'}, {name: 'David'}, {name: 'Peter'}, {name: 'Michael'} ]; const addEventListeners = () => { const erase = document.querySelectorAll('.erase'); erase.forEach(item => { item.onclick = (e) => { const itemText = item.parentElement.textContent.substr(1); array = array.filter(entry => entry.name;== itemText); create(); } }). } const create = () => { const app = document.querySelector(';app'). app;innerHTML = ''; for(let i=0.i<array;length.i++){ app;innerHTML += `<div class="item"><span class="erase">&#9747.</span>${array[i];name}</div>`; } addEventListeners(); } create();
 <div class="app"></div>

You can use the method removeChild to remove the element from your DOM, this way will prevent to re-render (with create method) every time you remove an item from the array. This way, your code will need some changes, the first of these is to have an id for each element of your array:

for(let person of array){
  app.innerHTML += 
  `<div class="item" id="${person.name}"><span class="erase">&#9747;</span>${person.name}</div>`;
}

After having the "person" name as your id (I recommend that you have a real identifier, like a number, but for this example the name will help us), you can only remove that node from DOM:

const elementToRemove = document.getElementById(item.parentElement.id);
elementToRemove.parentNode.removeChild(elementToRemove);

To enhance, you can check if the node exists, and if not you can throw an error to your console:

const elementToRemove = document.getElementById(item.parentElement.id);

if (!elementToRemove) throw new Error(`Element ${item.parentElement.id} not found!`)

elementToRemove.parentNode.removeChild(elementToRemove)

I recommend that you read the Node section on MDN this can be useful to add other elements to the list, edit some elements, and more. :)

instead of calling create() function again and creating new child elements for class '.app' you would use item.parentElement.remove(); in place of create() in onClick. That would have same result.

erase.forEach(item => {

item.onclick = () => {
 console.log()
  const itemText = item.parentElement.textContent.substr(1);
  const itemPos = array.findIndex(item => item.name == itemText);

    console.log(itemText + ' ' + itemPos);
    console.log(array);
    array.splice(itemPos, 1);
   item.parentElement.remove(); // this will remove your element.
  // create();
  
}

});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM