form serialize javascript (no framework)

后端 未结 23 1385
一生所求
一生所求 2020-11-22 16:07

Wondering is there a function in javascript without jquery or any framework that allows me to serialize the form and access the serialized version?

相关标签:
23条回答
  • 2020-11-22 16:41

    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);
    }
    
    0 讨论(0)
  • 2020-11-22 16:41

    This could be done by very simple function as follows

    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>

    0 讨论(0)
  • 2020-11-22 16:43

    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

    0 讨论(0)
  • 2020-11-22 16:44

    Improving upon David Lemon's answer.

    This converts form data to JSON and allows you to set the form from a data object.

    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>

    0 讨论(0)
  • 2020-11-22 16:45
      // 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);
    
    0 讨论(0)
  • 2020-11-22 16:46

    Using JavaScript reduce function should do a trick for all browsers, including 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;
     },[]);
    

    Live example bellow.

    var _formId = document.getElementById('formId'),
        formData = Array.prototype.slice.call(_formId.elements).reduce(function(acc,cur,indx,arr){
            var i,o = {type : cur.type, name : cur.name, value : cur.value};
            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;
        },[]);
    
    // 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
        <select multiple>
            <option value="Multi 1" selected>Multi 1</option>
            <option value="Multi 2">Saab</option>
            <option value="Multi 3" selected>Multi 3</option>
        </select>
    </form>
    <pre><code id="formOutput"></code></pre>

    0 讨论(0)
提交回复
热议问题