Reputation: 86845
I want to convert a json
array (that is fetched from backend) to a dynamic html form:
{
"journeys": [
{
"origin": "New York"
"destination": "San Francisco"
"distance": 4670
},
{
//repeat the above N times
}
]
}
While it would be ease to generate 3 inputs for each array element, how can I actually POST
them back to backend after editing?
I mean, normally each <input>
element has a name
attribute that is used as query parameter in get/post requests.
But how could I actually post the modified json
equivalent here?
<form>
<div class="mb-3">
<label for="origin1" class="form-label">Origin</label>
<input type="text" class="form-control" id="origin1">
</div>
<div class="mb-3">
<label for="destination1" class="form-label">Destination</label>
<input type="text" class="form-control" id="destination1">
</div>
<div class="mb-3 form-check">
<label for="distance1" class="form-label">Distance</label>
<input type="text" class="form-control" id="distance1">
</div>
<!-- repeat the above N times, with id="originN" / "destinationN" / "distanceN" -->
<button type="submit" class="btn btn-primary">Submit</button>
</form>
Upvotes: 0
Views: 575
Reputation: 997
I have updated some of the code from the answer of @ikhvjs to increase the field id with the N element when it is rendering. Thanks for the answer @ikhvjs
And Yes I kept the first element as it is so if you don't want you can remove that HTML code.
const data = {
journeys: [
{
origin: "New York",
destination: "San Francisco",
distance: 4670,
},
{
origin: "Australia",
destination: "Sydney",
distance: 2300,
},
{
origin: "Australia 1",
destination: "Sydney 1",
distance: 2301,
},
{
origin: "Australia 2",
destination: "Sydney 2",
distance: 2302,
},
],
};
var increment = 2;
for (const { origin, destination, distance } of data.journeys) {
const form = document.createElement("form");
form.innerHTML = `<hr/>
<div class="mb-3">
<label for="origin'${increment}'" class="form-label">Origin</label>
<input type="text" class="form-control" name='origin' id="origin'${increment}'" value='${origin}'/>
</div>
<div class="mb-3">
<label for="destination'${increment}'" class="form-label">Destination</label>
<input type="text" class="form-control" name='destination' id="destination'${increment}'" value='${destination}'/>
</div>
<div class="mb-3 form-check">
<label for="distance'${increment}'" class="form-label">Distance</label>
<input type="text" class="form-control" name='distance' id="distance'${increment}'" value='${distance}'/>
</div>
`;
document.querySelector("jsonresponse").appendChild(form);
increment++;
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>Title of the document</title>
</head>
<body>
<form id="my_test_form">
<div class="mb-3">
<label for="origin1" class="form-label">Origin</label>
<input type="text" name="origin[]" class="form-control" id="origin1">
</div>
<div class="mb-3">
<label for="destination1" class="form-label">Destination</label>
<input type="text" name="destination[]" class="form-control" id="destination1">
</div>
<div class="mb-3 form-check">
<label for="distance1" class="form-label">Distance</label>
<input type="text" name="distance[]" class="form-control" id="distance1">
</div>
<jsonresponse></jsonresponse>
<!-- repeat the above N times, with id="originN" / "destinationN" / "distanceN" -->
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</body>
</html>
Upvotes: 1
Reputation: 5967
You can use new FormData()
and loop formData.entries()
to construct the data you need.
const data = {
journeys: [
{
origin: "New York",
destination: "San Francisco",
distance: 4670,
},
{
origin: "Australia",
destination: "Sydney",
distance: 2300,
},
],
};
//create HTML
for (const { origin, destination, distance } of data.journeys) {
const form = document.createElement("form");
form.innerHTML = `
<div class="mb-3">
<label class="form-label">Origin</label>
<input type="text" class="form-control" name='origin' value='${origin}'/>
</div>
<div class="mb-3">
<label class="form-label">Destination</label>
<input type="text" class="form-control" name='destination' value='${destination}'/>
</div>
<div class="mb-3 form-check">
<label class="form-label">Distance</label>
<input type="text" class="form-control" name='distance' value='${distance}'/>
</div>
`;
document.querySelector("section").appendChild(form);
}
//add addEventListener to send data to backend
document.querySelector("#btn1").addEventListener("click", () => {
const forms = document.querySelectorAll("form");
const updatedData = { journeys: [] };
forms.forEach(form => {
const formData = new FormData(form);
const journey = {};
for (const [key, value] of formData.entries()) {
if (key === "distance") {
journey[key] = Number(value);
} else {
journey[key] = value;
}
}
updatedData.journeys.push(journey);
});
console.log(updatedData);
});
<section></section>
<button id="btn1" type="button" class="btn btn-primary">Submit</button>
Upvotes: 1