formulário serializar javascript (sem framework)

Imaginando se existe uma function em javascript sem jquery ou qualquer framework que me permita serializar o formulário e acessar a versão serializada?

Esta biblioteca em miniatura não depende de um framework. Além de algo assim, você precisará implementar a function de serialização por conta própria. (embora com um peso de 1,2 kilobytes, por que não usá-lo?)

Aqui está a abordagem JavaScript pura:

 var form = document.querySelector('form'); var data = new FormData(form); var req = new XMLHttpRequest(); req.send(data); 

Embora pareça estar funcionando apenas para solicitações POST.

https://developer.mozilla.org/pt-BR/docs/Web/API/FormData

Se você segmentar navegadores que suportam a API URLSearchParams ( todos os navegadores recentes ), use isto:

 new URLSearchParams(new FormData(formElement)).toString() 

Caso contrário, use este one-liner (funciona em todos os lugares, exceto no IE):

 Array.from(new FormData(formElement), e => e.map(encodeURIComponent).join('=')).join('&') 
 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("&"); } 

Fonte: http://code.google.com/p/form-serialize/source/browse/trunk/serialize-0.1.js

Aqui está uma versão ligeiramente modificada do TibTibs ‘:

 function serialize(form) { var field, s = []; if (typeof form == 'object' && form.nodeName == "FORM") { var len = form.elements.length; for (i=0; i=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, '+'); } 

Os campos desativados são descartados e os nomes também são codificados por URL. A substituição regex de% 20 caracteres ocorre apenas uma vez, antes de retornar a string.

A string de consulta é de forma idêntica ao resultado do método $ .serialize () do jQuery.

Comecei com a resposta de Johndave Decano.

Isso deve corrigir alguns dos problemas mencionados nas respostas à sua function.

  1. Substitua% 20 por um símbolo +.
  2. Os tipos de envio / botão só serão enviados se forem clicados para enviar o formulário.
  3. Botões de reset serão ignorados.
  4. O código parecia redundante para mim, pois está fazendo essencialmente a mesma coisa, independentemente dos tipos de campo. Sem mencionar a incompatibilidade com os tipos de campo HTML5, como ‘tel’ e ’email’, assim removi a maioria dos detalhes com as instruções switch.

Os tipos de botão ainda serão ignorados se não tiverem um valor de nome.

 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); } 

É assim que estou usando essa function no momento.

 

Se você precisar enviar o formulário “myForm” usando POST no formato json, você pode fazer:

 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) }); 

A segunda linha converte de uma matriz como:

 [["firstProp", "firstValue"], ["secondProp", "secondValue"], ...and so on... ] 

… em um object regular, como:

 {"firstProp": "firstValue", "secondProp": "secondValue", ...and so on ... } 

… faz esta conversão passando em um mapFn em Array.from (). Este mapFn é aplicado a cada par [“a”, “b”] e os converte em {“a”: “b”} para que o array contenha muitos objects com apenas uma propriedade em cada. O mapFn está usando “desestruturação” para obter nomes da primeira e segunda partes do par, e também está usando um ES6 “ComputedPropertyName” para definir o nome da propriedade no object retornado pelo mapFn (é por isso que se diz “[ x]: alguma coisa “em vez de apenas” x: alguma coisa “.

Todos esses objects de propriedade única são passados ​​para os argumentos da function Object.assign () que mescla todos os objects de propriedade única em um único object que possui todas as propriedades.

Array.from (): https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Array/from

Destructuring em parâmetros: https://simonsmith.io/destructuring-objects-as-function-parameters-in-es6/

Mais sobre nomes de propriedades calculadas aqui: Variável como o nome da propriedade em um literal de object JavaScript?

Uma versão refatorada do código do @ SimonSteinberger usando menos variables ​​e aproveitando a velocidade dos loops forEach (que são um pouco mais rápidos do que 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, '+'); } 
 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 ); } 

Para usar assim:

 var dataToSend = document.querySelector("form").serialize(); 

Espero ter ajudado.

Se você estiver procurando serializar as inputs em um evento. Aqui está uma abordagem JavaScript pura que eu uso.

 // serialize form var data = {}; var inputs = [].slice.call(e.target.getElementsByTagName('input')); inputs.forEach(input => { data[input.name] = input.value; }); 

Os dados serão um object JavaScript das inputs.

Eu refatorei TibTibs em algo muito mais claro para ler. É um pouco mais longo por causa da largura de 80 caracteres e alguns comentários.

Além disso, ele ignora nomes de campo em branco e valores em branco.

 // 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); } 
  // 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); 

Eu peguei o método entries () de formData da resposta do @moison e do MDN ele disse:

O método FormData.entries () retorna um iterador que permite passar por todos os pares chave / valor contidos neste object. A chave de cada par é um object USVString; o valor ou um USVString ou um Blob.

mas o único problema é que o navegador móvel (android e safari não são suportados) e o IE e o Safari também

mas basicamente aqui está minha abordagem:

 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' }; 

o código pode ser encontrado aqui

 var inputs = document.querySelector("form").elements; var values = {}; for (i = 0; i < inputs.length; i++) { values[inputs[i].name] = inputs[i].value; } console.log(values); console.log(JSON.stringify(values)); 
 
 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; } 

Para fins de debugging, isso pode ajudá-lo:

 function print_form_data(form) { const form_data = new FormData(form); for (const item of form_data.entries()) { console.log(item); } return false; }