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?
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?
Odpowiedzi:
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ć?)
case 'email':
w sekcji wprowadzania kodu
That's an error
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.
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.
Jeśli kierujesz reklamy na przeglądarki obsługujące URLSearchParams
interfejs API ( najnowsze przeglądarki ) i FormData(formElement)
konstruktor ( najnowsze przeglądarki z wyjątkiem Edge ), użyj tego:
new URLSearchParams(new FormData(formElement)).toString()
W przypadku przeglądarek, które obsługują, URLSearchParams
ale 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()
W przypadku nawet starszych przeglądarek (np. IE 10) użyj wypełnienia FormData , w Array.from
razie potrzeby polyfill i tego kodu:
Array.from(
new FormData(formElement),
e => e.map(encodeURIComponent).join('=')
).join('&')
.toString()
naprawdę jest tu potrzebne?
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 toString
wywołanie nie jest konieczne.
new FormData(formElement)
nie jest tam jeszcze obsługiwany?
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
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.
form.nodeName.toLowerCase() == "form"
zamiast tego można dodaćform.nodeName == "FORM"
Zacząłem od odpowiedzi Johndave Decano.
Powinno to rozwiązać kilka problemów wymienionych w odpowiedziach na jego funkcję.
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))">
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?
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="john@jonhson.j">
</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>
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.
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.
Refaktoryzowana wersja kodu @ SimonSteinbergera wykorzystująca mniej zmiennych i wykorzystująca prędkość forEach
pętli (które są nieco szybsze niż for
s)
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, '+');
}
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);
}
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
// 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);
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
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.
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;
}
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" : "john@jonhson.com",
"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>
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>
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);
}
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;
}
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;
}
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);
}
select
- i tak dalej