Loop to change text from a cell (A) when you click a button (B) located on the same row as the cell (A) in an HTML table

Asked

Viewed 32 times

0

I have a table with dates on which I am mounting a button that adds seven days to the present value. As there are several lines, the intention is that each date has its own postponement button, however I can’t get the current date of the line where the button responsible for changing it is.

In short, I tried to use filterItem[i] to get the date of each line, but it doesn’t work. In the code below, I left only the third row selects (which gives me an indication that the repeat loop is not working):

Where am I going wrong?

var filterItem = document.getElementById('table').querySelectorAll('td:nth-child(2)')
var adiarEntrega = document.querySelectorAll('.adiar')

for (var i = 0; i < filterItem.length; i++) {
    var dataAtual = filterItem[i].innerHTML;
    var botao = adiarEntrega[i];
    botao.addEventListener('click', function() {
          
    var datainicial = filterItem[2].innerHTML;
    var dias = parseInt(7);
    var partes = datainicial.split("/");
    var ano = partes[2];
    var mes = partes[1]-1;
    var dia = partes[0];

    datainicial = new Date(ano,mes,dia);
    datafinal = new Date(datainicial);
    datafinal.setDate(datafinal.getDate() + dias);

    var dd = ("0" + datafinal.getDate()).slice(-2);
    var mm = ("0" + (datafinal.getMonth()+1)).slice(-2);
    var y = datafinal.getFullYear();

    var dataformatada = dd + '/' + mm + '/' + y;
    filterItem[2].innerHTML = dataformatada
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<table id="table">
  <tr>
  <th>Coluna 1</th>
  <th>Coluna 2</th>
  </tr>
  <tr>
    <td class="adiar">Avançar 7 dias --> </td>
    <td>12/03/2018</td>
  </tr>
  <tr>
    <td class="adiar">Avançar 7 dias --> </td>
    <td>15/06/1962</td>
  </tr>
  <tr>
    <td class="adiar">Avançar 7 dias --> </td>
    <td>23/11/2009</td>
  </tr>
</table>

1 answer

2


I know this response could be a comment, but I wanted to try to elaborate a clear explanation of the subject addressed...

Your case is a serious scope problem because of var, it does not maintain the variable scope i within the for, that is, the value of i is accessible throughout the scope of the script, which generates unexpected results. At the end of the loop, i vale 3 and this generates the error below if we try to use var datainicial = filterItem[i].innerHTML; within the function of eventListener:

Uncaught TypeError: filterItem[i] is undefined

And that’s fact, if you make one console.log(i) within the Listener, he will always show 3, for the value of i was updated because of i++, then it will generate the code filterItem[3].innerHTML and filterItem[3] is undefined:

for (var i = 0; i < filterItem.length; i++) {
  var dataAtual = filterItem[i].innerHTML;
  var botao = adiarEntrega[i];
  botao.addEventListener('click', function () {
    console.log(i) // mostra sempre "3"

    // var datainicial = filterItem[i].innerHTML; <- vai lançar um erro
    var datainicial = filterItem[2].innerHTML;
    var dias = parseInt(7);
    var partes = datainicial.split('/');
    var ano = partes[2];
    var mes = partes[1] - 1;
    var dia = partes[0];

    datainicial = new Date(ano, mes, dia);
    datafinal = new Date(datainicial);
    datafinal.setDate(datafinal.getDate() + dias);

    var dd = ('0' + datafinal.getDate()).slice(-2);
    var mm = ('0' + (datafinal.getMonth() + 1)).slice(-2);
    var y = datafinal.getFullYear();

    var dataformatada = dd + '/' + mm + '/' + y;
    filterItem[2].innerHTML = dataformatada;
  });
}

To solve this, we use the keyword let to ensure that the scope will not be extrapolated, that the value of i for each filterItem[i].innerHTML is the corresponding value in the loop for.

See below the code and even put a console.log to print the value of i:

var filterItem = document.getElementById('table').querySelectorAll('td:nth-child(2)')
var adiarEntrega = document.querySelectorAll('.adiar')

//   ↓↓↓ não use "var"
for (let i = 0; i < filterItem.length; i++) {
  var dataAtual = filterItem[i].innerHTML;
  var botao = adiarEntrega[i];
  botao.addEventListener('click', function () {
    console.log(i); // mostra o valor de acordo com o loop
    //                          ↓↓↓ podemos usar o "i" sem problemas agora
    var datainicial = filterItem[i].innerHTML;
    var dias = parseInt(7);
    var partes = datainicial.split('/');
    var ano = partes[2];
    var mes = partes[1] - 1;
    var dia = partes[0];

    datainicial = new Date(ano, mes, dia);
    datafinal = new Date(datainicial);
    datafinal.setDate(datafinal.getDate() + dias);

    var dd = ('0' + datafinal.getDate()).slice(-2);
    var mm = ('0' + (datafinal.getMonth() + 1)).slice(-2);
    var y = datafinal.getFullYear();

    var dataformatada = dd + '/' + mm + '/' + y;
    filterItem[i].innerHTML = dataformatada;
  });
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<table id="table">
  <tr>
  <th>Coluna 1</th>
  <th>Coluna 2</th>
  </tr>
  <tr>
    <td class="adiar">Avançar 7 dias --> </td>
    <td>12/03/2018</td>
  </tr>
  <tr>
    <td class="adiar">Avançar 7 dias --> </td>
    <td>15/06/1962</td>
  </tr>
  <tr>
    <td class="adiar">Avançar 7 dias --> </td>
    <td>23/11/2009</td>
  </tr>
</table>

To learn more about var, let and scope in Javascript.

  • That’s some dough, Iglan! So just use it let instead of var? Thank you very much for the return and for the clear explanation, my dear!

  • 1

    Exactly! Don’t use anymore var, only let and const to declare variables.

  • Thanks for the tip! =]

Browser other questions tagged

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