Хотите знать, есть ли функция в javascript без jquery или какой-либо инфраструктуры, которая позволяет мне сериализовать форму и получить доступ к сериализованной версии?
Хотите знать, есть ли функция в javascript без jquery или какой-либо инфраструктуры, которая позволяет мне сериализовать форму и получить доступ к сериализованной версии?
Ответы:
Миниатюрная библиотека from-serialize не зависит от фреймворка. В остальном вам нужно реализовать функцию сериализации самостоятельно. (хотя при весе 1,2 килобайта, почему бы не использовать его?)
case 'email':
в раздел ввода кода
That's an error
Вот чистый подход JavaScript:
var form = document.querySelector('form');
var data = new FormData(form);
var req = new XMLHttpRequest();
req.send(data);
Хотя, похоже, он работает только для POST-запросов.
req.open("POST", "<your-url>");
до того, как в req.send(data);
противном случае у меня возникла ошибка InvalidStateError: XMLHttpRequest state must be OPENED.
в Firefox 66. Он должен работать с другими запросами, такими как PUT, если вы заменяете POST на PUT.
Если вы нацелены на браузеры, которые поддерживают URLSearchParams
API ( самые последние браузеры ) и FormData(formElement)
конструктор ( самые последние браузеры, кроме Edge ), используйте это:
new URLSearchParams(new FormData(formElement)).toString()
Для браузеров, которые поддерживают, URLSearchParams
но не FormData(formElement)
конструктор, используйте этот polyfill FormData и этот код (работает везде, кроме IE):
new URLSearchParams(Array.from(new FormData(formElement))).toString()
Для более старых браузеров (например, IE 10) используйте полифилл FormData , Array.from
полифилл при необходимости и этот код:
Array.from(
new FormData(formElement),
e => e.map(encodeURIComponent).join('=')
).join('&')
.toString()
действительно нужно?
URLSearchParams
, то да. Строковое преобразование также происходит неявно, если вы интерполируете или добавляете его в строку, и в этом случае явный toString
вызов не требуется.
new FormData(formElement)
, там еще не поддерживается?
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("&");
}
Источник: http://code.google.com/p/form-serialize/source/browse/trunk/serialize-0.1.js
Вот немного измененная версия 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, '+');
}
Отключенные поля отбрасываются, а имена также кодируются URL. Regex замена% 20 символов происходит только один раз, прежде чем вернуть строку.
Строка запроса имеет ту же форму, что и результат метода $ .serialize () jQuery.
form.nodeName.toLowerCase() == "form"
вместоform.nodeName == "FORM"
Я начал с ответа от Johndave Decano.
Это должно исправить некоторые из проблем, упомянутых в ответах на его функции.
Типы кнопок будут по-прежнему игнорироваться, если они не имеют значения имени.
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);
}
Вот как я сейчас использую эту функцию.
<form onsubmit="myAjax('http://example.com/services/email.php', 'POST', serialize(this, event))">
Если вам нужно отправить форму "myForm", используя POST в формате json, вы можете сделать:
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)
});
Вторая строка преобразует из массива, как:
[["firstProp", "firstValue"], ["secondProp", "secondValue"], ...and so on... ]
... в обычный объект, как:
{"firstProp": "firstValue", "secondProp": "secondValue", ...and so on ... }
... он выполняет это преобразование, передавая mapFn в Array.from (). Этот mapFn применяется к каждой паре ["a", "b"] и преобразует их в {"a": "b"}, так что массив содержит множество объектов с только одним свойством в каждой. MapFn использует «деструктурирование» для получения имен первой и второй частей пары, а также ES6 «ComputedPropertyName» для установки имени свойства в объекте, возвращаемом mapFn (поэтому и говорится «[ х]: что-то ", а не просто" х: что-то ".
Все эти объекты одного свойства затем передаются в аргументы функции Object.assign (), которая объединяет все объекты одного свойства в один объект, имеющий все свойства.
Array.from (): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from
Разрушение в параметрах: https://simonsmith.io/destructuring-objects-as-function-parameters-in-es6/
Подробнее об именах вычисляемых свойств здесь: Переменная как имя свойства в литерале объекта JavaScript?
Работает во всех браузерах.
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 );
}
Чтобы использовать как это:
var dataToSend = document.querySelector("form").serialize();
Я надеюсь, что помог.
Если вы хотите сериализовать входы для события. Вот чистый подход JavaScript, который я использую.
// serialize form
var data = {};
var inputs = [].slice.call(e.target.getElementsByTagName('input'));
inputs.forEach(input => {
data[input.name] = input.value;
});
Данные будут JavaScript-объектом ввода.
Реорганизованная версия кода @ SimonSteinberger, использующая меньше переменных и использующая преимущества скорости forEach
циклов (которые немного быстрее, чем 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, '+');
}
Я переработал ответ TibTibs в нечто, что намного понятнее для чтения. Это немного длиннее из-за ширины в 80 символов и нескольких комментариев.
Кроме того, он игнорирует пустые имена полей и пустые значения.
// 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 };
(как редактирование). Смысл в том, чтобы передать событие, которое вызвало сериализацию, если оно есть, такое как форма событие «отправить» или «нажатие» кнопки. Если форма имеет несколько кнопок для отправки, вам нужно учитывать только значение кнопки, которая вызвала событие, и игнорировать остальные. Я взломал очень простой
// 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);
Я взял метод entry () для formData из @moison answer и из MDN сказано, что:
Метод FormData.entries () возвращает итератор, позволяющий просмотреть все пары ключ / значение, содержащиеся в этом объекте. Ключ каждой пары является объектом USVString; значение либо USVString, либо Blob.
но единственная проблема заключается в том, что мобильный браузер (Android и Safari не поддерживаются), а также IE и Safari Desktop
но в основном вот мой подход:
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'
};
код можно найти здесь
Использование функции JavaScript JavaScript должно помочь всем браузерам, включая 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;
},[]);
Живой пример ниже.
Надеюсь это сработает
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;
}
Улучшение ответа Дэвида Лемона.
Это преобразует данные формы в JSON и позволяет вам установить форму из объекта данных.
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>
Это может быть сделано очень простой функцией следующим образом
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>
Вот чистый подход 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;
}
В целях отладки это может помочь вам:
function print_form_data(form) {
const form_data = new FormData(form);
for (const item of form_data.entries()) {
console.log(item);
}
return false;
}
Я могу быть сумасшедшим, но я нахожу эти ответы серьезно раздутыми. Вот мое решение
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
, и все