2

Pretty straight forward.

When a user clicks "submit", I need the form serialized and the JSON data displayed in the class"debug".

How do I do this with my current Javascript?

Cannot use jQuery. Cannot edit HTML. Only pure Javascript.

Thanks!

HTML

<ol class="household"></ol>
    <form>
        <div>
            <label>Age
                <input type="text" name="age">
            </label>
        </div>
        <div>
            <label>Relationship
                <select name="rel">
                    <option value="">---</option>
                    <option value="self">Self</option>
                    <option value="spouse">Spouse</option>
                    <option value="child">Child</option>
                    <option value="parent">Parent</option>
                    <option value="grandparent">Grandparent</option>
                    <option value="other">Other</option>
                </select>
            </label>
        </div>
        <div>
            <label>Smoker?
                <input type="checkbox" name="smoker">
            </label>
        </div>
        <div>
            <button class="add">add</button>
        </div>
        <div>
            <button type="submit">submit</button>
        </div>
    </form>
</div>
<pre class="debug"></pre>

JS

function validate(form) {
        fail = validateAge(form.age.value)
        fail += validateRel(form.rel.value)

        if (fail == "") return true
        else {
            alert(fail);
            return false
        }
    }

    function validateAge(field) {
        if (isNaN(field)) return "No age was entered. \n"
        else if (field < 1 || field > 200)
            return "Age must be greater than 0. \n"
        return ""
    }

    function validateRel(field) {
        if (field == "") return "Please select a relationship \n"
        return ""
    }

    document.querySelector("form").onsubmit = function() {
        return validate(this)
    }

    document.querySelector(".add").onclick = function(event) {
        event.preventDefault();
        createinput()
    }

    count = 0;
    function createinput() {
        field_area = document.querySelector('.household')
        var li = document.createElement("li");
        var p1 = document.createElement("p");
        var p2 = document.createElement("p");
        var p3 = document.createElement("p");
        var x = document.getElementsByName("age")[0].value;
        var y = document.getElementsByName("rel")[0].value;
        var z = document.getElementsByName("smoker")[0].checked;
        if (!z) {
            z = "Non smoker \n";
        } else {
            z = "Smoker \n";
        }
        p1.innerHTML = x;
        p2.innerHTML = y;
        p3.innerHTML = z;
        li.appendChild(p1);
        li.appendChild(p2);
        li.appendChild(p3);
        field_area.appendChild(li);
        //removal link
        var removalLink = document.createElement('a');
        removalLink.onclick = function() {
            this.parentNode.parentNode.removeChild(this.parentNode)
        }
        var removalText = document.createTextNode('Remove Field');
        removalLink.appendChild(removalText);
        li.appendChild(removalLink);
        count++
    }

    // serialize form
    var data = {};
    var inputs = [].slice.call(e.target.querySelector('form'));
    inputs.forEach(input => {
        data[input.name] = input.value;
    });
spidey677
  • 317
  • 1
  • 10
  • 27

3 Answers3

3

The shortest possible solution (pure javascript):

var form = document.querySelector('form');
var data = new FormData(form);

docs: https://developer.mozilla.org/en-US/docs/Web/API/FormData

mitch
  • 2,235
  • 3
  • 27
  • 46
2

Iterate through the form, grabbing the various elements and creating new objects for each one, then setting the properties for each object and pushing to the final array would solve your problem fairly easily.

Then you can simply use querySelectorAll to match .debug and use JSON.stringify() to convert your array to a string and innerText to set the contents.

Example:

function go() {
  var debug_class = document.querySelectorAll(".debug");
  for (var i = 0; i < debug_class.length; i++) {
    var element = debug_class[i];
    element.innerText = JSON.stringify(serializeArray(document.querySelector("form")));
  }

}

function serializeArray(form) {
  var field, l, s = [];
  if (typeof form == 'object' && form.nodeName == "FORM") {
    var len = form.elements.length;
    for (i = 0; i < len; i++) {
      field = form.elements[i];
      if (field.name && !field.disabled && field.type != 'file' && field.type != 'reset' && field.type != 'submit' && field.type != 'button') {
        if (field.type == 'select-multiple') {
          l = form.elements[i].options.length;
          for (j = 0; j < l; j++) {
            if (field.options[j].selected)
              s[s.length] = {
                name: field.name,
                value: field.options[j].value
              };
          }
        } else if ((field.type != 'checkbox' && field.type != 'radio') || field.checked) {
          s[s.length] = {
            name: field.name,
            value: field.value
          };
        }
      }
    }
  }
  return s;
}
<form id="blah">
  <input type="text" name="input1" value="a"></input>
  <input type="text" name="input2" value="b"></input>
  <input type="text" name="input3" value="c"></input>
  <input type="text" name="input4" value="d"></input>

</form>
<button onclick="go()">Serialize!</button>

<div class="debug"></div>

EDIT

In your particular case, after including the above code, you would have to call go() at some point to generate the serialized data.

Here's how to do it after clicking on add

 document.querySelector(".add").onclick = function(event) {
        go();   // display in .debug
        event.preventDefault();
        createinput()
    }

FULL SNIPPET

function go() {
  var debug_class = document.querySelectorAll(".debug");
  for (var i = 0; i < debug_class.length; i++) {
    var element = debug_class[i];
    element.innerText = JSON.stringify(serializeArray(document.querySelector("form")));
  }

}

function serializeArray(form) {
  var field, l, s = [];
  if (typeof form == 'object' && form.nodeName == "FORM") {
    var len = form.elements.length;
    for (i = 0; i < len; i++) {
      field = form.elements[i];
      if (field.name && !field.disabled && field.type != 'file' && field.type != 'reset' && field.type != 'submit' && field.type != 'button') {
        if (field.type == 'select-multiple') {
          l = form.elements[i].options.length;
          for (j = 0; j < l; j++) {
            if (field.options[j].selected)
              s[s.length] = {
                name: field.name,
                value: field.options[j].value
              };
          }
        } else if ((field.type != 'checkbox' && field.type != 'radio') || field.checked) {
          s[s.length] = {
            name: field.name,
            value: field.value
          };
        }
      }
    }
  }
  return s;
}


function validate(form) {
  fail = validateAge(form.age.value)
  fail += validateRel(form.rel.value)

  if (fail == "") return true
  else {
    alert(fail);
    return false
  }
  go();
}

function validateAge(field) {
  if (isNaN(field)) return "No age was entered. \n"
  else if (field < 1 || field > 200)
    return "Age must be greater than 0. \n"
  return ""
}

function validateRel(field) {
  if (field == "") return "Please select a relationship \n"
  return ""
}

document.querySelector("form").onsubmit = function() {
  return validate(this)
}

document.querySelector(".add").onclick = function(event) {
  go();
  event.preventDefault();
  createinput()
}

count = 0;

function createinput() {
  field_area = document.querySelector('.household')
  var li = document.createElement("li");
  var p1 = document.createElement("p");
  var p2 = document.createElement("p");
  var p3 = document.createElement("p");
  var x = document.getElementsByName("age")[0].value;
  var y = document.getElementsByName("rel")[0].value;
  var z = document.getElementsByName("smoker")[0].checked;
  if (!z) {
    z = "Non smoker \n";
  } else {
    z = "Smoker \n";
  }
  p1.innerHTML = x;
  p2.innerHTML = y;
  p3.innerHTML = z;
  li.appendChild(p1);
  li.appendChild(p2);
  li.appendChild(p3);
  field_area.appendChild(li);
  //removal link
  var removalLink = document.createElement('a');
  removalLink.onclick = function() {
    this.parentNode.parentNode.removeChild(this.parentNode)
  }
  var removalText = document.createTextNode('Remove Field');
  removalLink.appendChild(removalText);
  li.appendChild(removalLink);
  count++
}

// serialize form

var data = {};
var inputs = [].slice.call(e.target.querySelector('form'));
inputs.forEach(input => {
  data[input.name] = input.value;
});
<ol class="household"></ol>
<form>
  <div>
    <label>Age
      <input type="text" name="age">
    </label>
  </div>
  <div>
    <label>Relationship
      <select name="rel">
        <option value="">---</option>
        <option value="self">Self</option>
        <option value="spouse">Spouse</option>
        <option value="child">Child</option>
        <option value="parent">Parent</option>
        <option value="grandparent">Grandparent</option>
        <option value="other">Other</option>
      </select>
    </label>
  </div>

  <div>

    <label>Smoker?
      <input type="checkbox" name="smoker">
    </label>
  </div>

  <div>
    <button class="add">add</button>
  </div>
  <div>
    <button type="submit">submit</button>
  </div>
</form>
</div>
<pre class="debug"></pre>
mike510a
  • 2,102
  • 1
  • 11
  • 27
  • hey @mike510a thanks for sharing. I added the code and I don't see the values populating in the class="debug". What am I doing wrong? – spidey677 Dec 31 '16 at 23:35
  • In my example the form's name is 'blah' -- for your case it would be `element.innerText = JSON.stringify(serializeArray(document.querySelector('form')));` – mike510a Jan 01 '17 at 00:47
  • Also you have to add the `` part to make it actually work -- specifically the `onlick="go()"` part – mike510a Jan 01 '17 at 00:51
  • Hey Mike - I can't add any additional HTML. Only pure JS for this. :/ – spidey677 Jan 01 '17 at 00:57
  • hey @mike510a I'm still not seeing the JSON values in the class="debug". :/ – spidey677 Jan 01 '17 at 01:10
  • In the full snippet provided, the result was hidden under the console window due to a different error in the javascript -- you can click 'Run' now and see the form data – mike510a Jan 01 '17 at 01:17
  • so strange, on my end i see in console "e is not defined". For this part of code "var inputs = [].slice.call(e.target.querySelector('form'));" Any ideas? – spidey677 Jan 01 '17 at 01:22
  • I've been trying to fix that error but no luck. Any ideas what that is? – spidey677 Jan 01 '17 at 01:33
  • Its at the bottom in this line: `var inputs =[].slice.call(e.target.querySelector('form'));` in that code, `e` doesnt exist because it is not defined anywhere – mike510a Jan 01 '17 at 02:04
  • hey @mike510a nevermind. the "debug" class is set to display:none. I deleted display:none to test it out and i see the values. Thanks! – spidey677 Jan 01 '17 at 02:45
2

I know this form very well as I applied for same job position.It is an interesting task. Here is your answer with pure js!

var peopleList = [];
var addButton = document.querySelector('button.add');
var submitButton = document.querySelector('button[type=submit]');
var debug = document.querySelector('pre.debug');
var mainForm = document.forms[0];
var ageFormField = mainForm.age;
var relationshipFormField = mainForm.rel;
var smokerFormField = mainForm.smoker;
var positionFormField=mainForm.position;

//Taken from https://www.inventpartners.com/open-source/free-web-software/javascript_is_int
function is_int(value) {
    if ((parseFloat(value) == parseInt(value)) && !isNaN(value)) {
        return true;
    } else {
        return false;
    }
}

function formIsValid() {
    return ageFormField.value != '' && is_int(ageFormField.value) && relationshipFormField.selectedIndex != 0 && positionFormField.value !='';
}

function updateDebug() {
    if (peopleList.length != 0) {
        debug.innerText = JSON.stringify(peopleList);
        debug.setAttribute('style', 'display: block');
        submitButton.disabled = false;
    } else {
        debug.innerText = '';
        debug.removeAttribute('style');
        submitButton.disabled = true;
    }
}

function addEventClick(event) {
    event.preventDefault();
    if (formIsValid()) {
        peopleList.push({
            'age': ageFormField.value,
            'position':positionFormField.value,
            'relationship': relationshipFormField.options[relationshipFormField.selectedIndex].value,
            'isSmoker': smokerFormField.checked,
           
        });
        updateDebug();
        ageFormField.value = '';
        positionFormField.value='';
        relationshipFormField.selectedIndex = 0;
        smokerFormField.checked = false;
      
    } else {
        var errors = '';
        if (ageFormField.value == '') {
            errors += 'Please enter your age!';
        } else if (!is_int(ageFormField.value)) {
            errors += 'Age must be a numeric value!';
        }
        if (relationshipFormField.selectedIndex == 0) {
            if (errors != '') {
                errors += '\n';
            }
            errors += 'Please select your relationship status!';
        }

        if (positionFormField.value == '') {
            if (errors != '') {
                errors += '\n';
            }
            errors += 'Please enter your position!';
        }
        if (errors != '') {
            alert(errors);
            errors = '';
        }
         else if (
            errors != '') {
                alert(errors);
                errors = '';
        }
    }
}

function submitEventClick(event) {
    event.preventDefault();
    if (peopleList.length != 0) {
        var http = new XMLHttpRequest();
        var url = "savePeopleList.php";
        http.open('POST', url, true);
        http.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
        http.onreadystatechange = function() {
            if (http.readyState == 4) {
                if (http.status == 200) {
                    peopleList = [];
                    updateDebug();
                    alert('All of the changes were saved to the server!');
                } else {
                    alert('An error occured while sending the data to the server!');
                }
            }
        };
        http.send(JSON.stringify(peopleList));
    }
}

addButton.addEventListener('click', addEventClick, false);
submitButton.addEventListener('click', submitEventClick, false);
updateDebug();
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>Household builder</title>
        <style>
            .debug {
                font-family: monospace;
                border: 1px solid black;
                padding: 10px;
                display: none;
            }
        </style>
    </head>
    <body>
        <h1>Household builder</h1>
        <div class="builder">
            <ol class="household"></ol>
            <form>
                <div>
                    <label>Age
                        <input type="text" name="age">
                    </label>
                </div>
                <div>
                    <label>Position
                        <input type="text" name="position">
                    </label>
                </div>
                <div>
                    <label>Relationship
                        <select name="rel">
                            <option value="">---</option>
                            <option value="self">Self</option>
                            <option value="spouse">Spouse</option>
                            <option value="child">Child</option>
                            <option value="parent">Parent</option>
                            <option value="grandparent">Grandparent</option>
                            <option value="other">Other</option>
                        </select>
                    </label>
                </div>
                <div>
                    <label>Smoker?
                        <input type="checkbox" name="smoker">
                    </label>
                </div>
                <div>
                    <button class="add">add</button>
                </div>
                <div>
                    <button type="submit">submit</button>
                </div>
            </form>
        </div>
        <pre class="debug"></pre>
        <script type="text/javascript" src="./index.js"></script>
    </body>
</html>