web-gelistirme-sc.com

form serileştirmek javascript (çerçeve yok)

Merak ediyorum, javascript'te jquery olmadan bir fonksiyon var mı ya da formu serileştirmeme ve serileştirilmiş sürüme erişmeme izin veren herhangi bir çerçeve var mı?

100
RussellHarrower

Minyatür seri hale getirme kütüphanesi bir çerçeveye güvenmiyor. Bunun gibi bir şeyin dışında serileştirme işlevini kendiniz uygulamanız gerekir. (1.2 kilobayt ağırlığında olsa da neden kullanmıyorsun?)

29
Lusitanian

İşte saf JavaScript yaklaşımı:

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

Yine de sadece POST istekleri için çalışıyor gibi görünüyor.

https://developer.mozilla.org/en-US/docs/Web/API/FormData

129
Artur Beljajev

URLSearchParams API ( en son tarayıcılar ) ve FormData(formElement) yapıcısını (Edge dışındaki son tarayıcılar) destekleyen tarayıcıları hedefliyorsanız, şunları kullanın:

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

URLSearchParams özelliğini destekleyen ancak FormData(formElement) yapıcısını desteklemeyen tarayıcılar için this FormData polyfill ve:

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

Daha eski tarayıcılar için (örneğin, IE 10), FormData polyfill , gerekirse bir Array.from polyfill ve bu tek astarı kullanın:

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

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

32
Johndave Decano

İşte TibTibs'in 'biraz değiştirilmiş bir versiyonu:

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, '+');
}

Devre dışı bırakılan alanlar atılır ve adlar ayrıca URL kodludur. % 20 karakterin regex yerine koyması, dizeyi döndürmeden önce yalnızca bir kez yapılır.

Sorgu dizesi, jQuery's $ .serialize () yönteminin sonucuyla aynı biçimdedir.

23

Johndave Decano'nun cevabıyla başladım.

Bu, işlevine verilen cevaplarda belirtilen sorunlardan birkaçını çözmelidir.

  1. % 20'yi bir + sembolüyle değiştirin.
  2. Gönder/Düğme türleri yalnızca, tıklatıldıysa gönderilir.
  3. Sıfırlama düğmeleri dikkate alınmayacaktır.
  4. Alan tiplerine bakılmaksızın, esasen Bahsetmiyorum bile.

Bir isim değeri yoksa, düğme tipleri hala göz ardı edilir.

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

Bu işlevi şu anda bu şekilde kullanıyorum.

<form onsubmit="myAjax('http://example.com/services/email.php', 'POST', serialize(this, event))">
10
TibTibs

Json formatında POST kullanarak "myForm" formunu göndermeniz gerekiyorsa, şunları yapabilirsiniz:

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

İkinci satır şöyle bir diziden dönüştürülür:

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

... normal bir nesneye, örneğin:

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

... bu dönüşümü bir mapFn dosyasında Array.from () dizinine ileterek yapar. Bu mapFn her ["a", "b"] çiftine uygulanır ve onları {"a": "b"} 'a dönüştürür, böylece dizi her birinde sadece bir özelliği olan çok fazla nesne içerir. MapFn, çiftin birinci ve ikinci bölümlerinin adlarını almak için "yıkımı" kullanıyor ve ayrıca mapFn tarafından döndürülen nesnede özellik adını ayarlamak için bir ES6 "ComputedPropertyName" kullanıyor (bu yüzden " x]: bir şey "sadece" x: bir şey "değil.

Bu tek özellik nesnelerinin tümü daha sonra, tüm tek özellik nesnelerini tüm özelliklere sahip tek bir nesneye birleştiren Object.assign () işlevinin argümanlarına geçirilir.

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

Parametrelerde yıkım: https://simonsmith.io/destructuring-objects-as-function-parameters-in-es6/

Burada hesaplanan özellik adları hakkında daha fazla bilgi: Bir JavaScript nesnesindeki özellik adı olarak değişebilir mi?

9
molsson

Tüm tarayıcılarda çalışır.

function 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 r = formSerialize(document.querySelector('form'));

console.log(r);
console.log(JSON.stringify(r));
<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="msg">Message:</label>
    <textarea id="msg" name="user_message">Hello My Friend</textarea>
  </div>
</form>

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

Bu şekilde kullanmak için:

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

Umarım yardım etmişimdir.

5
Eduardo Borges

@ SimonSteinberger'in kodunun daha az değişken kullanan ve forEach döngülerinin hızından yararlanan yeniden yapılandırılmış bir sürümü (fors öğesinden biraz daha hızlıdır)

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, '+');
}
5
Stefan Gabos

Bir olayla ilgili girişleri seri hale getirmek istiyorsanız. İşte kullandığım saf bir JavaScript yaklaşımı.

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

Veri, girişlerin bir JavaScript nesnesi olacaktır.

4
CAOakley

Yeniden canlandırarak TibTib'lerin okuması daha net bir şeye cevap verdim. 80 karakter genişliği ve birkaç yorum nedeniyle biraz daha uzun.

Ayrıca, boş alan adlarını ve boş değerleri yok sayar.

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

@Moison answer ve MDN adresinden formData'nin () form yöntemini yakaladım:

FormData.entries () yöntemi, gitmesine izin veren bir yineleyici döndürür. Bu nesnede bulunan tüm anahtar/değer çiftleri aracılığıyla. Her birinin anahtarı. çifti bir USVString nesnesidir; değer bir USVString veya bir Blob.

ancak tek sorun mobil tarayıcı (Android ve safari desteklenmiyor) ve IE ve Safari masaüstünün de olmasıdır. 

ama temelde burada benim yaklaşımım:

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'

};

kod bulunabilir burada

1
Espoir Murhabazi
  // 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);
1
Onome Mine Adamu

JavaScript azaltma işlevini kullanmak, IE9> dahil olmak üzere tüm tarayıcılar için bir numara yapmalıdır:

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;} // if input is checkbox or radio type
        acc.Push(o);
        return acc;
 },[]);

Canlı örnek feryat.

var _formId = document.getElementById('formId'),
    formData = Array.prototype.slice.call(_formId.elements).reduce(function(acc,cur,indx,arr){
        var o = {type : cur.type, name : cur.name, value : cur.value};
            if(['checkbox','radio'].indexOf(cur.type) !==-1){o.checked = cur.checked;}
            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
</form>
<pre><code id="formOutput"></code></pre>
0
crashtestxxx

Delirebilirim ama bu cevapları ciddi şekilde şişirilmiş buluyorum. İşte benim çözümüm

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

Umarım bu işe yarar

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;
}
0
Manoj Rana
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;
}
0
Hasan

Hata ayıklama amacıyla bu size yardımcı olabilir:

function print_form_data(form) {
    const form_data = new FormData(form);

    for (const item of form_data.entries()) {
        console.log(item);
    }

    return false;
}
0
tobias47n9e