Tự hỏi có một chức năng trong javascript mà không có jquery hoặc bất kỳ khung nào cho phép tôi tuần tự hóa biểu mẫu và truy cập phiên bản nối tiếp không?
Tự hỏi có một chức năng trong javascript mà không có jquery hoặc bất kỳ khung nào cho phép tôi tuần tự hóa biểu mẫu và truy cập phiên bản nối tiếp không?
Câu trả lời:
Thư viện thu nhỏ nối tiếp không dựa vào khung. Khác với những thứ tương tự, bạn sẽ cần phải tự thực hiện chức năng tuần tự hóa. (mặc dù với trọng lượng 1,2 kilobyte, tại sao không sử dụng nó?)
case 'email':
phần trong phần đầu vào của mã
That's an error
Đây là cách tiếp cận JavaScript thuần túy:
var form = document.querySelector('form');
var data = new FormData(form);
var req = new XMLHttpRequest();
req.send(data);
Mặc dù nó dường như chỉ hoạt động cho các yêu cầu POST.
req.open("POST", "<your-url>");
trước khi req.send(data);
khác Nếu tôi gặp lỗi InvalidStateError: XMLHttpRequest state must be OPENED.
trên Firefox 66. Nó cũng hoạt động với các yêu cầu khác giống như PUT là bạn thay thế POST bằng PUT.
Nếu bạn nhắm mục tiêu các trình duyệt hỗ trợ URLSearchParams
API ( hầu hết các trình duyệt gần đây ) và hàm FormData(formElement)
tạo ( hầu hết các trình duyệt gần đây trừ Edge ), hãy sử dụng:
new URLSearchParams(new FormData(formElement)).toString()
Đối với các trình duyệt hỗ trợ URLSearchParams
nhưng không phải là hàm FormData(formElement)
tạo, hãy sử dụng polyfill FormData này và mã này (hoạt động ở mọi nơi trừ IE):
new URLSearchParams(Array.from(new FormData(formElement))).toString()
Đối với các trình duyệt cũ hơn (ví dụ IE 10), hãy sử dụng polyfill FormData , một Array.from
polyfill nếu cần thiết và mã này:
Array.from(
new FormData(formElement),
e => e.map(encodeURIComponent).join('=')
).join('&')
.toString()
thực sự cần thiết ở đây?
URLSearchParams
, thì có. Chuyển đổi chuỗi cũng xảy ra ngầm nếu bạn nội suy hoặc thêm nó vào chuỗi, trong trường hợp đó, toString
cuộc gọi rõ ràng là không cần thiết.
new FormData(formElement)
chưa được hỗ trợ ở đó?
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("&");
}
Nguồn: http://code.google.com.vn/p/form-serialize/source/browse/trunk/serialize-0.1.js
Đây là một phiên bản sửa đổi một chút của 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, '+');
}
Các trường bị vô hiệu hóa bị loại bỏ và tên cũng được mã hóa URL. Regex thay thế% 20 ký tự chỉ diễn ra một lần, trước khi trả về chuỗi.
Chuỗi truy vấn có dạng giống hệt với kết quả từ phương thức $ .serialize () của jQuery.
form.nodeName.toLowerCase() == "form"
thay vìform.nodeName == "FORM"
Tôi bắt đầu với câu trả lời từ Johndave Decano.
Điều này sẽ khắc phục một số vấn đề được đề cập trong trả lời cho chức năng của mình.
Các loại nút sẽ vẫn bị bỏ qua nếu chúng không có giá trị tên.
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);
}
Đây là cách tôi hiện đang sử dụng chức năng này.
<form onsubmit="myAjax('http://example.com/services/email.php', 'POST', serialize(this, event))">
Nếu bạn cần gửi biểu mẫu "myForm" bằng POST ở định dạng json, bạn có thể làm:
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)
});
Dòng thứ hai chuyển đổi từ một mảng như:
[["firstProp", "firstValue"], ["secondProp", "secondValue"], ...and so on... ]
... thành một đối tượng thông thường, như:
{"firstProp": "firstValue", "secondProp": "secondValue", ...and so on ... }
... nó thực hiện chuyển đổi này bằng cách chuyển một mapFn vào Array.from (). MapFn này được áp dụng cho từng cặp ["a", "b"] và chuyển đổi chúng thành {"a": "b"} để mảng chứa nhiều đối tượng chỉ có một thuộc tính. MapFn đang sử dụng "phá hủy" để lấy tên của phần thứ nhất và thứ hai của cặp và nó cũng đang sử dụng "ComputingPropertyName" của ES6 để đặt tên thuộc tính trong đối tượng được mapFn trả về (đây là lý do tại sao nói "[ x]: một cái gì đó "chứ không chỉ là" x: một cái gì đó ".
Tất cả các đối tượng thuộc tính đơn lẻ này sau đó được chuyển vào các đối số của hàm Object.assign () để hợp nhất tất cả các đối tượng thuộc tính đơn lẻ thành một đối tượng có tất cả các thuộc tính.
Array.from (): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from
Sự phá hủy trong các tham số: https://simonsmith.io/desturationuring-objects-as-feft-parameter-in-es6/
Thông tin thêm về tên thuộc tính được tính ở đây: Biến là tên thuộc tính trong một đối tượng JavaScript theo nghĩa đen?
Hoạt động trong tất cả các trình duyệt.
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 );
}
Để sử dụng như thế này:
var dataToSend = document.querySelector("form").serialize();
Tôi hy vọng tôi đã giúp.
Nếu bạn đang tìm cách nối tiếp các đầu vào trong một sự kiện. Đây là một cách tiếp cận JavaScript thuần túy mà tôi sử dụng.
// serialize form
var data = {};
var inputs = [].slice.call(e.target.getElementsByTagName('input'));
inputs.forEach(input => {
data[input.name] = input.value;
});
Dữ liệu sẽ là một đối tượng JavaScript của các đầu vào.
Một phiên bản được tái cấu trúc của mã @ SimonSteinberger sử dụng ít biến số hơn và tận dụng tốc độ của forEach
các vòng lặp (nhanh hơn một chút so với 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, '+');
}
Tôi đã tái cấu trúc câu trả lời của TibTib thành một thứ rõ ràng hơn để đọc. Nó dài hơn một chút vì độ rộng 80 ký tự và một vài bình luận.
Ngoài ra, nó bỏ qua tên trường trống và giá trị trống.
// 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 };
(như đã chỉnh sửa) Điểm đằng sau nó là để vượt qua sự kiện kích hoạt tuần tự hóa, nếu có một, chẳng hạn như một biểu mẫu Sự kiện "gửi" hoặc "nhấp chuột" của nút. Nếu một biểu mẫu có nhiều nút để gửi, bạn chỉ muốn tính đến giá trị của nút đã kích hoạt sự kiện và bỏ qua các nút khác. Tôi đã hack cùng một ví dụ rất thô sơ về hành vi này trên dump.bedmonds.net/serialize-js
// 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);
Tôi đã nắm được phương thức entry () của formData từ câu trả lời @moison và từ MDN, nó nói rằng:
Phương thức FormData.entries () trả về một trình vòng lặp cho phép đi qua tất cả các cặp khóa / giá trị có trong đối tượng này. Khóa của mỗi cặp là một đối tượng USVString; giá trị là USVString hoặc Blob.
nhưng vấn đề duy nhất là trình duyệt di động (android và safari không được hỗ trợ) và cả máy tính để bàn IE và Safari
nhưng về cơ bản đây là cách tiếp cận của tôi:
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'
};
mã có thể được tìm thấy ở đây
Sử dụng chức năng giảm JavaScript sẽ thực hiện một mẹo cho tất cả các trình duyệt, bao gồm 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;
},[]);
Sống ví dụ dưới đây.
Tôi hy vọng điều này sẽ làm việc
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;
}
Cải thiện câu trả lời của David Lemon.
Điều này chuyển đổi dữ liệu biểu mẫu thành JSON và cho phép bạn đặt biểu mẫu từ một đối tượng dữ liệu.
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>
Điều này có thể được thực hiện bởi chức năng rất đơn giản như sau
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>
Đây là cách tiếp cận JavaScript thuần túy:
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;
}
Đối với mục đích gỡ lỗi, điều này có thể giúp bạn:
function print_form_data(form) {
const form_data = new FormData(form);
for (const item of form_data.entries()) {
console.log(item);
}
return false;
}
Tôi có thể bị điên nhưng tôi thấy những câu trả lời này thực sự nghiêm trọng. Đây là giải pháp của tôi
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
, et all