Wondering is there a function in javascript without jquery or any framework that allows me to serialize the form and access the serialize version?
问题:
回答1:
This miniature library doesn\'t rely on a framework. Other than something like that, you\'ll need to implement the serialization function yourself. (though at a weight of 1.2 kilobytes, why not use it?)
回答2:
Here is pure JavaScript approach:
var form = document.querySelector(\'form\');
var data = new FormData(form);
var req = new XMLHttpRequest();
req.send(data);
Though it seems to be working only for POST requests.
https://developer.mozilla.org/en-US/docs/Web/API/FormData
回答3:
If you target browsers that support the URLSearchParams
API (all recent browsers), use this:
new URLSearchParams(new FormData(formElement)).toString()
Otherwise, use this one-liner (works everywhere except IE):
Array.from(new FormData(formElement), e => e.map(encodeURIComponent).join(\'=\')).join(\'&\')
回答4:
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(\"&\");
}
Source: http://code.google.com/p/form-serialize/source/browse/trunk/serialize-0.1.js
回答5:
Here\'s a slightly modified version of TibTibs\':
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, \'+\');
}
Disabled fields are discarded and names are also URL encoded. Regex replace of %20 characters takes place only once, before returning the string.
The query string is in identical form to the result from jQuery\'s $.serialize() method.
回答6:
I started with the answer from Johndave Decano.
This should fix a few of the issues mentioned in replies to his function.
- Replace %20 with a + symbol.
- Submit/Button types will only be submitted if they were clicked to submit the form.
- Reset buttons will be ignored.
- The code seemed redundant to me since it is doing essentially the same thing regardless of the field types. Not to mention incompatibility with HTML5 field types such as \'tel\' and \'email\', thus I removed most of the specifics with the switch statements.
Button types will still be ignored if they don\'t have a name value.
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);
}
This is how I am currently using this function.
<form onsubmit=\"myAjax(\'http://example.com/services/email.php\', \'POST\', serialize(this, event))\">
回答7:
If you need to submit form \"myForm\" using POST in json format you can do:
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)
});
The second line converts from an array like:
[[\"firstProp\", \"firstValue\"], [\"secondProp\", \"secondValue\"], ...and so on... ]
...into a regular object, like:
{\"firstProp\": \"firstValue\", \"secondProp\": \"secondValue\", ...and so on ... }
...it does this conversion by passing in a mapFn into Array.from(). This mapFn is applied to each [\"a\",\"b\"] pair and converts them into {\"a\": \"b\"} so that the array contains a lot of object with only one property in each. The mapFn is using \"destructuring\" to get names of the first and second parts of the pair, and it is also using an ES6 \"ComputedPropertyName\" to set the property name in the object returned by the mapFn (this is why is says \"[x]: something\" rather than just \"x: something\".
All of these single property objects are then passed into arguments of the Object.assign() function which merges all the single property objects into a single object that has all properties.
Array.from(): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from
Destructuring in parameters: https://simonsmith.io/destructuring-objects-as-function-parameters-in-es6/
More on computed property names here: Variable as the property name in a JavaScript object literal?
回答8:
A refactored version of @SimonSteinberger\'s code using less variables and taking advantage of the speed of forEach
loops (which are a bit faster than 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, \'+\');
}
回答9:
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 );
}
To use like this:
var dataToSend = document.querySelector(\"form\").serialize();
I hope I have helped.
回答10:
const inputs = document.querySelector(\"form\").elements;
const values = {};
for (let i = 0; i < inputs.length; i++) {
values[inputs[i].name] = inputs[i].value;
}
console.log(values);
console.log(JSON.stringify(values));
<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=\"msg\">Message:</label>
<textarea id=\"msg\" name=\"user_message\">Hello My Friend</textarea>
</div>
</form>
回答11:
If you are looking to serialize the inputs on an event. Here\'s a pure JavaScript approach I use.
// serialize form
var data = {};
var inputs = [].slice.call(e.target.getElementsByTagName(\'input\'));
inputs.forEach(input => {
data[input.name] = input.value;
});
Data will be a JavaScript object of the inputs.
回答12:
I refactored TibTibs answer into something that\'s much clearer to read. It is a bit longer because of the 80 character width and a few comments.
Additionally, it ignores blank field names and blank values.
// 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);
}
回答13:
// 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);
回答14:
I\'ve grabbed the entries() method of formData from @moison answer and from MDN it\'s said that :
The FormData.entries() method returns an iterator allowing to go through all key/value pairs contained in this object. The key of each pair is a USVString object; the value either a USVString, or a Blob.
but the only issue is that mobile browser (android and safari are not supported ) and IE and Safari desktop too
but basically here is my approach :
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\'
};
the code can be found here
回答15:
I could be crazy but I\'m finding these answers seriously bloated. Here\'s my solution
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);
}
回答16:
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;
}
回答17:
For debugging purposes this might help you:
function print_form_data(form) {
const form_data = new FormData(form);
for (const item of form_data.entries()) {
console.log(item);
}
return false;
}