Reputation: 2673
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
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
Reputation: 4689
(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
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
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
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
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
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
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
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
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.
Can I prevent history.popstate from triggering on initial page-load?
Upvotes: 0
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