formularz serializacji javascript (bez frameworka)

141

Zastanawiasz się, czy w javascript jest funkcja bez jquery lub jakiegokolwiek środowiska, która pozwala mi serializować formularz i uzyskać dostęp do wersji zserializowanej?

RussellHarrower
źródło
1
Co rozumiesz przez „dostęp do wersji serializowanej”? Opracowałem skrypt, który nie ma zależności od innych firm, który może przekształcić formularz HTML w obiekt podobny do JSON, który jest wielowymiarowy: github.com/serbanghita/formToObject - jeśli pomoże to upuścić odpowiedź
Șerban Ghiță

Odpowiedzi:

39

Biblioteka miniatur z serializacji nie opiera się na frameworku. Poza czymś takim musisz samodzielnie zaimplementować funkcję serializacji. (choć przy wadze 1,2 kilobajta, dlaczego go nie użyć?)

Lusitanian
źródło
2
To było doskonałe. Ale musiałem dodać case 'email':w sekcji wprowadzania kodu
aravind
och, teraz widzę, kod googlecode nie działa bez javascript. Po prostu plujeThat's an error
user1040495
3
Dołącz kod, a nie tylko link do biblioteki. Jeśli biblioteka jest open source, powinieneś być w stanie skopiować odpowiedni kod.
Łukasz
171

Oto podejście oparte na czystym JavaScript:

var form = document.querySelector('form');
var data = new FormData(form);
var req = new XMLHttpRequest();
req.send(data);

Chociaż wydaje się, że działa tylko w przypadku żądań POST.

https://developer.mozilla.org/en-US/docs/Web/API/FormData

Artur Beljajev
źródło
13
Uwaga, to wysyła multipart, który działa słabo z niektórymi prostymi usługami REST (np. Feathers-mongoDB)
Jason McCarrell
Myślę, że masz rację, że działa tylko z żądaniami POST. To nie było od razu jasne z dokumentów.
manisha
to nie działa dla mnie. Forma jest głęboko zagnieżdżona. Obiekt FormData jest pusty…
chitzui
Uwaga, może być konieczne użycie req.open("POST", "<your-url>");wcześniej. req.send(data);W przeciwnym razie wystąpił błąd InvalidStateError: XMLHttpRequest state must be OPENED.w przeglądarce Firefox 66. Powinien działać z innymi żądaniami, także takimi jak PUT, jeśli zastąpisz POST PUT.
baptx
1
Pomyśl o tym: jak możesz wysłać obiekt FormData za pomocą metody „GET”? Tak, FormData działa tylko z „POST”.
Rex the Strange
88

Tylko dla nowoczesnych przeglądarek

Jeśli kierujesz reklamy na przeglądarki obsługujące URLSearchParamsinterfejs API ( najnowsze przeglądarki ) i FormData(formElement)konstruktor ( najnowsze przeglądarki z wyjątkiem Edge ), użyj tego:

new URLSearchParams(new FormData(formElement)).toString()

Wszędzie oprócz IE

W przypadku przeglądarek, które obsługują, URLSearchParamsale nie obsługują FormData(formElement)konstruktora, użyj tego wypełnienia FormData i tego kodu (działa wszędzie z wyjątkiem IE):

new URLSearchParams(Array.from(new FormData(formElement))).toString()

Przykład

Kompatybilny z IE 10

W przypadku nawet starszych przeglądarek (np. IE 10) użyj wypełnienia FormData , w Array.fromrazie potrzeby polyfill i tego kodu:

Array.from(
  new FormData(formElement),
  e => e.map(encodeURIComponent).join('=')
).join('&')
glebm
źródło
Czy .toString()naprawdę jest tu potrzebne?
Ollie Williams
1
Jeśli chcesz sznurka, a nie URLSearchParams, to tak. Konwersja ciągów zachodzi również niejawnie, jeśli interpolujesz lub dodajesz go do ciągu, w którym to przypadku jawne toStringwywołanie nie jest konieczne.
glebm
One-liner nie działał dla mnie na iOS Safari od kwietnia 2018
jchook
Jaki błąd pojawia się i jaka to wersja Safari? Być może new FormData(formElement)nie jest tam jeszcze obsługiwany?
glebm
@glebm tak, to nie jest obsługiwane w Safari, czy znalazłeś jakieś inne rozwiązanie?
rishiAgar
34
function serialize (form) {
    if (!form || form.nodeName !== "FORM") {
            return;
    }
    var i, j, q = [];
    for (i = form.elements.length - 1; i >= 0; i = i - 1) {
        if (form.elements[i].name === "") {
            continue;
        }
        switch (form.elements[i].nodeName) {
            case 'INPUT':
                switch (form.elements[i].type) {
                    case 'text':
                    case 'tel':
                    case 'email':
                    case 'hidden':
                    case 'password':
                    case 'button':
                    case 'reset':
                    case 'submit':
                        q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value));
                        break;
                    case 'checkbox':
                    case 'radio':
                        if (form.elements[i].checked) {
                                q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value));
                        }                                               
                        break;
                }
                break;
                case 'file':
                break; 
            case 'TEXTAREA':
                    q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value));
                    break;
            case 'SELECT':
                switch (form.elements[i].type) {
                    case 'select-one':
                        q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value));
                        break;
                    case 'select-multiple':
                        for (j = form.elements[i].options.length - 1; j >= 0; j = j - 1) {
                            if (form.elements[i].options[j].selected) {
                                    q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].options[j].value));
                            }
                        }
                        break;
                }
                break;
            case 'BUTTON':
                switch (form.elements[i].type) {
                    case 'reset':
                    case 'submit':
                    case 'button':
                        q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value));
                        break;
                }
                break;
            }
        }
    return q.join("&");
}

Źródło: http://code.google.com/p/form-serialize/source/browse/trunk/serialize-0.1.js

Johndave Decano
źródło
1
Ta serializacja nie wydaje się być zgodna ze standardową serializacją formularza, w której spacje są reprezentowane przez „+”. Powyższe używa tylko encodeURIComponent , który zakoduje spację jako „% 20”. Jeśli wymagana jest zgodność, na końcu można użyć wyrażenia regularnego, aby przekonwertować „% 20” na „+” przed transmisją.
RobG
3
Dodałem taką zmodyfikowaną wersję do gist.github.com/brettz9/7147458 (z kilkoma innymi ulepszeniami)
Brett Zamir
3
Przyciski przesyłania nie muszą być koniecznie przesyłane, przyciski resetowania nigdy nie powinny być przesyłane, a przyciski tylko wtedy, gdy są używane do przesyłania i są w takim przypadku traktowane jako przycisk przesyłania. Zobacz HTML5 4.10.22 Przesyłanie formularza .
RobG
nie serializuj e-maila typu wejściowego.
Ivan
25

Oto nieco zmodyfikowana wersja TibTibsa:

function serialize(form) {
    var field, s = [];
    if (typeof form == 'object' && form.nodeName == "FORM") {
        var len = form.elements.length;
        for (i=0; i<len; i++) {
            field = form.elements[i];
            if (field.name && !field.disabled && field.type != 'file' && field.type != 'reset' && field.type != 'submit' && field.type != 'button') {
                if (field.type == 'select-multiple') {
                    for (j=form.elements[i].options.length-1; j>=0; j--) {
                        if(field.options[j].selected)
                            s[s.length] = encodeURIComponent(field.name) + "=" + encodeURIComponent(field.options[j].value);
                    }
                } else if ((field.type != 'checkbox' && field.type != 'radio') || field.checked) {
                    s[s.length] = encodeURIComponent(field.name) + "=" + encodeURIComponent(field.value);
                }
            }
        }
    }
    return s.join('&').replace(/%20/g, '+');
}

Wyłączone pola są odrzucane, a nazwy są również kodowane jako adresy URL. Zastąpienie wyrażenia regularnego% 20 znaków odbywa się tylko raz, przed zwróceniem ciągu.

Ciąg zapytania ma taką samą postać jak wynik z metody $ .serialize () jQuery.

Simon Steinberger
źródło
6
+1 za poświęcenie czasu na ulepszenie kodu. Lubię, gdy ludzie odkrywają moje wady, ponieważ jest to dobra okazja do nauki. +1 za utrzymanie ładnego wyglądu. -1, ponieważ nie mogę dać +2 = (
TibTibs
1
form.nodeName.toLowerCase() == "form"zamiast tego można dodaćform.nodeName == "FORM"
StefanNch
12

Zacząłem od odpowiedzi Johndave Decano.

Powinno to rozwiązać kilka problemów wymienionych w odpowiedziach na jego funkcję.

  1. Zastąp% 20 symbolem +.
  2. Typy Prześlij / Przyciski zostaną przesłane tylko wtedy, gdy zostały kliknięte w celu przesłania formularza.
  3. Przyciski resetowania będą ignorowane.
  4. Kod wydawał mi się zbędny, ponieważ zasadniczo robi to samo, niezależnie od typów pól. Nie wspominając o niezgodności z typami pól HTML5, takimi jak „tel” i „email”, dlatego usunąłem większość szczegółów z instrukcjami przełączania.

Typy przycisków będą nadal ignorowane, jeśli nie mają wartości nazwy.

function serialize(form, evt){
    var evt    = evt || window.event;
    evt.target = evt.target || evt.srcElement || null;
    var field, query='';
    if(typeof form == 'object' && form.nodeName == "FORM"){
        for(i=form.elements.length-1; i>=0; i--){
            field = form.elements[i];
            if(field.name && field.type != 'file' && field.type != 'reset'){
                if(field.type == 'select-multiple'){
                    for(j=form.elements[i].options.length-1; j>=0; j--){
                        if(field.options[j].selected){
                            query += '&' + field.name + "=" + encodeURIComponent(field.options[j].value).replace(/%20/g,'+');
                        }
                    }
                }
                else{
                    if((field.type != 'submit' && field.type != 'button') || evt.target == field){
                        if((field.type != 'checkbox' && field.type != 'radio') || field.checked){
                            query += '&' + field.name + "=" + encodeURIComponent(field.value).replace(/%20/g,'+');
                        }   
                    }
                }
            }
        }
    }
    return query.substr(1);
}

W ten sposób obecnie używam tej funkcji.

<form onsubmit="myAjax('http://example.com/services/email.php', 'POST', serialize(this, event))">
TibTibs
źródło
6
+1 za ładnie zreformowany kod. -1 w celu zignorowania wyłączonych pól, które nie powinny pojawiać się w ciągu zapytania. +1 za bardzo eleganckie zestawienie, które pozwala uniknąć wielokrotnego liczenia elementów formularza. Razem: +1 :-) Dzięki!
Simon Steinberger
Dobra uwaga na temat wyłączonych pól, natknąłem się na to niedawno z nową funkcją, którą pisałem. Daj +1 wam obojgu, ponieważ lubię czytać zabawne komentarze. :)
TibTibs
11

Jeśli chcesz przesłać formularz „myForm” za pomocą POST w formacie json, możesz to zrobić:

const formEntries = new FormData(myForm).entries();
const json = Object.assign(...Array.from(formEntries, ([x,y]) => ({[x]:y})));
fetch('/api/foo', {
  method: 'POST',
  body: JSON.stringify(json)
});

Druga linia konwertuje z tablicy takiej jak:

[["firstProp", "firstValue"], ["secondProp", "secondValue"], ...and so on... ]

... w zwykły obiekt, taki jak:

{"firstProp": "firstValue", "secondProp": "secondValue", ...and so on ... }

... dokonuje tej konwersji, przekazując mapFn do Array.from (). To mapFn jest stosowane do każdej pary ["a", "b"] i konwertuje je na {"a": "b"}, tak że tablica zawiera wiele obiektów z tylko jedną właściwością w każdej. MapFn używa „destrukturyzacji”, aby uzyskać nazwy pierwszej i drugiej części pary, a także używa ES6 „ComputedPropertyName”, aby ustawić nazwę właściwości w obiekcie zwróconym przez mapFn (dlatego jest napisane „[ x]: coś ", a nie tylko" x: coś ".

Wszystkie te pojedyncze obiekty właściwości są następnie przekazywane do argumentów funkcji Object. assign (), która łączy wszystkie pojedyncze obiekty właściwości w jeden obiekt, który ma wszystkie właściwości.

Array.from (): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from

Destrukturyzacja w parametrach: https://simonsmith.io/destruifying-objects-as-function-parameters-in-es6/

Więcej o obliczonych nazwach właściwości tutaj: Zmienna jako nazwa właściwości w literale obiektu JavaScript?

molsson
źródło
U mnie działa, nawet jeśli nie rozumiem drugiej linii, czy możesz podać więcej informacji na ten temat?
Espoir Murhabazi
Piękna odpowiedź przy użyciu operatora rozprzestrzeniania oraz natywnych metod Object i Array.
Vinny Fonseca
Zauważ, że to podejście nie jest obsługiwane w IE (.entries ())
stary,
Strona MDN dla Object.entries () zawiera krótkie wypełnienie, którego możesz użyć w IE: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/ ... ale IE również nie obsługuje operatora spreadu.
molsson
możesz serializować formularz za pomocą nowej metody Object.fromEntries (new FormData (myFormElement)).
miguel savignano
10

Działa we wszystkich przeglądarkach.

const formSerialize = formElement => {
  const values = {};
  const inputs = formElement.elements;

  for (let i = 0; i < inputs.length; i++) {
    values[inputs[i].name] = inputs[i].value;
  }
  return values;
}

const dumpValues = form => () => {
  
  const r = formSerialize(form);
  console.log(r);
  console.log(JSON.stringify(r));
}

const form = document.querySelector('form');

dumpValues(form)();

form.addEventListener('change',dumpValues(form));
<form action="/my-handling-form-page" method="post">
  <div>
    <label for="name">Name:</label>
    <input type="text" id="name" name="user_name" value="John">
  </div>
  <div>
    <label for="mail">E-mail:</label>
    <input type="email" id="mail" name="user_mail" value="[email protected]">
  </div>
  <div>
    <label for="interests">Interest:</label>
    <select required=""  id="interests" name="interests">
      <option value="" selected="selected">- None -</option>
      <option value="drums">Drums</option>
      <option value="js">Javascript</option>
      <option value="sports">Sports</option>
      <option value="trekking">Trekking</option>
    </select>
  </div>
  <div>
    <label for="msg">Message:</label>
    <textarea id="msg" name="user_message">Hello My Friend</textarea>
  </div>
</form>

David Lemon
źródło
ten tworzy json, zakładam, że autor pytał o serializację do URI.
jaskmar
Chciałbym zobaczyć, jak to działa dla wielu formularzy opcji do wyboru.
Zach Smith
@ZachSmith To już działało, ale dodałem przykład, aby to sprawdzić
David Lemon
8
HTMLElement.prototype.serialize = function(){
    var obj = {};
    var elements = this.querySelectorAll( "input, select, textarea" );
    for( var i = 0; i < elements.length; ++i ) {
        var element = elements[i];
        var name = element.name;
        var value = element.value;

        if( name ) {
            obj[ name ] = value;
        }
    }
    return JSON.stringify( obj );
}

Aby użyć w ten sposób:

var dataToSend = document.querySelector("form").serialize();

Mam nadzieję, że pomogłem.

Eduardo Borges
źródło
3
Nie będzie działać z polami wyboru. Tutaj musisz jawnie sprawdzić typ wejścia.
Adrian Preuss,
5

Jeśli chcesz serializować dane wejściowe w zdarzeniu. Oto czysta metoda JavaScript, której używam.

// serialize form
var data = {};
var inputs = [].slice.call(e.target.getElementsByTagName('input'));
inputs.forEach(input => {
  data[input.name] = input.value;
});

Dane będą obiektem JavaScript danych wejściowych.

CAOakley
źródło
2
To powinno działać na większości elementów. Zdecydowanie nie textarea / select
jaggedsoft
czy to slice.call to to samo co Array.from?
user1040495
5

Refaktoryzowana wersja kodu @ SimonSteinbergera wykorzystująca mniej zmiennych i wykorzystująca prędkość forEachpętli (które są nieco szybsze niż fors)

function serialize(form) {
    var result = [];
    if (typeof form === 'object' && form.nodeName === 'FORM')
        Array.prototype.slice.call(form.elements).forEach(function(control) {
            if (
                control.name && 
                !control.disabled && 
                ['file', 'reset', 'submit', 'button'].indexOf(control.type) === -1
            )
                if (control.type === 'select-multiple')
                    Array.prototype.slice.call(control.options).forEach(function(option) {
                        if (option.selected) 
                            result.push(encodeURIComponent(control.name) + '=' + encodeURIComponent(option.value));
                    });
                else if (
                    ['checkbox', 'radio'].indexOf(control.type) === -1 || 
                    control.checked
                ) result.push(encodeURIComponent(control.name) + '=' + encodeURIComponent(control.value));
        });
        return result.join('&').replace(/%20/g, '+');
}
Stefan Gabos
źródło
3

Przefaktorowałem odpowiedź TibTibsa na coś, co jest o wiele jaśniejsze do odczytania. Jest nieco dłuższy ze względu na szerokość 80 znaków i kilka komentarzy.

Ponadto ignoruje puste nazwy pól i puste wartości.

// Serialize the specified form into a query string.
//
// Returns a blank string if +form+ is not actually a form element.
function $serialize(form, evt) {
  if(typeof(form) !== 'object' && form.nodeName !== "FORM")
    return '';

  var evt    = evt || window.event || { target: null };
  evt.target = evt.target || evt.srcElement || null;
  var field, query = '';

  // Transform a form field into a query-string-friendly
  // serialized form.
  //
  // [NOTE]: Replaces blank spaces from its standard '%20' representation
  //         into the non-standard (though widely used) '+'.
  var encode = function(field, name) {
    if (field.disabled) return '';

    return '&' + (name || field.name) + '=' +
           encodeURIComponent(field.value).replace(/%20/g,'+');
  }

  // Fields without names can't be serialized.
  var hasName = function(el) {
    return (el.name && el.name.length > 0)
  }

  // Ignore the usual suspects: file inputs, reset buttons,
  // buttons that did not submit the form and unchecked
  // radio buttons and checkboxes.
  var ignorableField = function(el, evt) {
    return ((el.type == 'file' || el.type == 'reset')
        || ((el.type == 'submit' || el.type == 'button') && evt.target != el)
        || ((el.type == 'checkbox' || el.type == 'radio') && !el.checked))
  }

  var parseMultiSelect = function(field) {
    var q = '';

    for (var j=field.options.length-1; j>=0; j--) {
      if (field.options[j].selected) {
        q += encode(field.options[j], field.name);
      }
    }

    return q;
  };

  for(i = form.elements.length - 1; i >= 0; i--) {
    field = form.elements[i];

    if (!hasName(field) || field.value == '' || ignorableField(field, evt))
      continue;

    query += (field.type == 'select-multiple') ? parseMultiSelect(field)
                                               : encode(field);
  }

  return (query.length == 0) ? '' : query.substr(1);
}
Brian Edmonds
źródło
Skopiowałem to bezpośrednio do mojej aplikacji i funkcja wielokrotnego wyboru nie działa (wartości są zduplikowane)
anastymiczny
@anastymous Dzięki za haczyk, został naprawiony.
Brian Edmonds
Cześć Brian, do czego służy evt ? i co mam za to przekazać? Firefox mówi mi, że nie jest zdefiniowany.
anastymous
Cześć anastymicznie, jeszcze raz dziękuję za haczyk, należy to naprawić zmieniając przypisanie do evt na evt = evt || window.event || { target: null };(tak jak to zrobiła edycja) Chodzi o to, aby przekazać zdarzenie, które wyzwoliło serializację, jeśli istnieje, takie jak formularz zdarzenie „wyślij” lub „kliknięcie” przycisku. Jeśli formularz ma wiele przycisków do przesłania, chcesz uwzględnić tylko wartość przycisku, który wywołał zdarzenie, a zignorować pozostałe. Zhakowałem
Brian Edmonds
2
  // supports IE8 and IE9 
  function serialize(form) {
    var inputs = form.elements;
    var array = [];
    for(i=0; i < inputs.length; i++) {
      var inputNameValue = inputs[i].name + '=' + inputs[i].value;
      array.push(inputNameValue);
    }
    return array.join('&');
  }
 //using the serialize function written above
 var form = document.getElementById("form");//get the id of your form. i am assuming the id to be named form.
 var form_data = serialize(form);
 var xhr = new XMLHttpRequest();
 xhr.send(form_data);

 //does not work with IE8 AND IE9
 var form = document.querySelector('form');
 var data = new FormData(form);
 var xhr = new XMLHttpRequest();
 xhr.send(data);
Onome Mine Adamu
źródło
2

Wziąłem metodę entry () formData z @moison answer iz MDN jest powiedziane, że:

Metoda FormData.entries () zwraca iterator umożliwiający przejrzenie wszystkich par klucz / wartość zawartych w tym obiekcie. Kluczem każdej pary jest obiekt USVString; wartość USVString lub Blob.

ale jedynym problemem jest to, że przeglądarka mobilna (Android i Safari nie są obsługiwane), a także IE i Safari na komputery stacjonarne

ale w zasadzie oto moje podejście:

let theForm =  document.getElementById("contact"); 

theForm.onsubmit = function(event) {
    event.preventDefault();

    let rawData = new FormData(theForm);
    let data = {};

   for(let pair of rawData.entries()) {
     data[pair[0]] = pair[1]; 
    }
    let contactData = JSON.stringify(data);
    console.warn(contactData);
    //here you can send a post request with content-type :'application.json'

};

kod można znaleźć tutaj

Espoir Murhabazi
źródło
2

Użycie funkcji redukcji JavaScript powinno załatwić sprawę dla wszystkich przeglądarek, w tym IE9>:

Array.prototype.slice.call(form.elements) // convert form elements to array
    .reduce(function(acc,cur){   // reduce 
        var o = {type : cur.type, name : cur.name, value : cur.value}; // get needed keys
        if(['checkbox','radio'].indexOf(cur.type) !==-1){
            o.checked = cur.checked;
        } else if(cur.type === 'select-multiple'){
            o.value=[];
            for(i=0;i<cur.length;i++){
                o.value.push({
                    value : cur.options[i].value,
                    selected : cur.options[i].selected
                });
            }
        }
        acc.push(o);
        return acc;
 },[]);

Przykład na żywo poniżej.

crashtestxxx
źródło
czy to działa w przypadku wielokrotnego wyboru? wydaje się, że kiedy używam twojego kodu, zwraca tylko pierwszą pozycję z wielu wybranych wartości opcji
Zach Smith
@ZachSmith Zaktualizowałem moją odpowiedź, aby zawierała wiele wybranych elementów.
crashtestxxx
0

Mam nadzieję, że to zadziała

var serializeForm = (formElement) => {
  const formData = {};
  const inputs = formElement.elements;

  for (let i = 0; i < inputs.length; i++) {
    if(inputs[i].name!=="")
        formData[inputs[i].name] = inputs[i].value;
  }
  return formData;
}
Manoj Rana
źródło
0

Poprawa odpowiedzi Davida Lemona.

To konwertuje dane formularza do formatu JSON i umożliwia ustawienie formularza z obiektu danych.

const main = () => {
  const form = document.forms['info'];
  const data = {
    "user_name"       : "John",
    "user_email"      : "[email protected]",
    "user_created"    : "2020-03-24",
    "user_age"        : 42,
    "user_subscribed" : true,
    "user_interests"  : "sports",
    "user_message"    : "Hello My Friend"
  };

  populateForm(form, data);
  updateJsonView(form);
  form.addEventListener('change', (e) => updateJsonView(form));
}

const getFieldValue = (field, opts) => {
  let type = field.getAttribute('type');
  if (type) {
    switch (type) {
      case 'checkbox':
        return field.checked;
      case 'number':
        return field.value.includes('.')
          ? parseFloat(field.value)
          : parseInt(field.value, 10);
    }
  }
  if (opts && opts[field.name] && opts[field.name].type) {
    switch (opts[field.name].type) {
      case 'int':
        return parseInt(field.value, 10);
      case 'float':
        return parseFloat(field.value);
    }
  }
  return field.value;
}

const setFieldValue = (field, value) => {
  let type = field.getAttribute('type');
  if (type) {
    switch (type) {
      case 'checkbox':
        field.checked = value;
        break;
      default:
        field.value = value;
        break;
    }
  } else {
    field.value = value;
  }
}

const extractFormData = (form, opts) => {
  return Array.from(form.elements).reduce((data, element) => {
    return Object.assign(data, { [element.name] : getFieldValue(element, opts) });
  }, {});
};

const populateForm = (form, data) => {
  return Array.from(form.elements).forEach((element) => {
    setFieldValue(element, data[element.name]);
  });
};

const updateJsonView = (form) => {
  let fieldOptions = {};
  let formData = extractFormData(form, fieldOptions);
  let serializedData = JSON.stringify(formData, null, 2);
  document.querySelector('.json-view').textContent = serializedData;
};

main();
.form-field {
  margin-bottom: 0.5em;
}

.form-field label {
  display: inline-block;
  font-weight: bold;
  width: 7em;
  vertical-align: top;
}

.json-view {
  position: absolute;
  top: 0.667em;
  right: 0.667em;
  border: thin solid grey;
  padding: 0.5em;
  white-space: pre;
  font-family: monospace;
  overflow: scroll-y;
  max-height: 100%;
}
<form name="info" action="/my-handling-form-page" method="post">
  <div class="form-field">
    <label for="name">Name:</label>
    <input type="text" id="name" name="user_name">
  </div>
  <div class="form-field">
    <label for="mail">E-mail:</label>
    <input type="email" id="mail" name="user_email">
  </div>
  <div class="form-field">
    <label for="created">Date of Birth:</label>
    <input type="date" id="created" name="user_created">
  </div>
  <div class="form-field">
    <label for="age">Age:</label>
    <input type="number" id="age" name="user_age">
  </div>
  <div class="form-field">
    <label for="subscribe">Subscribe:</label>
    <input type="checkbox" id="subscribe" name="user_subscribed">
  </div>
  <div class="form-field">
    <label for="interests">Interest:</label>
    <select required=""  id="interests" name="user_interests">
      <option value="" selected="selected">- None -</option>
      <option value="drums">Drums</option>
      <option value="js">Javascript</option>
      <option value="sports">Sports</option>
      <option value="trekking">Trekking</option>
    </select>
  </div>
  <div class="form-field">
    <label for="msg">Message:</label>
    <textarea id="msg" name="user_message"></textarea>
  </div>
</form>
<div class="json-view"></div>

Panie Polywhirl
źródło
0

Można to zrobić za pomocą bardzo prostej funkcji w następujący sposób

function serialize(form) {
        let requestArray = [];
        form.querySelectorAll('[name]').forEach((elem) => {
            requestArray.push(elem.name + '=' + elem.value);
        });
        if(requestArray.length > 0)
            return requestArray.join('&');
        else
            return false;
    }

 serialized = serialize(document.querySelector('form'))
  console.log(serialized);
<form>

  <input type='text' name='fname' value='Johne'/>
  <input type='text' name='lname' value='Doe'/>
  <input type='text' name='contact[]' value='99999999'/>
  <input type='text' name='contact[]' value='34423434345'/>

</form>

Indygowiec
źródło
0

Oto podejście oparte na czystym JavaScript:

var form = document.querySelector('form');
var data = new FormData(form);

  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
       console.log(this.responseText);
    }
  };
  xhttp.open("POST", "<YOUR-URL>", true);
  xhttp.send(data);
}
RahmanRezaee
źródło
-1
document.serializeForm = function (selector) {
     var dictionary = {};
     var form = document.querySelector(selector);
     var formdata = new FormData(form);
     var done = false;
     var iterator = formdata.entries();
     do {
         var prop = iterator.next();
         if (prop.done && !prop.value) {
             done = true;
         }
         else {
             dictionary[prop.value[0]] = prop.value[1];
         }

     } while (!done);
     return dictionary;
}
Hasan
źródło
Wygląda schludnie, ale nie uwzględnia przycisków radiowych ani
pól
-1

W celach debugowania może ci to pomóc:

function print_form_data(form) {
    const form_data = new FormData(form);

    for (const item of form_data.entries()) {
        console.log(item);
    }

    return false;
}
tobias47n9e
źródło
-1

Mógłbym być szalony, ale te odpowiedzi są dla mnie poważnie nadęte. Oto moje rozwiązanie

function serialiseForm(form) {
  var input = form.getElementsByTagName("input");
  var formData = {};
  for (var i = 0; i < input.length; i++) {
    formData[input[i].name] = input[i].value;
  }
  return formData = JSON.stringify(formData);
}
Michael Sherris Caley
źródło
oparcie formularza na pobieraniu elementów według typu danych wejściowych zakończy się niepowodzeniem select- i tak dalej
Zach Smith