2012-06-20 19 views
7

Ho una forma sul mio sito come questo:jquery ingresso serializzare con array

<form id="myform" action="" method=""> 
<input type="text" name="name[1][first]"> 
<input type="text" name="name[2][first]"> 
<input type="text" name="name[3][first]"> 
</form> 

voglio afferrare semplicemente tutti i dati e inviarlo a un webservice in modo da avere questa js:

$fields = $('#myform').serializeArray(); 

Il problema è che crea il json con tutte le parentesi mostrate nei nomi di input in modo da ottenere un errore di analisi.

Come posso utilizzare serializeArray e ottenere json corretto?

Il formato risultante che mi piacerebbe vedere è qualcosa di simile:

{ 
    "name": { 
    "1": { 
     "first": "val1" 
    }, 
    "2": { 
     "first": "val2" 
    }, 
    "3": { 
     "first": "val3" 
    } 
    } 
} 

Grazie!

+8

10 domande, 0% risposte accettate. – pete

+1

Dovrai cambiare i nomi dei tuoi ingressi. Il serializzatore JSON non inventa nomi propri per loro. –

risposta

0

Dato che si è serializzato successo il sistema a $fields, ora è possibile camminare attraverso di essa e convertirlo in un oggetto risultato più facilmente digeribile:

var result = {}; 
for(var i in $fields) { 
    var parts = $fields[i].name.split("["); 
    var resultIndex = parseInt(parts[1].replace(']', ''), 10); 
    result[resultIndex] = $fields[i].value; 
} 

Mentre $fields è un nome valido per una variabile globale, Non posso mettere a nudo per tacere su questo argomento: in JavaScript, le variabili locali sono definite con la parola chiave var e non hanno il simbolo del dollaro prima di loro - il simbolo del dollaro di solito si riferisce all'oggetto jQuery. Di conseguenza è possibile recuperare i campi invocando:

var fields = $('#myform').serializeArray(); 
+0

Il nome della variabile non fa alcuna differenza e, indipendentemente dal fatto che sia globale o meno, non è correlato alla domanda. –

+0

Questo è stato solo un errore di battitura da parte mia quando ho digitato la domanda. È il PHP in me che esce. – user989557

+0

Come posso far funzionare questo quando il modulo ha anche altri input? Quando aggiungo input come: Ricevo un errore js che le parti [1] non sono definite. Presumo questo perché sta cercando di analizzare gli elementi senza parentesi. – user989557

9

Ho fatto una ricorsiva funzione/plugin per fare esattamente questo:

$.fn.serializeControls = function() { 
 
    var data = {}; 
 

 
    function buildInputObject(arr, val) { 
 
    if (arr.length < 1) 
 
     return val; 
 
    var objkey = arr[0]; 
 
    if (objkey.slice(-1) == "]") { 
 
     objkey = objkey.slice(0,-1); 
 
    } 
 
    var result = {}; 
 
    if (arr.length == 1){ 
 
     result[objkey] = val; 
 
    } else { 
 
     arr.shift(); 
 
     var nestedVal = buildInputObject(arr,val); 
 
     result[objkey] = nestedVal; 
 
    } 
 
    return result; 
 
    } 
 

 
    $.each(this.serializeArray(), function() { 
 
    var val = this.value; 
 
    var c = this.name.split("["); 
 
    var a = buildInputObject(c, val); 
 
    $.extend(true, data, a); 
 
    }); 
 
    
 
    return data; 
 
} 
 

 
$("#output").html(JSON.stringify($('#myform').serializeControls(), null, 2));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> 
 

 
<form id="myform" action="" method=""> 
 
<input type="text" name="name[1][first]" value="beep"> 
 
<input type="text" name="name[1][second]" value="bloop"> 
 
<input type="text" name="name[2][first]" value="derp"> 
 
    
 
<input type="text" name="foo" value="bar"> 
 
</form> 
 

 
<pre id="output"> 
 
</pre>

Si può anche chiamare su altri selettori oltre all'intero form. Ad esempio, la chiamata:

$('input[name^="name\\["]').serializeControls()

restituirà un oggetto che contiene solo i campi name. Vedi http://codepen.io/alexweissman/pen/MyWZdN per ulteriori esempi.

Si noti che (per ora), questo non funzionerà per i nomi dei campi con parentesi vuote (ad esempio, campi come input name="potatoes[]" verranno ignorati perché non è possibile estrarre una chiave univoca).

+1

Questo è un asso.Ho provato il plugin jquery-serialize-object, che non ha funzionato, ma questo è vero. Bello. –

+0

Ciao, il tuo codice sembra non serializzare correttamente '': 'var val = this.value;' restituisce solo il primo valore selezionato (testato su firefox). Poiché si tratta di un hack per jquery, penso che questo possa essere risolto facilmente con '$ (this) .val()'. – Asenar

0

Ecco una versione del codice alexw che funziona per i nomi dei campi con parentesi vuote. Ciò consente di gestire i campi con più valori (caselle di controllo, selezionare più).

$j.fn.serializeObject = function() { 
    var data = {}; 

    function buildInputObject(arr, val) { 
     if (arr.length < 1) { 
      return val; 
     } 
     var objkey = arr[0]; 
     if (objkey.slice(-1) == "]") { 
      objkey = objkey.slice(0,-1); 
     } 
     var result = {}; 
     if (arr.length == 1){ 
      result[objkey] = val; 
     } else { 
      arr.shift(); 
      var nestedVal = buildInputObject(arr,val); 
      result[objkey] = nestedVal; 
     } 
     return result; 
    } 

    function gatherMultipleValues(that) { 
     var final_array = []; 
     $j.each(that.serializeArray(), function(key, field) { 
      // Copy normal fields to final array without changes 
      if(field.name.indexOf('[]') < 0){ 
       final_array.push(field); 
       return true; // That's it, jump to next iteration 
      } 

      // Remove "[]" from the field name 
      var field_name = field.name.split('[]')[0]; 

      // Add the field value in its array of values 
      var has_value = false; 
      $j.each(final_array, function(final_key, final_field){ 
       if(final_field.name === field_name) { 
        has_value = true; 
        final_array[ final_key ][ 'value' ].push(field.value); 
       } 
      }); 
      // If it doesn't exist yet, create the field's array of values 
      if(! has_value) { 
       final_array.push({ 'name': field_name, 'value': [ field.value ] }); 
      } 
     }); 
     return final_array; 
    } 

    // Manage fields allowing multiple values first (they contain "[]" in their name) 
    var final_array = gatherMultipleValues(this); 

    // Then, create the object 
    $j.each(final_array, function() { 
     var val = this.value; 
     var c = this.name.split('['); 
     var a = buildInputObject(c, val); 
     $j.extend(true, data, a); 
    }); 

    return data; 
};