使用 FormData 从表单到对象数组
Form to Array of Object using FormData
我正在开发一个用户可以添加或删除朋友信息的表单。
我当前的代码如下所示:
(() => {
let currentCount = 0;
const theForm = document.querySelector("#theForm");
document
.querySelector("#addMoreFields")
.addEventListener("click", (event) => {
event.preventDefault();
// find and clone the template content
const template = theForm.getElementsByTagName("template")[0];
const clone = template.content.cloneNode(true);
const submitButton = document.querySelector("#submitForm");
// if the submitButton is hidden, show it
if (submitButton.offsetParent === null) {
submitButton.removeAttribute("style");
}
// add class to set and name on input fields
clone.querySelector(".set").classList.add(`set-${currentCount}`);
clone
.querySelector(".first_name")
.setAttribute("name", `firstName[${currentCount}]`);
clone
.querySelector(".middle_name")
.setAttribute("name", `middleName[${currentCount}]`);
clone
.querySelector(".last_name")
.setAttribute("name", `lastName[${currentCount}]`);
clone.querySelectorAll(".checkbox").forEach(function (item) {
item.setAttribute("name", `checkbox[${currentCount}]`);
});
clone.querySelectorAll(".radio").forEach(function (item) {
item.setAttribute("name", `radio[${currentCount}]`);
});
// remove button
clone
.querySelector(".removeSet")
.setAttribute("id", `remove-${currentCount}`);
clone
.querySelector(".removeSet")
.setAttribute("data-number", currentCount);
theForm.append(clone);
// add event listener to removeSet button
document
.querySelector(`#remove-${currentCount}`)
.addEventListener("click", (event) => {
event.preventDefault();
const setName = `.set-${event.target.getAttribute("data-number")}`;
document.querySelector(setName).remove();
});
currentCount++;
});
theForm.addEventListener("submit", (event) => {
event.preventDefault();
const theFormData = new FormData(theForm);
/*
we need to format the form as:
```
[
{
"first_name": "x",
"middle_name": "x",
"last_name": "x",
"checkbox": ['checkbox a', 'checkbox c'],
"radio": "radio b",
"textarea": "some text"
},
{
"first_name": "y",
"middle_name": "y",
"last_name": "y",
"checkbox": ['checkbox a', 'checkbox c'],
"radio": "radio b",
"textarea": "some text"
},
...
]
```
*/
});
})();
.set {
margin: 5px;
padding: 5px;
outline: 1px solid #ccc;
}
.removeSet {
float: right;
}
<form id="theForm">
<template>
<div class="set">
<button class="removeSet">remove</button>
<input class="first_name" placeholder="first name" /><br>
<input class="middle_name" placeholder="middle name" /><br>
<input class="last_name" placeholder="last name" /><br>
<!-- checkbox -->
<label><input type="checkbox" class="checkbox" value="checkbox a" />checkbox a</label>
<label><input type="checkbox" class="checkbox" value="checkbox b" />checkbox b</label>
<label><input type="checkbox" class="checkbox" value="checkbox c" />checkbox c</label><br>
<!-- radio -->
<label><input type="radio" class="radio" value="radio a" />radio a</label>
<label><input type="radio" class="radio" value="radio b" />radio b</label>
<label><input type="radio" class="radio" value="radio c" />radio c</label><br>
<!-- textarea -->
<textarea class="textarea" rows="4" cols="50">additional notes</textarea>
</div>
</template>
<button id="addMoreFields">add</button>
<button id="submitForm" style="display: none;">submit</button>
</form>
我的问题是,如何创建一个对象数组以发送到后端,格式如下:
[
{
"first_name": "x",
"middle_name": "x",
"last_name": "x",
"checkbox": ['checkbox a', 'checkbox c'],
"radio": "radio b",
"textarea": "some text"
},
{
"first_name": "x",
"middle_name": "x",
"last_name": "x",
"checkbox": ['checkbox a', 'checkbox c'],
"radio": "radio b",
"textarea": "some text"
},
...
]
我正在使用 new FormData
,但我愿意接受其他选择。
我们只使用 vanilla javascript 所以 jQuery 不是一个选项
这就是我解决问题的方法。
我添加了注释以使其易于理解。 ✌
(() => {
let currentCount = 0;
const theForm = document.querySelector("#theForm");
document
.querySelector("#addMoreFields")
.addEventListener("click", (event) => {
event.preventDefault();
// find and clone the template content
const template = theForm.getElementsByTagName("template")[0];
const clone = template.content.cloneNode(true);
const submitButton = document.querySelector("#submitForm");
// if the submitButton is hidden, show it
if (submitButton.offsetParent === null) {
submitButton.removeAttribute("style");
}
// add class to set and name on input fields
clone.querySelector(".set").classList.add(`set-${currentCount}`);
clone
.querySelector(".first_name")
.setAttribute("name", `firstName[${currentCount}]`);
clone
.querySelector(".middle_name")
.setAttribute("name", `middleName[${currentCount}]`);
clone
.querySelector(".last_name")
.setAttribute("name", `lastName[${currentCount}]`);
clone.querySelectorAll(".checkbox").forEach(function (item) {
item.setAttribute("name", `checkbox[${currentCount}]`);
});
clone.querySelectorAll(".radio").forEach(function (item) {
item.setAttribute("name", `radio[${currentCount}]`);
});
clone
.querySelector(".textarea")
.setAttribute("name", `textarea[${currentCount}]`);
// remove button
clone
.querySelector(".removeSet")
.setAttribute("id", `remove-${currentCount}`);
clone
.querySelector(".removeSet")
.setAttribute("data-number", currentCount);
theForm.append(clone);
// add event listener to removeSet button
document
.querySelector(`#remove-${currentCount}`)
.addEventListener("click", (event) => {
event.preventDefault();
const setName = `.set-${event.target.getAttribute("data-number")}`;
document.querySelector(setName).remove();
});
currentCount++;
});
theForm.addEventListener("submit", (event) => {
event.preventDefault();
const theArray = [];
const theFormData = new FormData(theForm);
// cycle through FormData keys
for(const [key, value] of theFormData.entries()) {
if (!value) {
// do validation here
return;
}
// get the key number
const keyNumber = key.match(/\d/g).join('');
// assign the object to theArray variable
theArray[keyNumber] = {
'first_name': theFormData.get(`firstName[${keyNumber}]`),
'middle_name': theFormData.get(`middleName[${keyNumber}]`),
'last_name': theFormData.get(`lastName[${keyNumber}]`),
'checkbox': theFormData.getAll(`checkbox[${keyNumber}]`),
'radio': theFormData.get(`radio[${keyNumber}]`),
'textarea': theFormData.get(`textarea[${keyNumber}]`)
}
}
// clean theArray before sending to the back-end
const filteredArray = theArray.filter(Boolean);
console.log(filteredArray);
});
})();
.set {
margin: 5px;
padding: 5px;
outline: 1px solid #ccc;
}
.removeSet {
float: right;
}
<form id="theForm">
<template>
<div class="set">
<button class="removeSet">remove</button>
<input class="first_name" placeholder="first name" /><br>
<input class="middle_name" placeholder="middle name" /><br>
<input class="last_name" placeholder="last name" /><br>
<!-- checkbox -->
<label><input type="checkbox" class="checkbox" value="checkbox a" />checkbox a</label>
<label><input type="checkbox" class="checkbox" value="checkbox b" />checkbox b</label>
<label><input type="checkbox" class="checkbox" value="checkbox c" />checkbox c</label><br>
<!-- radio -->
<label><input type="radio" class="radio" value="radio a" />radio a</label>
<label><input type="radio" class="radio" value="radio b" />radio b</label>
<label><input type="radio" class="radio" value="radio c" />radio c</label><br>
<!-- textarea -->
<textarea class="textarea" rows="4" cols="50">additional notes</textarea>
</div>
</template>
<button id="addMoreFields">add</button>
<button id="submitForm" style="display: none;">submit</button>
</form>
我正在开发一个用户可以添加或删除朋友信息的表单。
我当前的代码如下所示:
(() => {
let currentCount = 0;
const theForm = document.querySelector("#theForm");
document
.querySelector("#addMoreFields")
.addEventListener("click", (event) => {
event.preventDefault();
// find and clone the template content
const template = theForm.getElementsByTagName("template")[0];
const clone = template.content.cloneNode(true);
const submitButton = document.querySelector("#submitForm");
// if the submitButton is hidden, show it
if (submitButton.offsetParent === null) {
submitButton.removeAttribute("style");
}
// add class to set and name on input fields
clone.querySelector(".set").classList.add(`set-${currentCount}`);
clone
.querySelector(".first_name")
.setAttribute("name", `firstName[${currentCount}]`);
clone
.querySelector(".middle_name")
.setAttribute("name", `middleName[${currentCount}]`);
clone
.querySelector(".last_name")
.setAttribute("name", `lastName[${currentCount}]`);
clone.querySelectorAll(".checkbox").forEach(function (item) {
item.setAttribute("name", `checkbox[${currentCount}]`);
});
clone.querySelectorAll(".radio").forEach(function (item) {
item.setAttribute("name", `radio[${currentCount}]`);
});
// remove button
clone
.querySelector(".removeSet")
.setAttribute("id", `remove-${currentCount}`);
clone
.querySelector(".removeSet")
.setAttribute("data-number", currentCount);
theForm.append(clone);
// add event listener to removeSet button
document
.querySelector(`#remove-${currentCount}`)
.addEventListener("click", (event) => {
event.preventDefault();
const setName = `.set-${event.target.getAttribute("data-number")}`;
document.querySelector(setName).remove();
});
currentCount++;
});
theForm.addEventListener("submit", (event) => {
event.preventDefault();
const theFormData = new FormData(theForm);
/*
we need to format the form as:
```
[
{
"first_name": "x",
"middle_name": "x",
"last_name": "x",
"checkbox": ['checkbox a', 'checkbox c'],
"radio": "radio b",
"textarea": "some text"
},
{
"first_name": "y",
"middle_name": "y",
"last_name": "y",
"checkbox": ['checkbox a', 'checkbox c'],
"radio": "radio b",
"textarea": "some text"
},
...
]
```
*/
});
})();
.set {
margin: 5px;
padding: 5px;
outline: 1px solid #ccc;
}
.removeSet {
float: right;
}
<form id="theForm">
<template>
<div class="set">
<button class="removeSet">remove</button>
<input class="first_name" placeholder="first name" /><br>
<input class="middle_name" placeholder="middle name" /><br>
<input class="last_name" placeholder="last name" /><br>
<!-- checkbox -->
<label><input type="checkbox" class="checkbox" value="checkbox a" />checkbox a</label>
<label><input type="checkbox" class="checkbox" value="checkbox b" />checkbox b</label>
<label><input type="checkbox" class="checkbox" value="checkbox c" />checkbox c</label><br>
<!-- radio -->
<label><input type="radio" class="radio" value="radio a" />radio a</label>
<label><input type="radio" class="radio" value="radio b" />radio b</label>
<label><input type="radio" class="radio" value="radio c" />radio c</label><br>
<!-- textarea -->
<textarea class="textarea" rows="4" cols="50">additional notes</textarea>
</div>
</template>
<button id="addMoreFields">add</button>
<button id="submitForm" style="display: none;">submit</button>
</form>
我的问题是,如何创建一个对象数组以发送到后端,格式如下:
[
{
"first_name": "x",
"middle_name": "x",
"last_name": "x",
"checkbox": ['checkbox a', 'checkbox c'],
"radio": "radio b",
"textarea": "some text"
},
{
"first_name": "x",
"middle_name": "x",
"last_name": "x",
"checkbox": ['checkbox a', 'checkbox c'],
"radio": "radio b",
"textarea": "some text"
},
...
]
我正在使用 new FormData
,但我愿意接受其他选择。
我们只使用 vanilla javascript 所以 jQuery 不是一个选项
这就是我解决问题的方法。
我添加了注释以使其易于理解。 ✌
(() => {
let currentCount = 0;
const theForm = document.querySelector("#theForm");
document
.querySelector("#addMoreFields")
.addEventListener("click", (event) => {
event.preventDefault();
// find and clone the template content
const template = theForm.getElementsByTagName("template")[0];
const clone = template.content.cloneNode(true);
const submitButton = document.querySelector("#submitForm");
// if the submitButton is hidden, show it
if (submitButton.offsetParent === null) {
submitButton.removeAttribute("style");
}
// add class to set and name on input fields
clone.querySelector(".set").classList.add(`set-${currentCount}`);
clone
.querySelector(".first_name")
.setAttribute("name", `firstName[${currentCount}]`);
clone
.querySelector(".middle_name")
.setAttribute("name", `middleName[${currentCount}]`);
clone
.querySelector(".last_name")
.setAttribute("name", `lastName[${currentCount}]`);
clone.querySelectorAll(".checkbox").forEach(function (item) {
item.setAttribute("name", `checkbox[${currentCount}]`);
});
clone.querySelectorAll(".radio").forEach(function (item) {
item.setAttribute("name", `radio[${currentCount}]`);
});
clone
.querySelector(".textarea")
.setAttribute("name", `textarea[${currentCount}]`);
// remove button
clone
.querySelector(".removeSet")
.setAttribute("id", `remove-${currentCount}`);
clone
.querySelector(".removeSet")
.setAttribute("data-number", currentCount);
theForm.append(clone);
// add event listener to removeSet button
document
.querySelector(`#remove-${currentCount}`)
.addEventListener("click", (event) => {
event.preventDefault();
const setName = `.set-${event.target.getAttribute("data-number")}`;
document.querySelector(setName).remove();
});
currentCount++;
});
theForm.addEventListener("submit", (event) => {
event.preventDefault();
const theArray = [];
const theFormData = new FormData(theForm);
// cycle through FormData keys
for(const [key, value] of theFormData.entries()) {
if (!value) {
// do validation here
return;
}
// get the key number
const keyNumber = key.match(/\d/g).join('');
// assign the object to theArray variable
theArray[keyNumber] = {
'first_name': theFormData.get(`firstName[${keyNumber}]`),
'middle_name': theFormData.get(`middleName[${keyNumber}]`),
'last_name': theFormData.get(`lastName[${keyNumber}]`),
'checkbox': theFormData.getAll(`checkbox[${keyNumber}]`),
'radio': theFormData.get(`radio[${keyNumber}]`),
'textarea': theFormData.get(`textarea[${keyNumber}]`)
}
}
// clean theArray before sending to the back-end
const filteredArray = theArray.filter(Boolean);
console.log(filteredArray);
});
})();
.set {
margin: 5px;
padding: 5px;
outline: 1px solid #ccc;
}
.removeSet {
float: right;
}
<form id="theForm">
<template>
<div class="set">
<button class="removeSet">remove</button>
<input class="first_name" placeholder="first name" /><br>
<input class="middle_name" placeholder="middle name" /><br>
<input class="last_name" placeholder="last name" /><br>
<!-- checkbox -->
<label><input type="checkbox" class="checkbox" value="checkbox a" />checkbox a</label>
<label><input type="checkbox" class="checkbox" value="checkbox b" />checkbox b</label>
<label><input type="checkbox" class="checkbox" value="checkbox c" />checkbox c</label><br>
<!-- radio -->
<label><input type="radio" class="radio" value="radio a" />radio a</label>
<label><input type="radio" class="radio" value="radio b" />radio b</label>
<label><input type="radio" class="radio" value="radio c" />radio c</label><br>
<!-- textarea -->
<textarea class="textarea" rows="4" cols="50">additional notes</textarea>
</div>
</template>
<button id="addMoreFields">add</button>
<button id="submitForm" style="display: none;">submit</button>
</form>