Lewis Smith
Lewis Smith

Reputation: 1345

Jquery, .length + 1 seems to be adding multiples of 7

I have a jquery script to add some input fields at the click of a button, I need these to be numbering up, so there are 4 fields called first:

JSFIDDLE LINK http://jsfiddle.net/1orkxk2y/

ptno1
desc1
qty1
amnt1

when add field is clicked I expected this to be but I ended up with the numbers in brackets:

ptno2(7)
desc2(7)
qty2(7)
amnt2(7)

Code below:

$(document).ready(function() {
    $("#add").click(function() {
        var intId = $("#test div").length + 1;
        var fieldWrapper = $("<div id=\"test\" class=\"row\"/>");
        var fptno = $("<div class=\"col-md-2\"><input type=\"text\" name=\"ptno" + intId + "\" class=\"form-control\" /></>");
        var fdesc = $("<div class=\"col-md-2\"><input type=\"text\" name=\"desc" + intId + "\" class=\"form-control\" /></>");
        var fqty = $("<div class=\"col-md-2\"><input type=\"text\" name=\"qty" + intId + "\" class=\"form-control\" /></>");
        var famnt = $("<div class=\"col-md-2\"><input type=\"text\" name=\"amnt" + intId + "\" class=\"form-control\" /></>");
        var removeButton = $("<div class=\"col-md-2\"><input type=\"button\" class=\"remove\" value=\"-\" /></>");
        removeButton.click(function() {
            $(this).parent().remove();
        });
        fieldWrapper.append(fptno);
        fieldWrapper.append(fdesc);
        fieldWrapper.append(fqty);
        fieldWrapper.append(famnt);
        fieldWrapper.append(removeButton);
        $("#buildyourform").append(fieldWrapper);
    });
});

<fieldset id="buildyourform">
</fieldset>
<input type="button" value="Add a charge" class="add" id="add" />

Upvotes: 0

Views: 68

Answers (3)

Simon
Simon

Reputation: 794

The expression $("#test div") will get every div inside every #test. Since you add 5 div inside #test each time, the length attribute will increment by 5. Perhaps you could simply use a global variable instead of reading the DOM each time?

var intId = 1;

$(document).ready(function() {
    $("#add").click(function() {
        var fieldWrapper = $("<div id=\"test\" class=\"row\"/>");
        var fptno = $("<div class=\"col-md-2\"><input type=\"text\" name=\"ptno" + intId + "\" class=\"form-control\" /></>");
        ...
        intId++;
    });
});

Edit: Thanks Tim Lewis for pointing out that multiple id attributes produces invalid HTML.

Upvotes: 3

Marko Mackic
Marko Mackic

Reputation: 2333

First of, when you're appending to something make sure that you close the element tag, and secondly you can't query $('#test div') because it will query the divs inside the id named test, no matter the level. So your code should be :

$(document).ready(function() {
    function reIndex(){
      $('.test').each(function(index,element){    
         $(element).children().each(function(){    
           var inp_elem = $(this).children("input");
           if(inp_elem.attr("name").split("_").length == 2)
             {
              inp_elem.attr("name",inp_elem.attr("name").split("_")[0] + "_" + (index+1));
             }
      });
    });
    }
    $("#add").click(function() {
        var intId = $(".test").length + 1;
        var fieldWrapper = $("<div class=\"test row\"/></div>");
        var fptno = $("<div class=\"col-md-2\"><input type=\"text\" name=\"ptno_" + intId + "\" class=\"form-control\" /></div>");
        var fdesc = $("<div class=\"col-md-2\"><input type=\"text\" name=\"desc_" + intId + "\" class=\"form-control\" /></div>");
        var fqty = $("<div class=\"col-md-2\"><input type=\"text\" name=\"qty_" + intId + "\" class=\"form-control\" /></div>");
        var famnt = $("<div class=\"col-md-2\"><input type=\"text\" name=\"amnt_" + intId + "\" class=\"form-control\" /></div>");
        var removeButton = $("<div class=\"col-md-2\"><input type=\"button\" class=\"remove\" value=\"-\" /></div>");
        removeButton.click(function() {
            $(this).parent().remove();
            reIndex();
        });
        fieldWrapper.append(fptno);
        fieldWrapper.append(fdesc);
        fieldWrapper.append(fqty);
        fieldWrapper.append(famnt);
        fieldWrapper.append(removeButton);
        $("#buildyourform").append(fieldWrapper);
    });
});

I missed a thing Does ID have to be unique in the whole page? ID of element has to be unique because it gives an element a name, so you could use it with a class test. EDIT: I added reindexing when element is removed, so the indexing would be consistent and no overlaps will occur :) and here is a new fiddle http://jsfiddle.net/1orkxk2y/3/

Upvotes: 0

Jonathan Michalik
Jonathan Michalik

Reputation: 1532

$("#test div").length is returning the number of div elements that have a parent with an id of test. Currently, you are generating a new container for these inputs, all with an id of test, so they all meet the criteria for the selector.

I'd like to point out, first, that creating multiple elements with the same id is invalid HTML. Something you can do to address the iterator and duplicate id problems in one swoop is to use the row class that you're already placing on your input containers:

$("#add").click(function() {
        var intId = $(".row").length + 1;
        var fieldWrapper = $("<div class=\"row\"/>");
        var fptno = $("<div class=\"col-md-2\"><input type=\"text\" name=\"ptno" + intId + "\" class=\"form-control\" /></>");
        var fdesc = $("<div class=\"col-md-2\"><input type=\"text\" name=\"desc" + intId + "\" class=\"form-control\" /></>");
        ...

No global iterator, just utilizing classes you're already using.

Upvotes: 0

Related Questions