Remove elements created within a function

Asked

Viewed 96 times

1

I’m starting in Javascript studies and several doubts have arisen as I’m doing exercises, this specific I could not find a content in Portuguese that explains well.

Next, I have two buttons: one that adds an item and another that removes that added item. The problem is that I am unable to find a way to always remove the last item added by clicking the remove button. I could only make it work by removing all the items at once.

<div class="adicionar-produtos">
<button id="remove-vip" class="btn-produtos"> - </button>
<button id="add-vip" class="btn-produtos">+</button>
</div>

By clicking the button the item is added here:

<div class="item-adicionado">
 <p class="item-adicionado-main"> </p>
 </div>

Javascript:

var botao_adicionar_vip = document.querySelector("button#add-vip");
var containerItemAdicionado = document.querySelector(".item-adicionado-main");
var botao_remover_vip = document.querySelector("#remove-vip");



botao_adicionar_vip.onclick = function() {

item_vip = document.createElement("p");
item_vip_text = document.createTextNode("Item Vip 1");
item_vip.className = "teste1";
item_vip.appendChild(item_vip_text);
containerItemAdicionado.appendChild(item_vip);

};


botao_remover_vip.onclick = function() {
document.querySelectorAll('.teste1').forEach(e => e.remove());
};

https://jsfiddle.net/wjykgxdn/

2 answers

4

You are removing all elements because of this excerpt from your code:

document.querySelectorAll('.teste1').forEach(e => e.remove());

He will basically select all added elements and iterate over each of them by removing them individually.

You need to select the last element within the element .teste1. There are several ways to select the last element.

Using the pseudo selector :last-child

const element = document.querySelector('.teste1 > *:last-child');

if (element) {
  element.remove();
}

This will make you select the last child that is inside the first element found with the class .classe1. For this, we use the pseudo-selector :last-child.

If your environment endure, you can even use the new syntax of optional chaining (optional chaining), introduced in the latest version of Ecmascript:

document.querySelector('.teste1 > *:last-child')?.remove();

A functional example:

const button = document.querySelector('.remove');

button.addEventListener('click', () => {
  const element = document.querySelector('.teste1 > *:last-child');
  
  if (element) {
    element.remove();
  }
});
<button class="remove">Remover Último</button>

<div class="teste1">
  <div>Filho 01</div>
  <div>Filho 02</div>
  <div>Filho 03</div>
  <div>Filho 04</div>
</div>

Use the API ParentNode.lastElementChild

This is a "native" Javascript API. It’s older, which gives greater support for legacy environments. It is also a little simpler, as no CSS pseudo-selectors are involved.

Behold:

const button = document.querySelector('.remove');

button.addEventListener('click', () => {
  const parent = document.querySelector('.teste1');
  const element = parent.lastElementChild;
  
  if (element) {
    element.remove();
  }
});
<button class="remove">Remover Último</button>

<div class="teste1">
  <div>Filho 01</div>
  <div>Filho 02</div>
  <div>Filho 03</div>
  <div>Filho 04</div>
</div>

If the environment supports, you can also make use of the new optional chaining syntax to avoid the declaration if.

Retrieve all children and select the last element of the array

Finally, you can get all children using the API ParentNode.children, that returns a HTMLCollection (an array type, but with some differences). From this collection, just get your last element.

Thus:

const button = document.querySelector('.remove');

button.addEventListener('click', () => {
  const parent = document.querySelector('.teste1');
  const children = parent.children;
  const element = children[children.length - 1];
  
  if (element) {
    element.remove();
  }
});
<button class="remove">Remover Último</button>

<div class="teste1">
  <div>Filho 01</div>
  <div>Filho 02</div>
  <div>Filho 03</div>
  <div>Filho 04</div>
</div>

Surely there are more ways to do this, but I will stop here. :)

3


Your forEach is removing all.

You can do so to remove the last:

botao_remover_vip.onclick = function() {
   const itens = document.querySelectorAll('.teste1');
   if(itens.length){
      itens[itens.length-1].remove();
   }
};

First creates a variable itens that selects all created elements:

const itens = document.querySelectorAll('.teste1');

Then a if to check if there is at least one item:

if(itens.length){

If it exists, you remove the last one, which is the variable size itens -1. The querySelectorAll creates a nodelist where each element has an index based on 0, equal to an array, where the number of elements in the nodelist is equal to the total size -1:

itens[itens.length-1].remove();

See working:

var botao_adicionar_vip = document.querySelector("button#add-vip");
var containerItemAdicionado = document.querySelector(".item-adicionado-main");
var botao_remover_vip = document.querySelector("#remove-vip");

botao_adicionar_vip.onclick = function() {

   item_vip = document.createElement("p");
   item_vip_text = document.createTextNode("Item Vip 1");
   item_vip.className = "teste1";
   item_vip.appendChild(item_vip_text);
   containerItemAdicionado.appendChild(item_vip);

};


botao_remover_vip.onclick = function() {
   const itens = document.querySelectorAll('.teste1');
   if(itens.length){
      itens[itens.length-1].remove();
   }
};
<div class="adicionar-produtos">
<button id="remove-vip" class="btn-produtos"> - </button>
<button id="add-vip" class="btn-produtos">+</button>
</div>
<div class="item-adicionado">
 <p class="item-adicionado-main"> </p>
 </div>

Try to declare your variables with var, let or const (depending on the case. See more information in this topic) to avoid global variables. For example:

let item_vip = document.createElement("p");

Browser other questions tagged

You are not signed in. Login or sign up in order to post.