Uzyskać pola wprowadzania formularza za pomocą jQuery?

412

Mam formularz z wieloma polami do wprowadzania danych.

Czy podczas przechwytywania zdarzenia przesłania formularza za pomocą jQuery można uzyskać wszystkie pola wejściowe tego formularza w tablicy asocjacyjnej?

Wasil
źródło
23
To dobre pytanie; w rzeczywistości uważam, że to naprawdę dziwne, że jQuery nie ma funkcji, która dokładnie to robi. Istnieją funkcje pozwalające uzyskać dane formularza w dwóch różnych formatach, ale nie w tym najwygodniejszym dla skryptów … (Może .val () powinien zwrócić taką tablicę, jeśli zostanie wywołany na elemencie formularza?)
Luke Maurer

Odpowiedzi:

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

});

Dzięki wskazówce od Simon_Weaver, oto inny sposób, w jaki możesz to zrobić, używając serializeArray:

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

Pamiętaj, że ten fragment kodu nie powiedzie się na <select multiple>elementach.

Wygląda na to, że nowe dane wejściowe formularza HTML 5 nie działają serializeArrayw jQuery w wersji 1.3. Działa to w wersji 1.4+

pseudonim
źródło
1
W nowszych wersjach jQuery odpowiedź Simon_Weaver jest bardziej niezawodna i łatwiejsza.
MightyE
1
@MightyE & @Simon_Weaver - masz rację, jest to bardziej niezawodna metoda, ale nie robi dokładnie tego, czego szukał OP. serializeArray zwraca tablicę obiektów o właściwościach namei value. Lepszym rozwiązaniem może być przetworzenie danych wyjściowych z serializeArray na dowolny wymagany format.
nickf
1
Myślę, że serializeArray () robi dokładnie to, co chcesz i jest znacznie mniej kodu.
slacy
1
Co do pierwszej opcji, co z <select>elementami? Próbowałem, var $inputs = $('#new-ticket :input, :select');ale to nie działa. Czy ktoś wie, jak to zrobić, ponieważ nie sądzę, że robię to dobrze.
Nathan
2
@Nathan, powinieneś użyć $("#new-ticket :input, #new-ticket :select"), a nawet lepiej,$(":input, :select", "#new-ticket")
nickf
252

Późno na imprezę w tej kwestii, ale jest to jeszcze łatwiejsze:

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

});
Lance pędzi
źródło
8
To naprawdę najlepsza odpowiedź. Zachowuje nawet dowolne formatowanie tablic dla pól wejściowych. Nie sądzę, aby odpowiedź nickf zachowałaby twoje struktury danych w nienaruszonym stanie, gdyby zostały utworzone przy użyciu Zend_Form, na przykład, gdzie jako pola danych wejściowych miałbyś pole [coś] i pole [coś_else] ... przynajmniej semantycznie nie widzę, jak by to było ...
msumme
43
Zgodnie z dokumentacją interfejsu API jQuery .serialize()( api.jquery.com/serialize ) umieszcza wszystkie elementy formularza w jednym ciągu gotowym do dołączenia do adresu URL w ciągu zapytania, zasadniczo naśladując żądanie formularza GET. Nie osiągnęłoby to tego, co osiągnęła odpowiedź nickf.
Christopher Parker
To najlepsza odpowiedź!
Daniel Hunter
5
Warto wiedzieć: .serialize()działa również na elementy po prostu formy. Tak $('form select').serialize()serializuje dane tylko dla wybranych.
antytoksyczny
3
Zamiast powtarzać $('#myForm'), użyj $ (this).
Jimothy,
23

jquery.form Wtyczka może pomóc z tym, co inni szukają tego skończyć na to pytanie. Nie jestem pewien, czy robi to bezpośrednio, co chcesz, czy nie.

Istnieje również funkcja serializeArray .

Simon_Weaver
źródło
15

Czasami okazuje się, że otrzymywanie jednego na raz jest bardziej przydatne. W tym celu jest to:

var input_name = "firstname";
var input = $("#form_id :input[name='"+input_name+"']"); 
Malachiasz
źródło
Dołączając [0].valuedo tego tj. $(...)[0].value;Bezpośrednio podałem wartość wejściową, dzięki!
Pau Coma Ramirez,
12
$('#myForm').bind('submit', function () {
  var elements = this.elements;
});

Zmienna elements będzie zawierać wszystkie dane wejściowe, zaznaczenia, pola tekstowe i zestawy pól w formularzu.

Quentin
źródło
9

Oto inne rozwiązanie, w ten sposób możesz pobrać wszystkie dane o formularzu i użyć go do połączenia z serwerem lub czegoś takiego.

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

Następnie możesz użyć tego z wywołaniami 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" );
       });
}

Mam nadzieję, że jest to przydatne dla każdego z was :)

Ole Aldric
źródło
5

Miałem podobny problem z lekkim zwrotem akcji i myślałem, że to wyrzucę. Mam funkcję wywołania zwrotnego, która pobiera formularz, więc miałem już obiekt formularza i nie mogłem łatwo wprowadzić jego wariantów $('form:input'). Zamiast tego wymyśliłem:

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

Podobna, ale nie identyczna sytuacja, ale ten wątek okazał się bardzo przydatny i pomyślałem, że schowam go na końcu i mam nadzieję, że ktoś inny uzna to za przydatne.

Chris
źródło
4

Asocjacyjny? Nie bez pracy, ale możesz użyć ogólnych selektorów:

var items = new Array();

$('#form_id:input').each(function (el) {
    items[el.name] = el;
});
Oli
źródło
w rzeczywistości odpowiedź Lance'a utrzymuje tablicę asocjacyjną nietkniętą dla wartości POST i zajmuje jeden wiersz kodu.
msumme
dlaczego przedmioty są tablicą? używasz go jak zwykłego obiektu. Tablica nie jest potrzebna
Jonathan Morales Vélez
3
@ Oliathan 2008 Oli nie jest już gotowy na komentarze. 2015 r. Zgadza się z tobą.
Oli
4

jQuery serializeArraynie zawiera wyłączonych pól, więc jeśli ich potrzebujesz, spróbuj:

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

Nie zapomnij pól wyboru i przycisków opcji -

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
Mężczyzna nazywa się Haney
źródło
3

Ten fragment kodu będzie działał zamiast nazwy, e-mail wprowadź nazwę pola formularza

$(document).ready(function(){
  $("#form_id").submit(function(event){
    event.preventDefault();
    var name = $("input[name='name']",this).val();
    var email = $("input[name='email']",this).val();
  });
});
sparsh turkane
źródło
3

Wydaje się dziwne, że nikt nie ocenił ani nie zaproponował zwięzłego rozwiązania w zakresie uzyskiwania danych z listy. Prawie żadne formy nie będą obiektami jednowymiarowymi.

Wadą tego rozwiązania jest oczywiście to, że do obiektów singletonowych trzeba będzie uzyskać dostęp w indeksie [0]. Ale IMO jest o wiele lepsze niż stosowanie jednego z kilkudziesięciu linii rozwiązań mapowania.

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
źródło
2

Miałem ten sam problem i rozwiązałem go w inny sposób.

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

Zwraca wartość wszystkich pól wejściowych. Możesz zmienić na $(':input')bardziej szczegółowy.

suizo
źródło
2

To samo rozwiązanie, co podane przez nickf , ale z uwzględnieniem nazw wejściowych tablic, np

<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
źródło
1

Jeśli potrzebujesz uzyskać wiele wartości z danych wejściowych i używasz [] do zdefiniowania danych wejściowych z wieloma wartościami, możesz użyć następujących opcji:

$('#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
źródło
1

Inspirowane odpowiedziami Lance'a Rushinga i Simona_Weavera , to moje ulubione rozwiązanie.

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

Dane wyjściowe to tablica obiektów, np

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

Z poniższym kodem

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

jego końcowy wynik byłby

{"start-time":"11:01", "end-time":"11:01"}
T.Liu
źródło
1

Używam tego kodu bez każdej pętli:

$('.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
źródło
1

Mam nadzieję, że jest to pomocne i najłatwiejsze.

 $("#form").submit(function (e) { 
    e.preventDefault();
    input_values =  $(this).serializeArray();
  });
dipenparmar12
źródło
Co dziwne, nie działało to w najnowszej wersji jquery 3.4.1
powtórka
0

Kiedy potrzebowałem wykonać wywołanie ajax ze wszystkimi polami formularza, miałem problemy z selektorem : input zwracającym wszystkie pola wyboru, niezależnie od tego, czy były zaznaczone. Dodałem nowy selektor, aby uzyskać tylko możliwe elementy formularza:

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

stosowanie:

$('#form_id :submitable');

Nie przetestowałem go jeszcze z wieloma polami wyboru, ale działa to tak, aby uzyskać wszystkie pola formularza w sposób zgodny ze standardowym przesyłaniem.

Użyłem tego przy dostosowywaniu opcji produktu w witrynie OpenCart w celu uwzględnienia pól wyboru i pól tekstowych, a także standardowego typu pola wyboru.

slarti42uk
źródło
0

serialize () to najlepsza metoda. @ Christopher Parker powiedział, że anwser Nickfa osiąga więcej, jednak nie bierze pod uwagę, że formularz może zawierać obszar tekstowy i wybrane menu. O wiele lepiej jest użyć serialize (), a następnie manipulować nim tak, jak trzeba. Dane z serialize () można wykorzystać w poście Ajax lub w get, więc nie ma problemu.

Pałka policjanta
źródło
0

Mam nadzieję, że to komuś pomoże. :)

// 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;
};
juliański
źródło
0

Wszystkie odpowiedzi są dobre, ale czy istnieje pole, które chcesz zignorować w tej funkcji? Łatwo, nadaj temu polu właściwość, na przykład ignore_this:

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

I w twojej funkcji serializacji:

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

W ten sposób ignorujesz niektóre pola.

Marcelo Rocha
źródło
1
To bardziej komentarz niż odpowiedź, ponieważ nie odpowiada na pierwotne pytanie.
Wai Ha Lee
Może dlatego, że ma już mnóstwo odpowiedzi? To uzupełnienie odpowiedzi, które otrzymał.
Marcelo Rocha,
Zaimplementowałbym to z nazwą klasy obowiązkową, jeśli dane wejściowe muszą być wypełnione. Wtedy mogę sprawdzić $('.mandatory');i!$('.mandatory');
lharby
Zmień ignore_thisna data-ignore-this="true"zamiast tworzyć własne atrybuty, które nie sprawdzają poprawności w3c
zanderwar
0

Wypróbuj następujący kod:

jQuery("#form").serializeArray().filter(obje => 
obje.value!='').map(aobj=>aobj.name+"="+aobj.value).join("&")
Teodor Rautu
źródło
2
Proszę wyjaśnić swoją odpowiedź
Ling Vu
0

W przypadku wielu wybranych elementów (<select multiple="multiple"> ) zmodyfikowałem rozwiązanie z @Jason Norwood-Young, aby działało.

Odpowiedź (jak opublikowano) bierze wartość tylko z pierwszego wybranego elementu, a nie wszystkich . Nie zainicjował się ani nie zwróciłdata , ten pierwszy generuje błąd JavaScript.

Oto nowa wersja:

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
}

Stosowanie:

_get_values($('#form'))

Uwaga: Musisz tylko upewnić się, że wybrany nameprzez Ciebie dodatek został []dołączony na końcu, na przykład:

<select name="favorite_colors[]" multiple="multiple">
  <option value="red">Red</option>
  <option value="green">Green</option>
  <option value="blue">Blue</option>
</select>
tzazo
źródło
-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
źródło