Obtener campos de entrada de formulario usando jQuery?

412

Tengo un formulario con muchos campos de entrada.

Cuando capturo el evento de envío de formulario con jQuery, ¿es posible obtener todos los campos de entrada de ese formulario en una matriz asociativa?

Vasil
fuente
23
Es una buena pregunta; de hecho, me parece realmente extraño que jQuery no tenga una función que haga precisamente esto. Hay funciones para obtener los datos del formulario en dos formatos diferentes, pero no es el más conveniente para, ya sabes, crear scripts ... (¿Quizás .val () debería devolver una matriz de este tipo si se llama a un elemento del formulario?)
Luke Maurer,

Respuestas:

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

});

Gracias al consejo de Simon_Weaver, aquí hay otra forma de hacerlo, usando serializeArray:

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

Tenga en cuenta que este fragmento fallará en los <select multiple>elementos.

Parece que las nuevas entradas de formulario HTML 5 no funcionan con serializeArrayjQuery versión 1.3. Esto funciona en la versión 1.4+

nickf
fuente
1
En las versiones más recientes de jQuery, la respuesta de Simon_Weaver es más robusta y fácil.
MightyE
1
@MightyE y @Simon_Weaver: tienes razón, es un método más robusto, pero no hace exactamente lo que estaba buscando el OP. serializeArray devuelve una matriz de objetos con las propiedades namey value. Una mejor solución podría ser procesar la salida de serializeArray en el formato requerido.
nickf
1
Creo que serializeArray () hace exactamente lo que quieres, y es mucho menos código.
Slacy
1
Para la primera opción, ¿qué pasa con los <select>elementos? Lo intenté var $inputs = $('#new-ticket :input, :select');pero eso no funciona. ¿Alguien sabe la forma correcta de hacer esto porque no creo que lo esté haciendo bien?
Nathan
2
@Nathan, deberías usar $("#new-ticket :input, #new-ticket :select"), o incluso mejor,$(":input, :select", "#new-ticket")
nickf
252

Tarde a la fiesta en esta pregunta, pero esto es aún más fácil:

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

});
Lance Rushing
fuente
8
Esta es realmente la mejor respuesta. Incluso mantiene cualquier formato de matriz que pueda tener para sus campos de entrada. No creo que la respuesta de nickf realmente mantenga intactas sus estructuras de datos si se formara usando Zend_Form, por ejemplo, donde tendría campo [algo] y campo [algo_else] como los nombres de las entradas ... al menos semánticamente, no puedo ver cómo sería ...
msumme
43
De acuerdo con los documentos de la API jQuery, .serialize()( api.jquery.com/serialize ) coloca todos los elementos del formulario en una sola cadena lista para agregar a una URL en una cadena de consulta, esencialmente imitando una solicitud de formulario GET. Esto no lograría lo que logra la respuesta de nickf.
Christopher Parker
¡Esta es la mejor respuesta!
Daniel Hunter
55
Vale la pena saberlo: .serialize()también funciona solo con elementos de formulario. Por $('form select').serialize()lo tanto , serializará los datos solo para las selecciones.
antitóxico
3
En lugar de repetir $('#myForm'), use $ (this).
Jimothy
23

El complemento jquery.form puede ayudar con lo que otros buscan y que terminan en esta pregunta. No estoy seguro de si hace directamente lo que quieres o no.

También existe la función serializeArray .

Simon_Weaver
fuente
15

A veces encuentro que obtener uno a la vez es más útil. Para eso, hay esto:

var input_name = "firstname";
var input = $("#form_id :input[name='"+input_name+"']"); 
Malaquías
fuente
Anexar [0].valueesto, es decir, $(...)[0].value;me dio el valor de la entrada directamente, ¡gracias!
Pau Coma Ramirez
12
$('#myForm').bind('submit', function () {
  var elements = this.elements;
});

La variable de elementos contendrá todas las entradas, selecciones, áreas de texto y conjuntos de campos dentro del formulario.

Quentin
fuente
9

Aquí hay otra solución, de esta manera puede obtener todos los datos sobre el formulario y usarlo en una llamada del servidor o algo así.

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

Luego puede usar esto con llamadas 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 esto sea de utilidad para cualquiera de ustedes :)

Ole Aldric
fuente
5

Tuve un problema similar con un ligero giro y pensé en tirar esto. Tengo una función de devolución de llamada que obtiene el formulario, por lo que ya tenía un objeto de formulario y no podía tener variantes fáciles $('form:input'). En cambio, se me ocurrió:

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

Es una situación similar pero no idéntica, pero este hilo me pareció muy útil y pensé en meterlo al final y esperar que alguien más lo encontrara útil.

Chris
fuente
4

¿De asociación? No sin un poco de trabajo, pero puede usar selectores genéricos:

var items = new Array();

$('#form_id:input').each(function (el) {
    items[el.name] = el;
});
Oli
fuente
en realidad, la respuesta de Lance mantiene intacta la matriz asociativa para los valores POST, y toma una enorme línea de código.
msumme
¿Por qué los artículos son una matriz? Lo estás utilizando como un objeto simple. No hay necesidad de la matriz aquí
Jonathan Morales Vélez
3
@ JonathanMoralesVélez 2008 Oli ya no está para comentar. 2015 está de acuerdo con usted.
Oli
4

jQuery's serializeArrayno incluye campos deshabilitados, así que si los necesita también, intente:

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

No olvide las casillas de verificación y los botones de opción.

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
El hombre llamado Haney
fuente
3

Este código funcionará en lugar del nombre, ingrese por correo electrónico el nombre de los campos de su formulario

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

Parece extraño que nadie haya votado o propuesto una solución concisa para obtener datos de la lista. Casi ninguna forma será un objeto unidimensional.

La desventaja de esta solución es, por supuesto, que tendrá que acceder a sus objetos singleton en el índice [0]. Pero IMO es mucho mejor que usar una de las soluciones de mapeo de docenas de líneas.

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

Tuve el mismo problema y lo resolví de una manera diferente.

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

Devuelve el valor de todos los campos de entrada. Podrías cambiar el $(':input')para ser más específico.

suizo
fuente
2

La misma solución dada por nickf , pero teniendo en cuenta los nombres de entrada de matriz, por ejemplo

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

Si necesita obtener múltiples valores de las entradas y está usando [] 's para definir las entradas con múltiples valores, puede usar lo siguiente:

$('#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
fuente
1

Inspirado por las respuestas de Lance Rushing y Simon_Weaver , esta es mi solución favorita.

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

La salida es una matriz de objetos, p. Ej.

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

Con el siguiente código,

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

su salida final sería

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

Estoy usando este código sin cada bucle:

$('.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
fuente
1

Espero que esto sea útil, así como el más fácil.

 $("#form").submit(function (e) { 
    e.preventDefault();
    input_values =  $(this).serializeArray();
  });
dipenparmar12
fuente
Curiosamente, esto no funcionó en la última versión de jquery 3.4.1
relipse
0

Cuando necesitaba hacer una llamada ajax con todos los campos del formulario, tuve problemas con el : selector de entrada que devuelve todas las casillas de verificación, estén o no marcadas. Agregué un nuevo selector para obtener los elementos de formulario que se pueden enviar:

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

Sin embargo, aún no lo he probado con varios cuadros de selección, pero funciona para obtener todos los campos de formulario de la forma en que lo haría un envío estándar.

Lo utilicé al personalizar las opciones del producto en un sitio de OpenCart para incluir casillas de verificación y campos de texto, así como el tipo de cuadro de selección estándar.

slarti42uk
fuente
0

serialize () es el mejor método. @ Christopher Parker dice que la respuesta de Nickf logra más, sin embargo, no tiene en cuenta que el formulario puede contener área de texto y menús seleccionados. Es mucho mejor usar serialize () y luego manipular eso como sea necesario. Los datos de serialize () se pueden usar en una publicación de Ajax o get, por lo que no hay ningún problema allí.

Porra
fuente
0

Espero que esto ayude a alguien. :)

// 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
fuente
0

Todas las respuestas son buenas, pero si hay un campo que le gustaría ignorar en esa función. Fácil, dele al campo una propiedad, por ejemplo ignore_this:

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

Y en su función de serialización:

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

Así es como ignoras algunos campos.

Marcelo Rocha
fuente
1
Esto es más un comentario que una respuesta, ya que no responde la pregunta original.
Wai Ha Lee
¿Quizás porque ya tiene toneladas de respuestas? Es un complemento de las respuestas que recibió.
Marcelo Rocha
Implementaría esto con un nombre de clase como obligatorio si la entrada debe completarse. Entonces puedo verificar $('.mandatory');y!$('.mandatory');
lharby
Cambie ignore_thisa en data-ignore-this="true"lugar de crear sus propios atributos que no validen w3c
zanderwar
0

Prueba el siguiente código:

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

Para múltiples elementos seleccionados ( <select multiple="multiple">), modifiqué la solución de @Jason Norwood-Young para que funcione.

La respuesta (tal como se publicó) solo toma el valor del primer elemento que se seleccionó, no todos . Tampoco se inicializó ni regresó data, el primero arrojó un error de JavaScript.

Aquí está la nueva versión:

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: Solo necesita asegurarse de que el namede su selección se haya []agregado al final, por ejemplo:

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