4

i'm trying to pull out all of the data from my form and convert it to a queryString, to then post to an endpoint.

This is what I have so far, however I can#t figure out a quick and clean way to convert this to for example: key=value&key=value.

let data = Array.from(this.querySelectorAll('input:not([type="submit"]), select, textarea')).map(input => {
    let value = '';
    switch(input.tagName) {
        case 'INPUT':
            value = input.value;
            break;
        case 'SELECT':
            value = input[input.selectedIndex].value;
            break;
        case 'TEXTAREA':
            value = input.innerHTML;
            break;
    }

    return {
        key: input.name,
        value: value
    };
});

console.log(data);

// Object.keys(obj).map(k => `${encodeURIComponent(k)}=${encodeURIComponent(obj[k])}`).join('&');

The above code is creating an array of objects, with the key and values. It would be nice to be able use the one liner which is commented out above.

5
  • 3
    You don't need that switch. this.value will work in all three cases. Commented Jul 17, 2019 at 11:51
  • stackoverflow.com/questions/41431322/… Commented Jul 17, 2019 at 11:53
  • 1
    Using .innerHTML for <textarea> is not correct; it's just .value. Also you should probably test for elements that are disabled, for completeness. Commented Jul 17, 2019 at 11:55
  • stackoverflow.com/questions/11661187/… Commented Jul 17, 2019 at 11:58
  • 2
    be nice to be able use the one liner -> data.map(({key, value}) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`).join('&'); Commented Jul 17, 2019 at 12:02

2 Answers 2

12

Scrap what you got. You should wrap your inputs in a <form>. Not only is this semantically correct, but it allows you to get a FormData object from the form. See my code:

const form = document.getElementById('my-form');

form.addEventListener('submit', (evt) => {
  evt.preventDefault();
  const formData = new FormData(form);
  const params = new URLSearchParams(formData);
  console.log(params.toString());
});
<form id="my-form">
  <input type="text" name="name" id="name">
  <select id="gender" name="gender">
    <option value="foo">Foo</option>
    <option value="bar">Bar</option>
    <option value="baz">Baz</option>
  </select>
  <input type="submit" />
</form>

FormData objects can also be given directly to the body of a fetch-request. No need to construct the query string yourself.

You can add or remove different input fields from the code above, and it will still work.

Sign up to request clarification or add additional context in comments.

1 Comment

I tried FormData but it wouldn't work for me, and I also get a warning saying that FormData expects 0 parameters, but thanks, this works!
1

You could use URLSearchParams interface to transform a FormData interface into a query string

Please try this example

const form = document.forms.form;

form.addEventListener("submit", handleSubmit);

function handleSubmit(event) {
  event.preventDefault();

  const formData = new FormData(form);
  const queryString = new URLSearchParams(formData).toString();

  console.log(queryString);
}
label, input, select, textarea {
  display: block;
}
<form action="" name="form" id="form">
  <label for="firstName">
    First name
    <input type="text" name="firstName" id="firstName" />
  </label>

  <label for="lastName">
    Last name
    <input type="text" name="lastName" id="lastName" />
  </label>

  <label for="email">
    Email
    <input type="text" name="email" id="email" />
  </label>

  <label for="genre">
    Genre
    <select name="genre" id="genre">
      <option value="female">Female</option>
      <option value="male">Male</option>
    </select>
  </label>

  <label for="bio">
    Bio
    <textarea name="bio" id="bio" cols="30" rows="10"></textarea>
  </label>

  <p>
    <button type="submit">Submit</button>
  </p>
</form>

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.