Martin
Martin

Reputation: 2673

Getting all form values by JavaScript

I have form:

<form onchange="allvaluestostring()">
    <select name="status">
         <option value="*">All</option>
         <option value="1">Active</option>
         <option value="0">Inactive</option>
    </select>
    <select name="size">
          <option value="*">All</option>
          <option value="small">Small</option>
          <option value="big">Big</option>
    </select>
</form>

And the onchange action of any input in form I need to get a JavaScript string, for example "status=1&size=big" for using in httprequest.

Does there exist something in JavaScript that will take all form values when one of form inputs will be changed?

I used <select name="status" onchange="showExporteditems(this.name,this.value)">, but this will take only one input value for using only "status=1", but I need on each onchage all values from all inputs for string like "status=1&size=big&...etc....".

Without using jQuery.

Upvotes: 15

Views: 52425

Answers (11)

Creativos Online App
Creativos Online App

Reputation: 32

If you want all elements with certain class (example: step1):

var dataform = new FormData;
 var elemSteps = document.querySelectorAll('#frm-checkout .step1');
 elemSteps.forEach(elemStep => {
     dataform.append(elemStep.getAttribute('name'), elemStep.value)
 });
  var params = new URLSearchParams(dataform);
 params = params.toString();

//to get all data
var form = document.getElementById('frm-checkout');
 var dataform = new FormData(form); 
  var params = new URLSearchParams(dataform);
 params = params.toString();

Upvotes: 0

Jonathan
Jonathan

Reputation: 4689

2023 Version

(Since we're naming years here lol)

function onSubmit(e: Event) {

  const form = new FormData(e.target as HTMLFormElement);
  const { name, email } = Object.fromEntries(form);

  // do something with data

}

Here is an example with the Record type assuming a key / value both of type string:

const { name } = Object.fromEntries(form) as Record<string, string>;

J

Upvotes: 0

jonschlinkert
jonschlinkert

Reputation: 11007

As of late 2022, there is a better way to do this now, and it's supported by all modern browsers. Use the FormData constructor.

tldr;

console.log(Object.fromEntries(new FormData(form)));
// or
console.log(Object.fromEntries(new FormData(e.target)));

Example

Here is a full example of how to use the FormData constructor to get data from a form. You can see a live example here.

<!DOCTYPE html>
<html>
  <head>
    <title>FormData Example</title>
    <meta charset="UTF-8" />
  </head>

  <body>
    <form id="form">
      <input type="text" name="a" value="foo" />
      <input type="text" name="b" value="bar" />
      <input type="text" name="c" value="baz" />
      <input type="checkbox" name="check" checked disabled />
      <button>Submit</button>
    </form>

    <script>
      const form = document.getElementById("form");

      form.addEventListener("submit", (e) => {
        // this is used only for this example, 
        // to prevent submission of the form
        // so you can inspect the data below
        e.preventDefault();

        // you can pass "form" or "e.target" to FormData
        console.log(Object.fromEntries(new FormData(e.target)));
        console.log(Object.fromEntries(new FormData(form)));
        // { a: "foo", b: "bar", c: "baz" }
      });
    </script>
  </body>
</html>

Upvotes: 3

Goddard
Goddard

Reputation: 3059

this would likely be used when you attach an event to the form itself. I use the 'submit' event. Then this refers to the form itself.

2022 version

const formData = new URLSearchParams(new FormData(this));

Upvotes: 6

Greggers
Greggers

Reputation: 151

Dave's answer (https://stackoverflow.com/a/65383511/2740403) is perfect, but you need to extend it a little to work for multiselects...

    function getPlainObjectFromFormElement(form) {
    const elements = form.elements; 
    return Object.keys(elements).reduce((obj, field) => { 
        if (isNaN(field)) {

            // NEW SECTION
            if(elements[field].classList.contains("multiselect") ){ 
                var selected = [];
                for (var option of elements[field].options){
                    if (option.selected) {
                        selected.push(option.value);
                    }
                }
                obj[field] = selected.toString(); 
            // END NEW SECTION

            }else{
                obj[field] = elements[field].value;
            }
        }
        return obj;
    }, {});
}

Upvotes: 0

Slawa
Slawa

Reputation: 1217

2021 version (TypeScript)

  const onSubmit = (e: any) => {
    e.preventDefault();
    const form = e.target as HTMLFormElement;
    const values = Object.fromEntries(
      Array.from(form.elements).map((x: Element) => {
        const input = x as HTMLInputElement;
        console.log(input);
        return [input.name ?? input.id, input.value];
      })
    );
    console.log(values);
  };

Upvotes: 1

dave008
dave008

Reputation: 442

I don't know if there is an easier wait to do this but this solution, using just ECMAScript, is working for me:

function getPlainObjectFromFormElement(form) {
    const elements = form.elements;
    return Object.keys(elements)
        .reduce((obj, field) => {
            if (isNaN(field)) {
                obj[field] = elements[field].value;
            }
            return obj;
        }, {});
}

document.querySelector("form").onsubmit = function (e) {
    alert(JSON.stringify(getPlainObjectFromFormElement(e.target)));
}

Upvotes: 2

Subhasis Das
Subhasis Das

Reputation: 334

I guess this would be a nice ECMAScript 6 vanilla JavaScript-based solution.

const form = document.getElementById("sampleForm");

form.addEventListener("submit", e => {
    e.preventDefault();
    let reqBody = {};
    Object.keys(form.elements).forEach(key => {
        let element = form.elements[key];
        if (element.type !== "submit") {
            reqBody[element.name] = element.value;
        }
    });
    submitForm(reqBody); // Call to function for form submission
});

Upvotes: 13

Shairon Toledo
Shairon Toledo

Reputation: 2124

For input fields you could use ECMAScript 6 like the following:

Get your form in a constant:

const form = document.querySelector('form')

Grab all values:

Object.values(form).reduce((obj,field) => { obj[field.name] = field.value; return obj }, {})

The above snippet will produce an object with the input name as the key and its value.

Upvotes: 31

Afzaal Ahmad Zeeshan
Afzaal Ahmad Zeeshan

Reputation: 15860

When you're using the method GET request type. You're already using the default method which would append the form data to the URL.

So, you'll get the select element's value appended along with the name.

However, if you want to dynamically change the URL. Then you can try it like:

function allvaluestostring() {
  var sts = document.getElementById("status").value;
  var size = document.getElementById("size").value;
  history.pushState("", "Title", "new_URL");
}

In the above statement, the values are stored in the variables and a history.pushState() method is called and it would change the string of the URL dynamically.

History API

Can I prevent history.popstate from triggering on initial page-load?

Upvotes: 0

Seth
Seth

Reputation: 10454

Here is a working fiddle in vanilla JavaScript, but you need to add a serialize utility function. This works exactly like $('form').serialize() in jQuery.

JavaScript:

var data;

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 '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;
        }
    }
    data = q.join("&");
}

And change your form onchange to

<form onchange="serialize(this)">

I tested it and am getting "size=small&status=0" in the console.

Upvotes: 16

Related Questions