Increase index of a form's input field's name attribute in a dynamic form

Viewed 1239

Suppose I have this form with indexed input fields username and level:

<form>
 <table>
  <tr class="trToClone">
    <td>
      <label>Username:</label>
      <input type="text" name="username[0]" />
    </td>
    <td>
      <label>Level:</label>
      <select name="level[0]">
        <option value="">---</option>
        <option value="a">A</option>
        <option value="b">B</option>
        <option value="c">C</option>
      </select>
    </td>
    <td><input type="button" class="addField" value="Add" /></td>
  </tr>
 </table>  
</form>

The row can be repeated using this jQuery:

$("input.addField").on('click', function() {
  var $tr = $(this).closest('.trToClone');
  var $clone = $tr.clone();
  $clone.find(':text').val('');
  $tr.after($clone);
});

Now for every subsequent row I add, I want to increase the indices of the name attribute (i.e. username[1],level[1]; username[2],level[2]; and so on...). How can I do this? I've looked for possible solutions, but to no avail.

4 Answers

Specify new index with $('.trToClone').length, modify it on each element with name attribute with jQuery .attr() method:

$("input.addField").on('click', function() {
  var $tr = $(this).closest('.trToClone');
  var $clone = $tr.clone(true, true);
  
  var $names = $clone.find('[name]');
  var trIndex = $('.trToClone').length;
  
  $names.each(function(index, element) {
     
    var newName = $(element).attr('name').replace(/[0-9]/g, trIndex);
   
    $(element).attr('name', newName);
    
    console.log($(element).attr('name'));
  
  });
  
  $clone.find(':text').val('');
  $tr.after($clone);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
 <table>
  <tr class="trToClone">
    <td>
      <label>Username:</label>
      <input type="text" name="username[0]" />
    </td>
    <td>
      <label>Level:</label>
      <select name="level[0]">
        <option value="">---</option>
        <option value="a">A</option>
        <option value="b">B</option>
        <option value="c">C</option>
      </select>
    </td>
    <td><input type="button" class="addField" value="Add" /></td>
  </tr>
 </table>  
</form>

$('.addField').click(function(){
  var count = $('#btnIncrease').val();
  var $tr = $(this).closest('.trToClone');
  var $clone = $tr.clone();
  count++;
  $('#btnIncrease').val(count);
  $clone.find(':text').val('');
  $clone.find(':text').attr('name', 'username[' + count + ']');
  $tr.after($clone); 
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
  <tr class="trToClone">
    <td>
      <label>Username:</label>
      <input type="text" name="username[0]" />
    </td>
    <td>
      <label>Level:</label>
      <select name="level[0]">
        <option value="">---</option>
        <option value="a">A</option>
        <option value="b">B</option>
        <option value="c">C</option>
      </select>
    </td>
    <td><input type="button" class="addField" value="Add" /></td>
  </tr>
 </table>
 
 <input type="hidden" id="btnIncrease" value="0" />

This would work for you.

UPDATE: changing name attributes dynamically.

you can use a counter for counting your clicks! You have to move the "add" click button out of the table row. HTML:

<form>
 <input type="button" class="addField" value="Add" />
 <table>
  <tr class="trToClone">
    <td>
      <label>Username:</label>
      <input type="text" name="username[0]" />
    </td>
    <td>
      <label>Level:</label>
      <select name="level[0]">
        <option value="">---</option>
        <option value="a">A</option>
        <option value="b">B</option>
        <option value="c">C</option>
      </select>
    </td>
    <td></td>
  </tr>
 </table> 
</form>

JS:

var counter = 0;
$("input.addField").on('click', function() {
    counter++;
  var $tr = $('.trToClone:eq(0)');
  var $clone = $tr.clone();
  var newTextName = $clone.find(':text').attr('name').replace(/\[(\d)+\]/,'[+ counter +']');
  $clone.find(':text').attr('name',newTextName);
  $clone.find('.dropdown').attr('name','level['+ counter + ']');
  $tr.parent().append($clone);
});

check out this fiddle: https://jsfiddle.net/gknrfw1g/2/

For adding the name attribute you first need to find the index of current row and then you can add 1 to the index and again update the name attribute for both text and select list. Try with the code below-

Note- You should also hide the add button from previous row and bind the click function again for the newly cloned row.

 $("input.addField").on('click', function() {
      var $tr = $(this).closest('.trToClone');
      var $clone = $tr.clone();
      var lastIndexName= $clone.find(':text').attr("name").split('[');
      var lastIndex=parseInt(lastIndexName[1].substring(0,1));
      var updatedNameValue="username["+(lastIndex+1)+"]";
      $clone.find(':text').attr("name",updatedNameValue);
      $clone.find(':text').val('');
      $clone.find('select').attr("name","level["+(lastIndex+1)+"]")
      $tr.after($clone);
    });

Related