AntunCrnja
AntunCrnja

Reputation: 119

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/

Upvotes: 0

Views: 1816

Answers (6)

Danny181
Danny181

Reputation: 1

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();
  
}

});

Upvotes: 0

hartenfeller.dev
hartenfeller.dev

Reputation: 156

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>

Upvotes: 0

Victor Lucas
Victor Lucas

Reputation: 58

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

Upvotes: 0

John
John

Reputation: 6278

You need to just remove the dom element

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

https://jsfiddle.net/tLk5vmy0/

Upvotes: 0

Ognjen
Ognjen

Reputation: 144

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

Upvotes: 1

Abror Abdullaev
Abror Abdullaev

Reputation: 279

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>

Upvotes: 3

Related Questions