0

I am creating dynamic inputs in a for loop. Each input has its own onchange function which checks if its value is bigger than array value. In every onchange function, arrId variable is always 6 which is the last element in the array.

Is there any possibility to make it correct? If lets say I change first input, arrId should be the first element in the array, not the last element. But arrId is always the last element in the array.

var arr = ["22", "12", "15", "6"];

for (var i = 0; i < arr.length; i++) {

  var arrId = arr[i];

  var input = document.createElement("input");
  input.value = 0;
  input.type = "number";
  input.onchange = function(x) {

    console.log(x.target.value + " " + arrId);

    if (parseInt(x.target.value) > parseInt(arrId)) {

      x.target.value = arrId;
    }
  }

  document.getElementById("inputs").appendChild(input);

}
input {
  display: block;
  margin: 10px 0;
}
<div id="inputs">

</div>
Eniss
  • 975
  • 2
  • 20
  • 40

2 Answers2

1

It is showing always the last value of the i, because 6 is the last value, the function that you call on change will remember only the last value in its scope, In order to solve it you need to create a new scope so the function will remember the current value you can do it with IIFE.

var arr = ["22", "12", "15", "6"];

for (var i = 0; i < arr.length; i++) {

  var arrId = arr[i];

  var input = document.createElement("input");
  input.value = 0;
  input.type = "number";
  (function(i,input){
    input.onchange = function(x) {

      console.log(x.target.value + " " + i);

      if (parseInt(x.target.value) > parseInt(arrId)) {

        x.target.value = arrId;
      }
    }
  })(arrId,input);
  
  document.getElementById("inputs").appendChild(input);

}
input {
  display: block;
  margin: 10px 0;
}
<div id="inputs">

</div>

Another solution using ES6 is to declare your variables with let, since this is block scoped variable the value will live only in the loop.

var arr = ["22", "12", "15", "6"];

for (let i = 0; i < arr.length; i++) {

  let arrId = arr[i];

  let input = document.createElement("input");
  input.value = 0;
  input.type = "number";
    input.onchange = function(x) {

      console.log(x.target.value + " " + arrId);

      if (parseInt(x.target.value) > parseInt(arrId)) {

        x.target.value = arrId;
      }
    }
  
  document.getElementById("inputs").appendChild(input);

}
input {
  display: block;
  margin: 10px 0;
}
<div id="inputs">

</div>
Renzo Calla
  • 7,486
  • 2
  • 22
  • 37
0

Important: JavaScript does not have block scope. Variables introduced with a block are scoped to the containing function or script, and the effects of setting them persist beyond the block itself. In other words, block statements do not introduce a scope. Although "standalone" blocks are valid syntax, you do not want to use standalone blocks in JavaScript, because they don't do what you think they do, if you think they do anything like such blocks in C or Java.

var arr = ["22", "12", "15", "6"];

var input = document.createElement("input");
input.value = 0;
 input.type = "number";

for (var i = 0; i < arr.length; i++) {
(function(val){
  var arrId = val;

    var input = document.createElement("input");
    input.value = 0;
    input.type = "number";
    input.onchange = function(x) {

      console.log(x.target.value + " " + arrId);

      if (parseInt(x.target.value) > parseInt(arrId)) {

        x.target.value = arrId;
      }

})(arr[i],input)
}

document.getElementById("inputs").appendChild(input);

}
hannad rehman
  • 4,133
  • 3
  • 33
  • 55