2010-04-16 17 views
16

Sto cercando un modo efficace per clonare/rinominare o ricreare i campi degli indirizzi per offrire la possibilità di inviare più indirizzi sulla stessa pagina. Così, con l'esempio forma in questo modo:Clonazione e ridenominazione degli elementi del modulo con 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> 

Da quello che posso capire ci sono due opzioni per farlo:

  1. ricreare il campo del modulo da campo e incrementare l'indice che è una specie di verbose:

    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. clone livello esistente e sostituire il nome nel clone: ​​

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

Quale mi consigliate utilizzare in termini di essere più efficienti e se # 2 può si prega di suggerire come andrei sulla ricerca e la sostituzione di tutte le occorrenze di [0] con [1] ([n]). Grazie.

risposta

29

In teoria, il modo più semplice sarebbe quella di clonare poi cambiare il nome:

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

Tuttavia:

a. jQuery's clone() è un lavoro davvero antipatico. Su IE, serializza i nodi in HTML, elabora la stringa HTML con regex (!) Per rimuovere gli attributi ID interni del bodge-job e quindi chiede al browser di ri-analizzarlo. Questa è una delle mie parti preferite di jQuery: è altamente soggetta a errori, perde alcune informazioni ed è lenta (non che la velocità sia importante per il lavoro piuttosto piccolo che sembra fare qui).

Il metodo nativo del browser cloneNode(true) è molto meglio, ma non si può realmente usarlo se si sta facendo jQuery perché copierà gli ID interni di jQuery, potenzialmente confondendo il suo scripting. Ugh. Che casino.

b. Quando modifichi il nome di un input, che sia input.name come qui o utilizzando attr() come nell'esempio, ci sono problemi in IE < = 7.

In particolare, sebbene invierà gli input con il nome di controllo corretto, essi non verranno indicizzati con il nome corretto in form.elements HTMLCollection (o su form stesso, sebbene non si debba comunque utilizzarlo). Questo non è necessariamente un problema se si selezionano input basati su ID o selettori jQuery piuttosto che sull'interfaccia HTMLCollection vecchia scuola. Peggio ancora, i pulsanti radio, se ne usate, non saranno correttamente raggruppati per nome.

Se questa è una preoccupazione per te, ho paura di usare innerHTML/html() per creare il div, come nella risposta di pst, è la tua unica opzione. (È sempre possibile combinare le due cose, la creazione utilizzando HTML quindi modificando gli altri attributi e contenuti di testo utilizzando text(), attr(), val() ecc per evitare i soliti problemi HTML-fuggire quando si va in giro attaccando stringhe di testo in HTML.)

+0

Questo è perfetto! grazie per la spiegazione del funzionamento interno del clone e un promemoria sui problemi con il cambio del nome di input in IE. – Micor

4

È molto meno prolisso se lo scrivi in ​​modo sano :-) Probabilmente userò solo clone e append. Tuttavia,, otterrai nomi duplicati. Questo non è un grosso problema se il tuo back-end può gestire correttamente "address []. Street", ma potrebbe non farlo e in tal caso avresti bisogno di ripulire dopo il clone. Quindi consiglierei di "nasconderlo in una ordinata funzione builder".

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

Dove sostituire è una funzione ordinata che comprende una semplice mappatura di interpolazione. Preferisco "mantenere il markup in qualcosa che assomiglia al markup".

Preoccuparsi di prestazioni qui non è probabilmente giustificato.

+0

Questo è sicuramente un modo più sano di farlo :) La ragione per cui mi sto appoggiando al metodo clone perché lo stato è in realtà un campo selezionato popolato da un elenco di stati, quindi la clonazione sembra essere più facile. Potrei usarlo qui in un modo simile e ottenere html() del mio div clonato e quindi sostituire l'indice usando regex forse? – Micor

0

I belive sto attraversando la stessa cosa e trovato alcuni grande fonte che va in questo modo:

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

e il codice 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" /> 

....

Problemi correlati