2010-04-16 105 views
16

我正在尋找克隆/重命名或重新創建地址字段以提供在同一頁上提交多個地址的功能的有效方法。因此,與形式例子是這樣的:使用jQuery克隆和重命名錶單元素

<div id="addresses"> 
    <div class="address"> 
    <input type="text" name="address[0].street"> 
    <input type="text" name="address[0].city"> 
    <input type="text" name="address[0].zip"> 
    <input type="text" name="address[0].state"> 
    </div> 
</div> 
<a href="" id="add_address">Add address form</a> 

據我瞭解有兩個選擇這樣做:

  1. 重新創建域的表單字段,增加這是一種詳細的指標:

    var index = $(".address").length; 
    
    $('<`input`>').attr({ 
    name: 'address[' + index + '].street', 
    type: 'text' 
    }).appendTo(...); 
    
    $('<`input`>').attr({ 
    name: 'address[' + index + '].city', 
    type: 'text' 
    }).appendTo(...); 
    
    $('<`input`>').attr({ 
    name: 'address[' + index + '].zip', 
    type: 'text' 
    }).appendTo(...); 
    
    $('<`input`>').attr({ 
    name: 'address[' + index + '].state', 
    type: 'text' 
    }).appendTo(...); 
    
  2. 克隆現有層,並在克隆替換名稱:

    $("div.address").clone().appendTo($("#addresses")); 
    

您推薦使用哪一種方法來提高效率?如果它的#2可以請您建議我如何去搜索並用[1]([n])替換所有[0] )。謝謝。

回答

29

從理論上說,最簡單的方法是將克隆,然後更改名稱:

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

但是:

一個。 jQuery的clone()是一件非常討厭的工作。在IE中,它將節點串行化爲HTML,使用正則表達式(!)處理HTML字符串以刪除其緩存作業內部ID屬性,然後要求瀏覽器重新解析它。這是我最不喜歡的jQuery部分之一:它非常容易出錯,會丟失一些信息,並且速度很慢(對於你在這裏做的很小的工作,速度並不重要)。

瀏覽器的原生cloneNode(true)方法好得多,但如果你在做jQuery的東西,你不能真正使用它,因爲它會複製jQuery的內部標識符,可能會混淆它的腳本。啊。真是一團糟。

b。當您更改輸入的名稱時,無論是按input.name這裏的還是按照您的示例使用attr(),IE < = 7中都有問題。

尤其是,雖然它會提交具有正確控件名稱的輸入,但它們將不會在form.elementsHTMLCollection(或form本身,儘管您不應該使用它)下使用正確名稱進行索引。如果您基於ID或jQuery選擇器而不是舊式HTMLCollection接口選擇輸入,則這不一定是問題。更糟糕的是,單選按鈕,如果你使用任何,將不會正確的名稱分組。

如果這是您的擔憂,我恐怕使用innerHTML/html()來創建div,因爲在pst的回答中,這是您唯一的選擇。 (您可以隨時結合使用HTML,然後使用text()attr(),val()等等來更改其他屬性和文本內容,以避免在將文本字符串粘貼到HTML中時避免常見的HTML轉義問題。)

+0

這是完美的!感謝你對克隆內部工作的解釋,以及在IE中改變輸入名稱的問題。 – Micor 2010-04-16 01:02:31

4

如果你把它寫得很清楚,它就不那麼冗長了:-)我可能只是使用clone和append。 但是,你會得到重複的名字。如果您的後端可以正確處理「address []。street」,這並不是什麼大問題,但它可能不會,在這種情況下,您需要在克隆後進行清理。因此,我建議「把它藏在一個整潔的建造者功能中」。

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

其中replace是一些理解簡單插值映射的整齊函數。我更喜歡「使標記看起來像標記」。

擔心這裏的表現可能不合理。

+0

這當然是一個更理智的方法:)我傾向於克隆方法的原因,因爲狀態實際上是一個填充狀態列表的選擇字段,因此克隆似乎更容易。我可以在這裏以類似的方式使用它,獲取克隆的div的html(),然後用regex替換索引嗎? – Micor 2010-04-16 00:44:41

0

我相信我正在經歷同樣的事情,發現是這樣的一些偉大的來源:

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

和HTML代碼是:

<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" /> 

....