membersound
membersound

Reputation: 86845

How to convert Json to html form and Post back?

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

Answers (2)

Vishal P Gothi
Vishal P Gothi

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

ikhvjs
ikhvjs

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

Related Questions