Obter campos de entrada de formulário usando jQuery?

412

Eu tenho um formulário com muitos campos de entrada.

Quando eu pego o evento de envio de formulário com o jQuery, é possível obter todos os campos de entrada desse formulário em uma matriz associativa?

Vasil
fonte
23
É uma boa pergunta; de fato, acho realmente estranho que o jQuery não tenha uma função que faça exatamente isso. Existem funções para obter os dados do formulário em dois formatos diferentes, mas não o mais conveniente para, você sabe, scripts ... (Talvez .val () devesse retornar esse array se chamado em um elemento de formulário?)
Luke Maurer

Respostas:

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

});

Graças à dica de Simon_Weaver, aqui está outra maneira de fazer isso, usando serializeArray:

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

Observe que este trecho falhará nos <select multiple>elementos.

Parece que as novas entradas de formulário HTML 5 não funcionam serializeArrayno jQuery versão 1.3. Isso funciona na versão 1.4 ou superior

nickf
fonte
1
Nas versões mais recentes do jQuery, a resposta de Simon_Weaver é mais robusta e fácil.
MightyE
1
@MightyE e @Simon_Weaver - você está certo, é um método mais robusto, mas não faz exatamente o que o OP estava procurando. serializeArray retorna uma matriz de objetos com as propriedades namee value. Uma solução melhor pode ser processar a saída do serializeArray para qualquer formato necessário.
nickf
1
Eu acho que serializeArray () faz exatamente o que você quer e tem muito menos código.
slacy 18/03/11
1
Para a primeira opção, e os <select>elementos? Eu tentei, var $inputs = $('#new-ticket :input, :select');mas isso não funciona. Alguém sabe a maneira correta de fazer isso, porque eu não acho que estou fazendo certo.
27412 Nathan
2
@ Nathan, você deve usar $("#new-ticket :input, #new-ticket :select"), ou até melhor,$(":input, :select", "#new-ticket")
nickf
252

Tarde para a parte sobre esta questão, mas isso é ainda mais fácil:

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

});
Lance Rushing
fonte
8
Esta é realmente a melhor resposta. Ele ainda mantém qualquer formatação de matriz que você possa ter para seus campos de entrada. Eu não acho que a resposta do nickf realmente manteria suas estruturas de dados intactas se elas fossem formadas usando o Zend_Form, por exemplo, onde você teria o campo [algo] e o campo [algo_else] como os nomes das entradas ... pelo menos semanticamente, não consigo ver como ...
msumme 27/01
43
De acordo com os documentos da API do jQuery, .serialize()( api.jquery.com/serialize ) coloca todos os elementos do formulário em uma única sequência pronta para anexar a um URL em uma sequência de consulta, imitando essencialmente uma solicitação de formulário GET. Isso não alcançaria o que a resposta de nickf realiza.
Christopher Parker
Esta é a melhor resposta!
Daniel Hunter
5
Vale a pena conhecer: .serialize()também funciona apenas em elementos de formulário. Então $('form select').serialize(), serializará os dados apenas para selects.
Antitóxico
3
Em vez de repetir $('#myForm'), use $ (this).
Jimothy
23

O plugin jquery.form pode ajudar com o que os outros estão procurando e acabam nessa questão. Não tenho certeza se ele faz diretamente o que você quer ou não.

Há também a função serializeArray .

Simon_Weaver
fonte
15

Às vezes, acho que conseguir um de cada vez é mais útil. Para isso, existe o seguinte:

var input_name = "firstname";
var input = $("#form_id :input[name='"+input_name+"']"); 
Malaquias
fonte
Anexar [0].valuea isto, ou seja, $(...)[0].value;me deu o valor da entrada diretamente, obrigado!
Pau Coma Ramirez
12
$('#myForm').bind('submit', function () {
  var elements = this.elements;
});

A variável elementos conterá todas as entradas, seleções, áreas de texto e conjuntos de campos no formulário.

Quentin
fonte
9

Aqui está outra solução, desta forma, você pode buscar todos os dados sobre o formulário e usá-los em uma chamada do servidor ou algo assim.

$('.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();
}

Você pode usar isso com chamadas 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" );
       });
}

Espero que seja útil para qualquer um de vocês :)

Ole Aldric
fonte
5

Teve um problema semelhante com uma ligeira torção e pensei em jogar isso fora. Eu tenho uma função de retorno de chamada que obtém o formulário, então eu já tinha um objeto de formulário e não podia facilitar as variantes $('form:input'). Em vez disso, eu vim com:

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

É uma situação semelhante, mas não idêntica, mas achei esse tópico muito útil e pensei em colocar isso no final e espero que alguém o ache útil.

Chris
fonte
4

Associativo? Não sem algum trabalho, mas você pode usar seletores genéricos:

var items = new Array();

$('#form_id:input').each(function (el) {
    items[el.name] = el;
});
Oli
fonte
na verdade, a resposta de Lance mantém intacta a matriz associativa para os valores de POST e utiliza uma linha de código enorme.
msumme
por que os itens são uma matriz? você está usando como um objeto simples. Não há necessidade de matriz aqui
Jonathan Morales Vélez
3
@ JonathanMoralesVélez 2008 Oli não está mais aqui para comentar. 2015 concorda com você.
213 Oli
4

O jQuery serializeArraynão inclui campos desativados; portanto, se você também precisar deles, tente:

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

Não esqueça as caixas de seleção e os botões de opção -

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
Homem chamado Haney
fonte
3

Este trecho de código funcionará em vez de nome; e-mail, digite o nome dos campos do formulário

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

Parece estranho que ninguém tenha votado ou proposto uma solução concisa para obter dados da lista. Dificilmente quaisquer formulários serão objetos de dimensão única.

A desvantagem desta solução é que seus objetos singleton precisarão ser acessados ​​no índice [0]. Mas a IMO é muito melhor do que usar uma das soluções de mapeamento de doze linhas.

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

Eu tive o mesmo problema e o resolvi de uma maneira diferente.

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

Retorna o valor de todos os campos de entrada. Você pode mudar $(':input')para ser mais específico.

suizo
fonte
2

A mesma solução dada pelo nickf , mas com os nomes de entrada da matriz levados em consideração, por exemplo

<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();
  }
});
Itako
fonte
1

Se você precisar obter vários valores de entradas e estiver usando [] para definir as entradas com vários valores, poderá usar o seguinte:

$('#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;
        }
    }                   
});
Jason Norwood-Young
fonte
1

Inspirada nas respostas de Lance Rushing e Simon_Weaver , esta é a minha solução favorita.

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

A saída é uma matriz de objetos, por exemplo

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

Com o código abaixo,

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

sua produção final seria

{"start-time":"11:01", "end-time":"11:01"}
T.Liu
fonte
1

Eu estou usando esse código sem cada loop:

$('.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;
});
Roman Grinev
fonte
1

Espero que isso seja útil, assim como o mais fácil.

 $("#form").submit(function (e) { 
    e.preventDefault();
    input_values =  $(this).serializeArray();
  });
dipenparmar12
fonte
Estranhamente, isso não funcionou na versão mais recente do jquery 3.4.1
relipse
0

Quando precisei fazer uma chamada ajax com todos os campos do formulário, tive problemas com o seletor : input retornando todas as caixas de seleção, independentemente de terem sido marcadas ou não. Adicionei um novo seletor para obter apenas os elementos do formulário que podem ser submetidos:

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

uso:

$('#form_id :submitable');

Ainda não testei com várias caixas de seleção, mas funciona para obter todos os campos do formulário da maneira que um envio padrão faria.

Usei isso ao personalizar as opções do produto em um site OpenCart para incluir caixas de seleção e campos de texto, além do tipo de caixa de seleção padrão.

slarti42uk
fonte
0

serialize () é o melhor método. @ Christopher Parker diz que a resposta de Nickf realiza mais, no entanto, não leva em conta que o formulário pode conter área de texto e selecionar menus. É muito melhor usar serialize () e manipular isso conforme necessário. Os dados de serialize () podem ser usados ​​em uma postagem do Ajax ou em get, portanto, não há problema nisso.

Billy
fonte
0

Espero que isso ajude alguém. :)

// 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: "[email protected]"
//   1: "[email protected]"
// 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;
};
Julian
fonte
0

Todas as respostas são boas, mas se houver um campo que você gostaria de ignorar nessa função? Fácil, atribua uma propriedade ao campo, por exemplo ignore_this:

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

E na sua função Serialize:

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

É assim que você ignora alguns campos.

Marcelo Rocha
fonte
1
Isso é mais um comentário do que uma resposta, pois não responde à pergunta original.
Wai Ha Lee
Talvez porque ele já tenha toneladas de respostas? É um complemento para as respostas que ele recebeu.
Marcelo Rocha
Gostaria de implementar isso com um nome de classe como obrigatória se a entrada deve ser preenchido, então eu posso verificar. $('.mandatory');E!$('.mandatory');
lharby
Alterar ignore_thisa data-ignore-this="true"vez de criar seus próprios atributos que não fazer W3C validar
zanderwar
0

Tente o seguinte código:

jQuery("#form").serializeArray().filter(obje => 
obje.value!='').map(aobj=>aobj.name+"="+aobj.value).join("&")
Teodor Rautu
fonte
2
Por favor, explique sua resposta
Ling Vu
0

Para vários elementos selecionados ( <select multiple="multiple">), modifiquei a solução de @Jason Norwood-Young para fazê-la funcionar.

A resposta (conforme publicada) assume apenas o valor do primeiro elemento que foi selecionado, nem todos . Também não inicializou ou retornou data, o primeiro gerando um erro de JavaScript.

Aqui está a nova versão:

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: Você só precisa garantir que o nameseu select foi []anexado ao final dele, por exemplo:

<select name="favorite_colors[]" multiple="multiple">
  <option value="red">Red</option>
  <option value="green">Green</option>
  <option value="blue">Blue</option>
</select>
tzazo
fonte
-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)
});
Raushan
fonte