Cloning and renaming form elements with jQuery

后端 未结 3 1424
失恋的感觉
失恋的感觉 2021-02-04 03:51

I am looking for an effective way to either clone/rename or re-create address fields to offer ability to submit multiple addresses on the same page. So with form example like th

相关标签:
3条回答
  • 2021-02-04 04:26

    In theory, the simplest way would be to clone then change name:

    var newaddress= $("#addresses div.address").eq(0).clone();
    newaddress.find('input').each(function() {
        this.name= this.name.replace('[0]', '['+i+']');
    });
    $('#addresses').append(newaddress);
    

    However:

    a. jQuery's clone() is a really nasty piece of work. On IE, it serialises the nodes to HTML, processes the HTML string with regex (!) to remove its bodge-job internal ID attributes and then asks the browser to re-parse it. This is one of my least favourite parts of jQuery: it's highly error-prone, loses some information, and is slow (not that speed matters for the quite small job you seem to be doing here).

    The browser's native cloneNode(true) method is much better, but you can't really use it if you're doing jQuery stuff because it will copy jQuery's internal ids, potentially confusing its scripting. Ugh. What a mess.

    b. When you change an input's name, whether that's by input.name as here or using attr() as in your example, there are issues in IE<=7.

    In particular, though it will submit the inputs with the correct control name, they won't be indexed under the right name in the form.elements HTMLCollection (or on form itself, though you shouldn't use that anyway). This isn't necessarily a problem if you are selecting inputs based on IDs or jQuery selectors rather than the old-school HTMLCollection interface. Worse is that radio buttons, if you use any, won't be properly name-grouped.

    If this is a concern for you I'm afraid using innerHTML/html() to create the div, as in pst's answer, is your only option. (You can always combine the two, creating using HTML then changing the other attributes and text content using text(), attr(), val() etc. to avoid the usual HTML-escaping problems when you go around sticking text strings into HTML.)

    0 讨论(0)
  • 2021-02-04 04:32

    I belive i am going through the same thing and found some great source that goes like this:

    <script type="text/javascript">
        function trimNums(stringToTrim)
        {
            return stringToTrim.replace(/\d+$/,"");
        }
        function dupForm(divId, divClass, btnAdd, btnRm)
        {
        //alert(divId+'   '+divClass);
            var num     = $(divClass).length;
            var newNum  = new Number(num + 1);
            var i;
            var newElem = $('#' + divId + num).clone().attr('id', divId + newNum).fadeIn('slow');
            for (i=0; i < newElem.children().length; i++)
            {
                var attrId = trimNums(newElem.children(':eq('+i+')').attr('id'));
                var attrName = trimNums(newElem.children(':eq('+i+')').attr('name'));
                newElem.children(':eq('+i+')').attr('id', attrId + newNum).val('');
            }
            $('#' + divId + num).after(newElem);
            $('#' + btnRm).attr('disabled','');
            if (newNum == 15)
                $('#' + btnAdd).attr('disabled','disabled');
        }
        function rmForm(divId, divClass, btnAdd, btnRm)
        {
            var num = $(divClass).length;
            $('#' + divId + num).remove();
            $('#' + btnAdd).attr('disabled','');
            if (num-1 == 1)
                $('#' + btnRm).attr('disabled','disabled');
        }
    </script>
    

    and the html code is:

    <form id="myForm" action="testingForm.php" method="post">
    <div id="input1" style="margin-bottom:4px;" class="clonedInput">
        Part #: <input name="part[]" type="text" id="part1" size="10" maxlength="15" />
        Description: <input name="description[]" type="text" id="description1" size="30" maxlength="50" />
        Qty: <input name="quantity[]" type="text" id="quantity1" size="5" maxlength="5" />
    

    ....

    0 讨论(0)
  • 2021-02-04 04:39

    It's much less verbose if you write it sanely :-) I would likely just use clone and append. However, you'll get duplicate names. This isn't a big deal if your back-end can correctly handle "address[].street", but it may not and in such a case you'd need to cleanup after the clone. Thus I'd recommend "hiding it in a tidy builder function".

    function createAddress (index) {
      return jQuery(replace('\
        <div class="address">\
          <input type="text" name="address[{i}].street">\
          <input type="text" name="address[{i}].city">\
          <input type="text" name="address[{i}].zip">\
          <input type="text" name="address[{i}].state">\
        </div>\
        ', {i: index}))
    }
    

    Where replace is some tidy function which understands a simple interpolation mapping. I prefer to "keep markup in something that looks like markup".

    Worrying about performance here is likely not warranted.

    0 讨论(0)
提交回复
热议问题