Ottenere campi di input modulo utilizzando jQuery?


412

Ho un modulo con molti campi di input.

Quando rilevo l'evento di invio modulo con jQuery, è possibile ottenere tutti i campi di input di quel modulo in un array associativo?


23
È una buona domanda; in effetti, trovo davvero strano che jQuery non abbia una funzione che fa esattamente questo. Ci sono funzioni per ottenere i dati del modulo in due diversi formati, ma non quello più conveniente per lo scripting ... (Forse .val () dovrebbe restituire un tale array se chiamato su un elemento del modulo?)
Luke Maurer

Risposte:


524
$('#myForm').submit(function() {
    // get all the inputs into an array.
    var $inputs = $('#myForm :input');

    // not sure if you wanted this, but I thought I'd add it.
    // get an associative array of just the values.
    var values = {};
    $inputs.each(function() {
        values[this.name] = $(this).val();
    });

});

Grazie al suggerimento di Simon_Weaver, ecco un altro modo per farlo, usando serializeArray:

var values = {};
$.each($('#myForm').serializeArray(), function(i, field) {
    values[field.name] = field.value;
});

Nota che questo frammento fallirà sugli <select multiple>elementi.

Sembra che i nuovi input del modulo HTML 5 non funzionino con serializeArrayjQuery versione 1.3. Funziona con la versione 1.4+


1
Nelle versioni più recenti di jQuery, la risposta di Simon_Weaver è più solida e semplice.
Potente

1
@MightyE & @Simon_Weaver: hai ragione, è un metodo più robusto, ma non fa esattamente quello che l'OP stava cercando. serializeArray restituisce una matrice di oggetti con le proprietà namee value. Una soluzione migliore potrebbe essere quella di elaborare l'output di serializeArray in qualunque formato sia richiesto.
Nickf

1
Penso che serializeArray () faccia esattamente quello che vuoi, ed è molto meno codice.
slacy

1
Per la prima opzione, che dire degli <select>elementi? Ci ho provato var $inputs = $('#new-ticket :input, :select');ma non funziona. Qualcuno conosce il modo corretto di farlo perché non penso di farlo nel modo giusto.
Nathan,

2
@Nathan, dovresti usare $("#new-ticket :input, #new-ticket :select"), o meglio,$(":input, :select", "#new-ticket")
nickf

252

In ritardo alla festa su questa domanda, ma questo è ancora più semplice:

$('#myForm').submit(function() {
    // Get all the forms elements and their values in one step
    var values = $(this).serialize();

});

8
Questa è davvero la risposta migliore. Mantiene anche qualsiasi formattazione dell'array che potresti avere per i tuoi campi di input. Non penso che la risposta di Nickf manterrebbe effettivamente intatte le tue strutture di dati se fosse formata usando Zend_Form per esempio, dove avresti campo [qualcosa] e campo [qualcosa_else] come nomi degli input ... almeno semanticamente, non riesco a vedere come sarebbe ...
msgme

43
Secondo i documenti dell'API jQuery, .serialize()( api.jquery.com/serialize ) inserisce tutti gli elementi del modulo in una singola stringa pronta per l'aggiunta a un URL in una stringa di query, essenzialmente imitando una richiesta di modulo GET. Ciò non compirebbe ciò che la risposta di Nickf realizza.
Christopher Parker

Questa è la risposta migliore!
Daniel Hunter,

5
Vale la pena sapere: .serialize()funziona anche solo su elementi di forma. Quindi $('form select').serialize()serializzerà i dati solo per le selezioni.
antitossico

3
Invece di ripetere $('#myForm'), usa $ (questo).
Jimothy,

23

Il plugin jquery.form può aiutare con ciò che gli altri stanno cercando che finiscono con questa domanda. Non sono sicuro se fa direttamente quello che vuoi o no.

C'è anche la funzione serializeArray .


15

A volte trovo che ottenerne uno alla volta sia più utile. Per questo, c'è questo:

var input_name = "firstname";
var input = $("#form_id :input[name='"+input_name+"']"); 

In aggiunta [0].valuea questo, cioè, $(...)[0].value;mi ha dato direttamente il valore dell'input, grazie!
Pau Coma Ramirez,

12
$('#myForm').bind('submit', function () {
  var elements = this.elements;
});

La variabile degli elementi conterrà tutti gli input, le selezioni, le textareas e i set di campi all'interno del modulo.


9

Ecco un'altra soluzione, in questo modo è possibile recuperare tutti i dati sul modulo e utilizzarlo in una chiamata sul server o qualcosa del genere.

$('.form').on('submit', function( e )){ 
   var form = $( this ), // this will resolve to the form submitted
       action = form.attr( 'action' ),
         type = form.attr( 'method' ),
         data = {};

     // Make sure you use the 'name' field on the inputs you want to grab. 
   form.find( '[name]' ).each( function( i , v ){
      var input = $( this ), // resolves to current input element.
          name = input.attr( 'name' ),
          value = input.val();
      data[name] = value;
   });

  // Code which makes use of 'data'.

 e.preventDefault();
}

È quindi possibile utilizzare questo con le chiamate Ajax:

function sendRequest(action, type, data) {
       $.ajax({
            url: action,
           type: type,
           data: data
       })
       .done(function( returnedHtml ) {
           $( "#responseDiv" ).append( returnedHtml );
       })
       .fail(function() {
           $( "#responseDiv" ).append( "This failed" );
       });
}

Spero che questo sia di qualche utilità per qualcuno di voi :)


5

Ho avuto un problema simile con una leggera svolta e ho pensato di buttarlo fuori. Ho una funzione di callback che ottiene il modulo, quindi avevo già un oggetto modulo e non potevo scegliere le varianti $('form:input'). Invece ho trovato:

    var dataValues = {};
    form.find('input').each(
        function(unusedIndex, child) {
            dataValues[child.name] = child.value;
        });

È una situazione simile ma non identica, ma ho trovato questa discussione molto utile e ho pensato di riporla alla fine e spero che qualcun altro l'abbia trovata utile.


4

Associativo? Non senza alcun lavoro, ma puoi utilizzare selettori generici:

var items = new Array();

$('#form_id:input').each(function (el) {
    items[el.name] = el;
});

in realtà, la risposta di Lance mantiene intatta la matrice associativa per i valori POST e accetta un'enorme riga di codice.
msumme

perché gli articoli sono un array? lo stai usando come un semplice oggetto. Non è necessario l'array qui
Jonathan Morales Vélez,

3
@ Oli JonathanMoralesVélez 2008 non è più disponibile per un commento. Il 2015 è d'accordo con te.
Oli,

4

jQuery serializeArraynon include campi disabilitati, quindi se hai bisogno anche di quelli, prova:

var data = {};
$('form.my-form').find('input, textarea, select').each(function(i, field) {
    data[field.name] = field.value;
});


4

Non dimenticare le caselle di controllo e i pulsanti di opzione -

var inputs = $("#myForm :input");
var obj = $.map(inputs, function(n, i) {
  var o = {};
  if (n.type == "radio" || n.type == "checkbox")
    o[n.id] = $(n).attr("checked");
  else
    o[n.id] = $(n).val();
  return o;
});
return obj

3

Questo pezzo di codice funzionerà invece del nome, e-mail inserisci il nome dei campi del modulo

$(document).ready(function(){
  $("#form_id").submit(function(event){
    event.preventDefault();
    var name = $("input[name='name']",this).val();
    var email = $("input[name='email']",this).val();
  });
});

3

Sembra strano che nessuno abbia votato o proposto una soluzione concisa per ottenere i dati dell'elenco. Quasi nessuna forma sarà un oggetto a dimensione singola.

Il rovescio della medaglia di questa soluzione è, ovviamente, che sarà necessario accedere ai tuoi oggetti singleton nell'indice [0]. Ma IMO è molto meglio che usare una delle soluzioni di mappatura a dozzina di linee.

var formData = $('#formId').serializeArray().reduce(function (obj, item) {
    if (obj[item.name] == null) {
        obj[item.name] = [];
    } 
    obj[item.name].push(item.value);
    return obj;
}, {});

2

Ho avuto lo stesso problema e l'ho risolto in modo diverso.

var arr = new Array();
$(':input').each(function() {
 arr.push($(this).val());
});
arr;

Restituisce il valore di tutti i campi di input. È possibile modificare il $(':input')per essere più specifico.


2

Stessa soluzione fornita da nickf , ma con i nomi di input dell'array presi in considerazione, ad es

<input type="text" name="array[]" />

values = {};
$("#something :input").each(function() {
  if (this.name.search(/\[\]/) > 0) //search for [] in name
  {
    if (typeof values[this.name] != "undefined") {
      values[this.name] = values[this.name].concat([$(this).val()])
    } else {
      values[this.name] = [$(this).val()];
    }
  } else {
    values[this.name] = $(this).val();
  }
});

1

Se è necessario ottenere più valori dagli input e si utilizzano [] per definire gli input con più valori, è possibile utilizzare quanto segue:

$('#contentform').find('input, textarea, select').each(function(x, field) {
    if (field.name) {
        if (field.name.indexOf('[]')>0) {
            if (!$.isArray(data[field.name])) {
               data[field.name]=new Array();
            }
            data[field.name].push(field.value);
        } else {
            data[field.name]=field.value;
        }
    }                   
});

1

Ispirata dalle risposte di Lance Rushing e Simon_Weaver , questa è la mia soluzione preferita.

$('#myForm').submit( function( event ) {
    var values = $(this).serializeArray();
    // In my case, I need to fetch these data before custom actions
    event.preventDefault();
});

L'output è una matrice di oggetti, ad es

[{name: "start-time", value: "11:01"}, {name: "end-time", value: "11:11"}]

Con il codice qui sotto,

var inputs = {};
$.each(values, function(k, v){
    inputs[v.name]= v.value;
});

il suo risultato finale sarebbe

{"start-time":"11:01", "end-time":"11:01"}

1

Sto usando questo codice senza ogni ciclo:

$('.subscribe-form').submit(function(e){
    var arr=$(this).serializeArray();
    var values={};
    for(i in arr){values[arr[i]['name']]=arr[i]['value']}
    console.log(values);
    return false;
});

1

Spero che sia utile, oltre che più semplice.

 $("#form").submit(function (e) { 
    e.preventDefault();
    input_values =  $(this).serializeArray();
  });

Stranamente questo non ha funzionato con l'ultima versione di jquery 3.4.1
ricominciare il

0

Quando avevo bisogno di fare una chiamata Ajax con tutti i campi del modulo, ho avuto problemi con il selettore di input che restituiva tutte le caselle di controllo, indipendentemente dal fatto che fossero selezionate. Ho aggiunto un nuovo selettore per ottenere solo gli elementi del modulo che possono essere inviati:

$.extend($.expr[':'],{
    submitable: function(a){
        if($(a).is(':checkbox:not(:checked)'))
        {
            return false;
        }
        else if($(a).is(':input'))
        {
            return true;
        }
        else
        {
            return false;
        }
    }
});

utilizzo:

$('#form_id :submitable');

Non l'ho ancora testato con più caselle di selezione, ma funziona per ottenere tutti i campi del modulo come farebbe un invio standard.

L'ho usato durante la personalizzazione delle opzioni del prodotto su un sito OpenCart per includere caselle di controllo e campi di testo, nonché il tipo di casella di selezione standard.


0

serialize () è il metodo migliore. @ Christopher Parker afferma che la risposta di Nickf offre di più, tuttavia non tiene conto del fatto che il modulo può contenere textarea e selezionare menu. È molto meglio usare serialize () e quindi manipolarlo come è necessario. I dati di serialize () possono essere utilizzati in un post Ajax o get, quindi non vi è alcun problema.


0

Spero che questo aiuti qualcuno. :)

// This html:
// <form id="someCoolForm">
// <input type="text" class="form-control" name="username" value="...." />
// 
// <input type="text" class="form-control" name="profile.first_name" value="...." />
// <input type="text" class="form-control" name="profile.last_name" value="...." />
// 
// <input type="text" class="form-control" name="emails[]" value="..." />
// <input type="text" class="form-control" name="emails[]" value=".." />
// <input type="text" class="form-control" name="emails[]" value="." />
// </form>
// 
// With this js:
// 
// var form1 = parseForm($('#someCoolForm'));
// console.log(form1);
// 
// Will output something like:
// {
// username: "test2"
// emails:
//   0: ".@....com"
//   1: "...@........com"
// profile: Object
//   first_name: "..."
//   last_name: "..."
// }
// 
// So, function below:

var parseForm = function (form) {

    var formdata = form.serializeArray();

    var data = {};

    _.each(formdata, function (element) {

        var value = _.values(element);

        // Parsing field arrays.
        if (value[0].indexOf('[]') > 0) {
            var key = value[0].replace('[]', '');

            if (!data[key])
                data[key] = [];

            data[value[0].replace('[]', '')].push(value[1]);
        } else

        // Parsing nested objects.
        if (value[0].indexOf('.') > 0) {

            var parent = value[0].substring(0, value[0].indexOf("."));
            var child = value[0].substring(value[0].lastIndexOf(".") + 1);

            if (!data[parent])
                data[parent] = {};

            data[parent][child] = value[1];
        } else {
            data[value[0]] = value[1];
        }
    });

    return data;
};

0

Tutte le risposte sono buone, ma se c'è un campo che ti piace ignorare in quella funzione? Facile, dai al campo una proprietà, ad esempio ignore_this:

<input type="text" name="some_name" ignore_this>

E nella tua funzione Serialize:

if(!$(name).prop('ignorar')){
   do_your_thing;
}

Questo è il modo in cui ignori alcuni campi.


1
Questo è più un commento che una risposta poiché non risponde alla domanda originale.
Wai Ha Lee,

Forse perché ha già tonnellate di risposte? È un complemento delle risposte che ha ricevuto.
Marcelo Rocha,

Lo implementerei con un nome di classe come obbligatorio se l'input deve essere compilato. Quindi posso controllare $('.mandatory');e!$('.mandatory');
lharby,

Cambio ignore_thisal data-ignore-this="true"posto di creare i propri attributi che non lo fanno w3c validate
zanderwar

0

Prova il seguente codice:

jQuery("#form").serializeArray().filter(obje => 
obje.value!='').map(aobj=>aobj.name+"="+aobj.value).join("&")

2
Spiega la tua risposta
Ling Vu,

0

Per più elementi di selezione (<select multiple="multiple"> ), ho modificato la soluzione da @Jason Norwood-Young per farlo funzionare.

La risposta (come pubblicata) prende solo il valore dal primo elemento che è stato selezionato, non tutti . Inoltre non è stato inizializzato o restituitodata , il primo ha generato un errore JavaScript.

Ecco la nuova versione:

function _get_values(form) {
  let data = {};
  $(form).find('input, textarea, select').each(function(x, field) {
    if (field.name) {
      if (field.name.indexOf('[]') > 0) {
        if (!$.isArray(data[field.name])) {
          data[field.name] = new Array();
        }
        for (let i = 0; i < field.selectedOptions.length; i++) {
          data[field.name].push(field.selectedOptions[i].value);
        }

      } else {
        data[field.name] = field.value;
      }
    }

  });
  return data
}

Uso:

_get_values($('#form'))

Nota: devi solo assicurarti che la nametua selezione sia stata []aggiunta alla fine, ad esempio:

<select name="favorite_colors[]" multiple="multiple">
  <option value="red">Red</option>
  <option value="green">Green</option>
  <option value="blue">Blue</option>
</select>

-1
$("#form-id").submit(function (e) { 
  e.preventDefault();
  inputs={};
  input_serialized =  $(this).serializeArray();
  input_serialized.forEach(field => {
    inputs[field.name] = field.value;
  })
  console.log(inputs)
});
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.