0

I have a problem with javascript on click. I have to add some input box when I press add more button but it didn't work.

Javascript

var i = $('table tr').length;
var count = $('table tr').length;
var row = i;
var a = 0;

for (a = 0; a <= i; a++) {
  $(".addmore_" + a).on('click', function() {
    var data = "<input class='form-control' type='text' id='packinglist_" + a + "' name='packinglist[]'/>";
    $("#keatas_" + a).append(data);
  });
};

HTML

for ($i = 1; $i <= 5; $i++) {
  echo "<tr>
    <td><span id='snum'>$i.</span>
    </td>
    <input class='form-control' type='hidden' id='hiddenlot_$i' name='hiddenlot[]' />
    <input class='form-control' type='hidden' id='hiddencustomer_$i' name='hiddencustomer[]' />
    <input class='form-control' type='hidden' id='hiddenprice_$i' name='hiddenprice[]' />
    <td>
      <input class='form-control' type='text' id='jenisbenang_$i' name='jenisbenang[]' readonly/>
    </td>
    <td>
      <input class='form-control' type='text' id='warna_$i' name='warna[]' readonly/>
    </td>
    <td>
      <input class='form-control' type='text' id='lot_$i' name='lot[]' required/>
    </td>
    <td>
      <input class='form-control sedang' type='text' id='netto_$i' name='netto[]' required/>
    </td>
    <td>
      <input class='form-control pendek' type='text' id='box_$i' name='box[]' />
    </td>
    <td>
      <input class='form-control pendek' type='text' id='cones_$i' name='cones[]' />
    </td>
    <td>
      <input class='form-control' type='text' id='keterangan_$i' name='keterangan[]' />
    </td>
    <td><a><span class='glyphicon glyphicon-plus addmore_$i'></span></a> 
    </td>
  </tr>
  <tr>
    <td colspan='10'>
      <div id='keatas_$i'>

      </div>
    </td>
  </tr>";
}

so ignore the code with input text-box , i want to append data to this :

<td colspan='10'>
  <div id='keatas_$i'>

  </div>
</td>
</tr>";

Any response would be appreciated!

Thanks.

1

1 Answer 1

1

Your variable a is bind to its latest value, so it won't work. You need to make a copy of a:

var i = $('table tr').length;
var count = $('table tr').length;
var row = i;
var a = 0;

for (a = 0; a <= i; a++) {
  $(".addmore_" + a).on('click', function (_a) {
    return function() {
      var data = "<input class='form-control' type='text' id='packinglist_" + _a + "' name='packinglist[]'/>";
      $("#keatas_" + _a).append(data);
    } ;
  } (a));
};

Explanation:

I will use setTimeout instead of your custom callback because it is easier to see what happen. Let's start with a simple example:

for (var i = 0 ; i < 5 ; i++) {
    setTimeout (function () {
        console.log(i) ;
    }, 250) ;
}

If you don't know setTimeout, it will simply call the function you specified (first argument) after the amount of time specified by the second argument (in milliseconds, 250ms in this example).

The output you expect for the above code is:

0 1 2 3 4

But what you actually get is:

5 5 5 5 5

So, why is that?

When you create the lambda function in the loop, you do not bind the current value of i, so the i used in the lambda function is actually a reference to the loop variable i.

When the lambda functions get called, they will retrieve the current value of the i variable, which is 5 at the end of the loop, thus you get the above output.

How to deal with it?

What you want is force the lambda function to use the value that i had at the time you created it. One way to do it, is to create a function and immediately call it:

function (_i) {
    // whatever
} (i)

By calling the function, you "detach" your variable from its original reference i and give it to a new reference _i. But since you are creating a new reference _i at each loop, the value will be bind correctly.

What you need to do then is create and return another lambda function using your new variable _i by setTimeout:

function (_i) {
    return function () {
        console.log(_i) ;
    } ;
} (i)

The full code:

for (var i = 0 ; i < 5 ; i++) {
    setTimeout (function (_i) {
        return function () {
            console.log(_i) ;
        } ;
    } (i), 250) ;
}

Output:

0 1 2 3 4

Note that in the original code of this answer, I was using the name a to reference both the loop variable and the temporary copy, which was confusing.

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

4 Comments

WOW ! its workingg , thanks a lot dude but i still dont understand what the problem is , so i have to put 'a' into function and return it ? and what for 'a' at last row in your code ? but thanks a lot dude , you saved my life
@JeremyHermawan See my updated answer, and feel free to comment if you don't understand everything. This answer is closely related. This problem often arises in javascript when you try to call setTimeout in a loop or do AJAX call in loop (you may search for javascript loop setTimeout/ajax on google to find extra explanation).
i got it a little lol , but in my case i want to incrase the number of 'id='packinglist_" + _a + "'' and foreach i click "add more" the number of ID input text box will increase by 1 . i want trying your code for my 2nd problem but i dont know to do that , may you help me once again please ?
@JeremyHermawan If you have a second problem (which is not in your original question), you should post a new question on SO.

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.