Get clicked element position

Asked

Viewed 2,427 times

6

I have a list of entries and one of the attributes of that item is a delete button.

By clicking the button I want to know the position of the line clicked inside the list.

When knowing the position I will delete from the array the same value of the posição[i]

removeLinha(element){
    //Aqui eu obtenho a 'tr' clicada
    let trash = element.parentNode.parentNode; 

    //Aqui eu removo;
    trash.parentNode.removeChild(trash);
}

But before I remove I need to know the position of <tr> inside <tbody> to delete in array as well.

NOTE: The big problem is that the method of adding a new line in the DOM it scans an array of objects and puts in the DOM, so I need to know the position of the line to know its position in the array and delete as well.

  • actually this is coming as argument in the method call there in HTML.

  • I’m using a controller class, so if I use this inside it, it selects the class itself...

  • "to delete in the array as well" - which array ? was built as ? You can include both the array and the html where the function is called removeLinha ?

  • the array is dynamically populated with a goal that generates an element: <tr><td></td><td></td><td></td><td></td></tr> then each item of my array is a row of my table

5 answers

2

With these pure JS, you get the position index from the button line clicked and eliminates the line.

Using eventListener:

window.onload = escuta;

botoes = document.getElementsByClassName("apagar");
function escuta(){
  for(x=0;x<botoes.length;x++){
    // arranjo os listeners com os index das linhas
    (function(index){
      botoes[x].addEventListener("click", function(){
        removeLinha(index);
      });
    })(x);
  }
}
	
function removeLinha(element){ // element é o index da linha clicada
   console.log(element); // mostrar index da linha como exemplo
  //removo a linha
  botoes[element].closest('tr').outerHTML = '';
  // removo os listeners
  for(x=0;x<botoes.length;x++){
    objclone = botoes[x].cloneNode(true);
    botoes[x].parentNode.replaceChild(objclone, botoes[x]);
  }
  escuta();
}
<table>
    <tr>
      <td>Linha 1</td>
      <td><input class="apagar" type="button" value="X" /></td>
    </tr>
    <tr>
      <td>Linha 2</td>
      <td><input class="apagar" type="button" value="X" /></td>
    </tr>
    <tr>
      <td>Linha 3</td>
      <td><input class="apagar" type="button" value="X" /></td>
    </tr>
    <tr>
      <td>Linha 4</td>
      <td><input class="apagar" type="button" value="X" /></td>
    </tr>
</table>

Using onclick:

function removeLinha(element){
  var el = element.closest('tr');
  var index = Array.prototype.indexOf.call(el.parentNode.children, el);
  console.log(index); // mostrar posição da linha como exemplo
  //removo a linha
  el.outerHTML = '';
}
<table>
    <tr>
      <td>Linha 1</td>
      <td><input class="apagar" type="button" value="X" onclick="removeLinha(this)" /></td>
    </tr>
    <tr>
      <td>Linha 2</td>
      <td><input class="apagar" type="button" value="X" onclick="removeLinha(this)" /></td>
    </tr>
    <tr>
      <td>Linha 3</td>
      <td><input class="apagar" type="button" value="X" onclick="removeLinha(this)" /></td>
    </tr>
    <tr>
      <td>Linha 4</td>
      <td><input class="apagar" type="button" value="X" onclick="removeLinha(this)" /></td>
    </tr>
</table>

1

An alternative is to use the rowIndex, which takes the actual position of the element in the DOM, just reference it with this, example.

var arr = ['tr1','tr2'];

var tr = document.querySelectorAll("tr");

for(var i=0; i<tr.length; i++){
  tr[i].onclick = function(){ 
      index = this.rowIndex;
      if(arr[index]) arr.splice(index, 1);
      this.parentElement.removeChild(this);
      console.log('tr clicada, posição ' + index + ' / arr: ' + arr);
 }
}
<table>
  <tr id="tr1">
    <td>teste</td>
    <td>teste1</td>
    <td>teste2</td>
  </tr>
  <tr id="tr2">
    <td>teste3</td>
    <td>teste4</td>
  </tr>
</table>

1


You can use the .closest('tr') to get the tr and then the .indexOf(.

For example:

function removeLinha(element) {
  const trash = element.closest('tr');
  const index = [...trash.parentNode.children].indexOf(trash);
  trash.parentNode.removeChild(trash);


  console.log('Index era:', index); // só para o exemplo
}
tr td:last-of-type:hover { color: #e88; }
<table id="codexpl">
  <tr>
    <td>1</td>
    <td>This</td>
    <td>Column</td>
    <td onclick="removeLinha(this)">Remove</td>
  </tr>
  <tr>
    <td>2</td>
    <td>Coloumn</td>
    <td>two</td>
    <td onclick="removeLinha(this)">Remove</td>
  </tr>
  <tr>
    <td>3</td>
    <td>is</td>
    <td>not equals</td>
    <td onclick="removeLinha(this)">Remove</td>
  </tr>
  <tr>
    <td>4</td>
    <td>the</td>
    <td>Column</td>
    <td onclick="removeLinha(this)">Remove</td>
  </tr>
  <tr>
    <td>5</td>
    <td>first</td>
    <td>One</td>
    <td onclick="removeLinha(this)">Remove</td>
  </tr>
</table>

0

Suppose you select one tr and then click a button to delete.

Follow the example(I used jquery because I’m used to the code, but just adapt the logic):

$(document).ready(function() {
  var tid = "";
  $('#sua_tabela tr').click(function(event) {
    tid = $(this).attr('id');
  });
  $("#del").click(function() {
    console.log(tid);
    if ($('#' + tid).length) {
      $('#' + tid).remove();
    }
  });
});

Explaining:
I store the tr that you selected in a variable. When I click the delete button it removes the tr selected, to remove more than 1 just create an array, place each 1 of the selected within the array and at the click of delete do a for traversing this array.
Or to remove directly by clicking on tr, use this example of a gringo:
https://stackoverflow.com/questions/11553768/remove-table-row-after-clicking-table-row-delete-button

  • That’s right, my code is very similar to the gringo version that responded with pure JS. I’m using classes and methods...

  • The point is that when I delete and add another, it searches within an array of several <tr> elements and puts it into the gift, if I do not delete from the array it will add again...

  • 1

    I understood your doubt... Well, have you ever thought about putting a counter inside the tr that follows the array together? (put inside the id, for example). Thus, when selecting tr vc you will get this value and then vc can remove using the array.splice(array, var_com_posicao_da_tr)

  • Example: <tr><td id='0'>item1</td></tr> <tr><td id='1'>item1</td></tr>and then take td.id

  • The idea is valid!!

0

to get the Intel, you can use a indexOf on the children.

var btsApagar = document.querySelectorAll(".apagar");
var onApagarClick = function (evt) {
  var linha = this.parentElement.parentElement;
  var nodes = [].slice.call(linha.parentElement.children, 0);
  var index = nodes.indexOf(linha);
  console.log(index);
};

[].forEach.call(btsApagar, function (apagar, indice) {
  apagar.addEventListener("click", onApagarClick);
});
<table>
  <thead>
    <tr>
      <th>Coluna 01</th>
      <th>Coluna 02</th>
      <th>Ações</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Valor 1.1</td>
      <td>Valor 1.2</td>
      <td><input class="apagar" type="button" value="Apagar" /></td>
    </tr>
    <tr>
      <td>Valor 2.1</td>
      <td>Valor 2.2</td>
      <td><input class="apagar" type="button" value="Apagar" /></td>
    </tr>
    <tr>
      <td>Valor 3.1</td>
      <td>Valor 3.2</td>
      <td><input class="apagar" type="button" value="Apagar" /></td>
    </tr>
  </tbody>
</table>

but it might be interesting to use some blibiotace to help you keep the DOM and array synchronized.

var app = new Vue({
  el: '#tabela',
  data: {
    lista: [
      { valor1: "Valor 1.1", valor2: "Valor 1.2" },
      { valor1: "Valor 2.1", valor2: "Valor 2.2" },
      { valor1: "Valor 3.1", valor2: "Valor 3.2" },
      { valor1: "Valor 4.1", valor2: "Valor 4.2" },
      { valor1: "Valor 5.1", valor2: "Valor 5.2" },
      { valor1: "Valor 6.1", valor2: "Valor 6.2" },
    ]
  },
  methods: {
    apagar: function (item) {
      var index = this.lista.indexOf(item);
      this.lista.splice(index, 1);
      console.log(index);
    } 
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.2/vue.js"></script>
<table id="tabela">
  <thead>
    <tr>
      <th>Coluna 01</th>
      <th>Coluna 02</th>
      <th>Ações</th>
    </tr>
  </thead>
  <tbody>
    <tr v-for="item in lista">
      <td>{{item.valor1}}</td>
      <td>{{item.valor2}}</td>
      <td><input type="button" value="Apagar" v-on:click="apagar(item)" /></td>
    </tr>
  </tbody>
</table>

Browser other questions tagged

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