2

I've the below code, that read form elements and convert them to JSON, it works well with most of the elements, but working wrongly with both: Checkbox and Radio buttons selection, how can I fix it?

const formToJSON = elements => [].reduce.call(elements, (data, element) => {
  data[element.name] = element.value;
  return data;

}, {});

const handleFormSubmit = event => {
  event.preventDefault();
  console.log("hi");
  const data = formToJSON(form.elements);
  console.log(data);
  //  const odata = JSON.stringify(data, null, "  ");
  const jdata = JSON.stringify(data);
  console.log(jdata);

  (async() => {
    const rawResponse = await fetch('/', {
      method: 'POST',
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      },
      body: jdata
    });
    const content = await rawResponse.json();

    console.log(content);
  })();
};
const form = document.forms['myForm']; // document.getElementsByClassName('contact-form')[0];
form.addEventListener('submit', handleFormSubmit);
<form id="myForm" action="/" method="post" accept-charset="utf-8">
  <label>Checkbox:
        <input type="checkbox" name="checkbox">
    </label><br /><br />

  <label>Number:
        <input name="number" type="number" value="123" />
    </label><br /><br />

  <label>Password:
        <input name="password" type="password" />
    </label>
  <br /><br />

  <label for="radio">Type:
        <label for="a">A
            <input type="radio" name="radio" id="a" value="a" />
        </label>
  <label for="b">B
            <input type="radio" name="radio" id="b" value="b" checked />
        </label>
  <label for="c">C
            <input type="radio" name="radio" id="c" value="c" />
        </label>
  </label>
  <br /><br />

  <label>Textarea:
        <textarea name="text_area" rows="10" cols="50">Write something here.</textarea>
    </label>
  <br /><br />

  <label>Select:
        <select name="select">
            <option value="a">Value A</option>
            <option value="b" selected>Value B</option>
            <option value="c">Value C</option>
        </select>
    </label>
  <br /><br />

  <label>Submit:
        <input type="submit" value="Login">
    </label>
  <br /><br />
</form>

UPDATE

Based on the comment received, I solved the issue of radio as below:

const formToJSON = elements => [].reduce.call(elements, (data, element) => {
  console.log(element);
  if(element.type == "radio") {
    if(element.checked) data[element.name] = element.value;
  } else data[element.name] = element.value;

  return data;

}, {});

But how to solve the one of the checkbox

Hasan A Yousef
  • 22,789
  • 24
  • 132
  • 203
  • You're putting the value of all the checkboxes and radios in the JSON, not just the ones that are checked. – Barmar Aug 07 '19 at 17:52
  • @Barmar so how to fix it? – Hasan A Yousef Aug 07 '19 at 17:53
  • @Barmar what about the checkbox? – Hasan A Yousef Aug 07 '19 at 17:58
  • Getting the `value` attribute for checkboxes and radio groups won't work; you want to know which ones are checked. For a checkbox, you can just test the element for whether it has the `checked` attribute. In the case of radio buttons, you probably want to make just one entry in the JSON for the whole group (using the group's `name` as the key), then loop through the group until you find one with the `checked` attribute and use that element's `value` as the value. (This explains more: https://stackoverflow.com/questions/9618504/how-to-get-the-selected-radio-button-s-value) – Cat Aug 07 '19 at 18:09

1 Answers1

1

Add a switch statement and check the element types. Use the checked attribute for checkbox

const formToJSON = elements => [].reduce.call(elements, (data, element) => {
  console.log(element);
  switch (element.type) {
    case "radio": if(element.checked) data[element.name] = element.value;
     break;
    case "checkbox" : data[element.name] = element.checked;
     break;
    case "number" : data[element.name] = Number(element.value);
     break;
    default: data[element.name] = element.value;
}
  return data;

}, {});
Hasan A Yousef
  • 22,789
  • 24
  • 132
  • 203
weegee
  • 3,256
  • 2
  • 18
  • 32