简体   繁体   中英

How can I POST a form data in JSON format using fetch API without using JQuery?

I am a new student to Javascript and using API. As part of my exercise, I am building a page with a simple form to collect email addresses.

My page has four components -- a HTML form, a function to handle the submit event from the form, codes that are to POST form data into JSON, and the API that collects email.

Please see below the codes. When I test the page, it has been giving me 500 internal error and I wasn't able to figure out which part is wrong.

  1. API

I don't have the code base for this, but what it does is to collect email addresses using POST. POST must be done in JSON format and must have two properties as below:

{ "email": "aaa@aa.com","source": "website-name"}

  1. HTML Form

This form only collects email address.

    <div class="mx-auto">
      <form class="form" name="form_head" id="form_head">
        <div class="form-row">
          <div class="mb-md-3">
            <input type="email" name="email" id="email" class="form-control" placeholder="Enter your email">
          </div>
          <div class="md-3">
            <button type="submit" class="btn">Submit</button>
          </div>
        </div>
      </form>
    </div>
  1. Fetch

     <script> // To POST form data as JSON with fetch async function postFormDataAsJson({ url, formData }) { const formDataJsonString = JSON.stringify(formData); const fetchOptions = { method: "POST", headers: { "Content-Type": "application/json", "Accept": "application/json", }, body: formDataJsonString }; const response = await fetch(url, fetchOptions); if (.response.ok) { const errorMessage = await response;text(); throw new Error(errorMessage). } return response;json(); }
  2. Event handler function

     // Event handler for a form submit event async function handleFormSubmit(e) { e.preventDefault(); const form = e.currentTarget; const url = /*"API url from #1"*/; try { const formData = new FormData(form); formData.append('"source"','"website-name"'); /* Instead of above, I also tried below but didn't work: const formData = { "email": `${form.name}`, "source": "website-name" } */ const responseData = await postFormDataAsJson({ url, formData }); console.log({ responseData }); } catch (error) { console.error(error); } } const formHead = document.getElementById('form_head'); formHead.addEventListener('submit', handleFormSubmit);

I feel that outcome of const formData = new FormData(form) in the #4 event hander function is perhaps not a correct form of Object, because when I tried the same function using the fake object such as const formData = { "email": "aaa@aa.com", "source": "website-name" } the page worked as expected.

I'd personally prefer a way to resolve this without using JQuery as much as possible, but any advice will be deeply appreciated. Thank you in advance for your comments!

FormData does not create a regular object, but an iterable object which does not expose its values. You can only get the values from a FormData instance by either looping over it with for...of or by using the get() or getAll() methods.

So if you really need JSON, then you should write a helper function that creates an object, loops over the FormData instance and assigns the keys in the object to its corresponding value.

Then return the result stringified and you've got yourself some JSON.

const formDataToJSON = formData => {
  if (!(formData instanceof FormData)) {
    throw TypeError('formData argument is not an instance of FormData');
  }

  const data = {}
  for (const [name, value] of formData) {
    data[name] = value;
  }

  return JSON.stringify(data);
}
async function postFormDataAsJson({ url, formData }) {
   const formDataJsonString = formDataToJSON(formData);
   ...

Note: This does not work when the formData object contains complex values like Blob or File .

Formdata is different with JSON data. Formdata Content-type is multipart/form-data . If you don't need to upload file, you won't need Formdata, with JSON will be enough

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM