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>

6
  • var arrId = arr[i]; to let arrId = arr[i]; Commented Dec 12, 2017 at 12:41
  • or let arrId = arr[i]; Commented Dec 12, 2017 at 12:42
  • I cannot use let. It says Let definitions are not supported by current JavaScript version. Commented Dec 12, 2017 at 12:43
  • stackoverflow.com/questions/30960460/… Commented Dec 12, 2017 at 12:49
  • I switched from 5.1 to 6. Thanks for the comments. let solved the solution. But why should I use let in this case? Commented Dec 12, 2017 at 12:50

2 Answers 2

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>

Sign up to request clarification or add additional context in comments.

Comments

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

}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.