Ingin tahu apakah ada fungsi dalam javascript tanpa jquery atau kerangka kerja apa pun yang memungkinkan saya untuk membuat serialisasi formulir dan mengakses versi serial?
javascript
forms
serialization
RussellHarrower
sumber
sumber
Jawaban:
Miniatur dari perpustakaan berseri tidak bergantung pada kerangka kerja. Selain itu, Anda harus mengimplementasikan fungsi serialisasi sendiri. (meski dengan berat 1,2 kilobyte, mengapa tidak menggunakannya?)
sumber
case 'email':
di bagian input kodeThat's an error
Berikut adalah pendekatan JavaScript murni:
var form = document.querySelector('form'); var data = new FormData(form); var req = new XMLHttpRequest(); req.send(data);
Meskipun tampaknya hanya berfungsi untuk permintaan POST.
https://developer.mozilla.org/en-US/docs/Web/API/FormData
sumber
req.open("POST", "<your-url>");
sebelumnya.req.send(data);
Jika tidak, saya mengalami kesalahanInvalidStateError: XMLHttpRequest state must be OPENED.
pada Firefox 66. Seharusnya bekerja dengan permintaan lain juga seperti PUT adalah Anda mengganti POST dengan PUT.Hanya untuk browser modern
Jika Anda menargetkan browser yang mendukung
URLSearchParams
API ( browser terbaru ) danFormData(formElement)
konstruktor ( browser terbaru ), gunakan ini:new URLSearchParams(new FormData(formElement)).toString()
Di mana-mana kecuali IE
Untuk browser yang mendukung
URLSearchParams
tetapi bukanFormData(formElement)
konstruktornya, gunakan polyfill FormData ini dan kode ini (berfungsi di mana saja kecuali IE):new URLSearchParams(Array.from(new FormData(formElement))).toString()
Contoh
Tampilkan cuplikan kode
var form = document.querySelector('form'); var out = document.querySelector('output'); function updateResult() { try { out.textContent = new URLSearchParams(Array.from(new FormData(form))); out.className = ''; } catch (e) { out.textContent = e; out.className = 'error'; } } updateResult(); form.addEventListener('input', updateResult);
body { font-family: Arial, sans-serif; display: flex; flex-wrap: wrap; } input[type="text"] { margin-left: 6px; max-width: 30px; } label + label { margin-left: 10px; } output { font-family: monospace; } .error { color: #c00; } div { margin-right: 30px; }
<!-- FormData polyfill for older browsers --> <script src="https://unpkg.com/[email protected]/formdata.min.js"></script> <div> <h3>Form</h3> <form id="form"> <label>x:<input type="text" name="x" value="1"></label> <label>y:<input type="text" name="y" value="2"></label> <label> z: <select name="z"> <option value="a" selected>a</option> <option value="b" selected>b</option> </select> </label> </form> </div> <div> <h3>Query string</h3> <output for="form"></output> </div>
Kompatibel dengan IE 10
Untuk browser yang lebih lama lagi (misalnya IE 10), gunakan polyfill FormData , sebuah
Array.from
polyfill jika perlu dan kode ini:Array.from( new FormData(formElement), e => e.map(encodeURIComponent).join('=') ).join('&')
sumber
.toString()
benar-benar perlu di sini?URLSearchParams
, maka ya. Konversi string juga terjadi secara implisit jika Anda menginterpolasi atau menambahkannya ke string, dalam hal initoString
panggilan eksplisit tidak diperlukan.new FormData(formElement)
belum didukung di sana?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("&"); }
Sumber: http://code.google.com/p/form-serialize/source/browse/trunk/serialize-0.1.js
sumber
Ini adalah versi TibTibs 'yang sedikit dimodifikasi:
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, '+'); }
Bidang yang dinonaktifkan akan dibuang dan nama juga dikodekan URL. Penggantian ekspresi reguler dari% 20 karakter terjadi hanya sekali, sebelum mengembalikan string.
String kueri dalam bentuk yang identik dengan hasil dari metode $ .serialize () jQuery.
sumber
form.nodeName.toLowerCase() == "form"
alih-alihform.nodeName == "FORM"
Saya mulai dengan jawaban dari Johndave Decano.
Ini harus memperbaiki beberapa masalah yang disebutkan dalam membalas fungsinya.
Jenis tombol akan tetap diabaikan jika tidak memiliki nilai nama.
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); }
Beginilah cara saya saat ini menggunakan fungsi ini.
<form onsubmit="myAjax('http://example.com/services/email.php', 'POST', serialize(this, event))">
sumber
Jika Anda perlu mengirimkan formulir "myForm" menggunakan POST dalam format json, Anda dapat melakukan:
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) });
Baris kedua dikonversi dari array seperti:
[["firstProp", "firstValue"], ["secondProp", "secondValue"], ...and so on... ]
... menjadi objek biasa, seperti:
{"firstProp": "firstValue", "secondProp": "secondValue", ...and so on ... }
... ia melakukan konversi ini dengan meneruskan mapFn ke Array.from (). MapFn ini diterapkan ke setiap pasangan ["a", "b"] dan mengubahnya menjadi {"a": "b"} sehingga larik berisi banyak objek dengan hanya satu properti di masing-masing. MapFn menggunakan "destructuring" untuk mendapatkan nama dari bagian pertama dan kedua dari pasangan, dan juga menggunakan "ComputedPropertyName" ES6 untuk menyetel nama properti dalam objek yang dikembalikan oleh mapFn (inilah mengapa dikatakan "[ x]: sesuatu "bukan hanya" x: sesuatu ".
Semua objek properti tunggal ini kemudian dilewatkan ke dalam argumen fungsi Object.assign () yang menggabungkan semua objek properti tunggal menjadi satu objek yang memiliki semua properti.
Array.from (): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from
Penghancuran dalam parameter: https://simonsmith.io/destructuring-objects-as-function-parameters-in-es6/
Lebih lanjut tentang nama properti yang dihitung di sini: Variabel sebagai nama properti dalam literal objek JavaScript?
sumber
Bekerja di semua browser.
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>
sumber
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 ); }
Untuk menggunakan seperti ini:
var dataToSend = document.querySelector("form").serialize();
Saya harap saya telah membantu.
sumber
Jika Anda ingin membuat serial input pada sebuah acara. Inilah pendekatan JavaScript murni yang saya gunakan.
// serialize form var data = {}; var inputs = [].slice.call(e.target.getElementsByTagName('input')); inputs.forEach(input => { data[input.name] = input.value; });
Data akan menjadi objek JavaScript dari input.
sumber
Versi kode @ SimonSteinberger yang difaktorkan ulang menggunakan lebih sedikit variabel dan memanfaatkan kecepatan
forEach
loop (yang sedikit lebih cepat darifor
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, '+'); }
sumber
Saya mengubah jawaban TibTibs menjadi sesuatu yang lebih jelas untuk dibaca. Ini sedikit lebih panjang karena lebar 80 karakter dan beberapa komentar.
Selain itu, ini mengabaikan nama bidang kosong dan nilai kosong.
// 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); }
sumber
evt = evt || window.event || { target: null };
(seperti yang telah dilakukan edit) Intinya adalah untuk melewati acara yang memicu serialisasi, jika ada, seperti formulir "kirim" acara, atau "klik" tombol. Jika formulir memiliki beberapa tombol untuk pengiriman, Anda hanya ingin memperhitungkan nilai tombol yang memicu acara dan mengabaikan yang lain. Saya telah meretas contoh yang sangat mendasar dari perilaku ini di dump.bedmonds.net/serialize-jsIni dapat dilakukan dengan fungsi yang sangat sederhana sebagai berikut
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>
sumber
// 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);
sumber
Saya telah mengambil metode entries () formData dari jawaban @moison dan dari MDN dikatakan bahwa:
tetapi satu-satunya masalah adalah browser seluler (android dan safari tidak didukung) dan juga desktop IE dan Safari
tetapi pada dasarnya inilah pendekatan saya:
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' };
kodenya dapat ditemukan di sini
sumber
Menggunakan fungsi pengurangan JavaScript seharusnya melakukan trik untuk semua browser, termasuk 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; },[]);
Contoh langsung dibawah.
Tampilkan cuplikan kode
var _formId = document.getElementById('formId'), formData = Array.prototype.slice.call(_formId.elements).reduce(function(acc,cur,indx,arr){ var i,o = {type : cur.type, name : cur.name, value : cur.value}; 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; },[]); // view document.getElementById('formOutput').innerHTML = JSON.stringify(formData, null, 4);
<form id="formId"> <input type="text" name="texttype" value="some text"> <select> <option value="Opt 1">Opt 1</option> <option value="Opt 2" selected>Opt 2</option> <option value="Opt 3">Opt 3</option> </select> <input type="checkbox" name="checkboxtype" value="Checkbox 1" checked> Checkbox 1 <input type="checkbox" name="checkboxtype" value="Checkbox 2"> Checkbox 2 <input type="radio" name="radiotype" value="Radio Btn 1"> Radio Btn 1 <input type="radio" name="radiotype" value="Radio Btn 2" checked> Radio Btn 2 <select multiple> <option value="Multi 1" selected>Multi 1</option> <option value="Multi 2">Saab</option> <option value="Multi 3" selected>Multi 3</option> </select> </form> <pre><code id="formOutput"></code></pre>
sumber
Memperbaiki jawaban David Lemon.
Ini mengonversi data formulir ke JSON dan memungkinkan Anda menyetel formulir dari objek data.
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>
sumber
Saya harap ini akan berhasil
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; }
sumber
Berikut adalah pendekatan JavaScript murni:
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); }
sumber
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; }
sumber
Untuk tujuan debugging, ini mungkin membantu Anda:
function print_form_data(form) { const form_data = new FormData(form); for (const item of form_data.entries()) { console.log(item); } return false; }
sumber
Saya bisa saja gila tetapi saya menemukan jawaban ini sangat membengkak. Inilah solusi saya
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); }
sumber
select
, dsb