1

I use Javascript to intercept an HTML form submission:

var form_api = $("#apiForm");
$(form_api).submit(function(event) {
   /* stop form from submitting normally */
   event.preventDefault();

   /* Get input values from form */
   var formData = prepFormData("#apiForm");
}

However, when I convert the data into an object (I wish to use jQuery to pass this to an endpoint), all object properties are strings.

function prepFormData(formSelector){
   var form_api = $(formSelector);

   // Serialize the form data as a PlainObject.
   var formData = $(form_api).serializeArray().reduce(function (obj, item) {
      obj[item.name] = item.value;
      return obj;
   }, {});
}

Why does it always produce strings? I would like the following behavior instead:

  • <input type="text"> should produce NULL when nothing has been entered.
  • <input type="number"> should produce an Int when a value has been entered.

2 Answers 2

3

You need to parse the input to suite your needs. Every form value in HTML in inherently a string.

The type attribute lets the browser know what kind of field to display, not what is the data type of the value. Take for example:

<input type="hidden" value="1">

HTML and javascript can infer no information about the data type from hidden it could be a string it could be an int.

number is equally problematic, why default to int, what about doubles and other number types?

In my example above, note that the value is surrounded by quotes, denoting a string. (Quotes are optional, but recommended, but do nothing to the data type.)

To actually solve your problem I would consider adding a data attribute to your fields, say data-type to hold the data type you want to cast your value to.

Here's a quick example:

var form_api = $("#apiForm");
$(form_api).submit(function(event) {
   /* stop form from submitting normally */
   event.preventDefault();

   /* Get input values from form */
  var formData = prepFormData("#apiForm");  
  console.log(formData);
});


function prepFormData(formSelector){
 var form_api = $(formSelector);

   // Serialize the form data as a PlainObject.
   var formData = $(form_api).serializeArray().reduce(function (obj, item) {
      var tempValue = null;
      if(item.value !== "") {
        //Get data type of current field
        var dataType = $(form_api).find("[name=" + item.name + "]").data("type");
        
        if(dataType === undefined) {
          dataType = "text";
        }
        
        //Extend this based on the other data types you need   
        switch(dataType) {
          case "text" :
            tempValue = item.value;
            break;
         case "int" :
            tempValue = parseInt(item.value, 10);
            break;
         case "float" : 
            tempValue = parseFloat(item.value);
            break;         
         //Fall back for no data type defined, eg the select in this example   
         default :
            tempValue = item.value;
            break;
        }
      }
      obj[item.name] = tempValue;
      return obj;
   }, {});
   
   return formData;
}
label {display:block; margin-bottom:5px;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<form id="apiForm" method="get" action="">
  <label>Name <input type="text" data-type="text" name="Name"></label>
  <label>Integer <input type="number" data-type="int" name="Integer"></label>
  <label>Float <input type="number" step="0.1" data-type="float" name="Float"></label>
  <fieldset>
    <legend>Age Range</legend>
    <label>&lt;18 <input type="radio" data-type="text" name="AgeRange" value="<18"></label>
    <label>&gt;18 <input type="radio" data-type="text" name="AgeRange" value=">18"></label>
  </fieldset>
  <label>Country
  <select name="country">
    <option value="usa">USA</option>
    <option value="aus">Australia</option>
    <option value="other">Other</option>
  </select>
  </label>
  <label>Product
    <select name="ProductId" data-type="int">
      <option value="1">Apple</option>
      <option value="2">Orange</option>
      <option value="11">Pear</option>
      <option value="110">Pineapple</option>
    </select>
  </label>
  <input type="hidden" data-type="text" name="HiddenText" value="">
  <input type="submit">
</form>

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

1 Comment

You can just add any data attribute you want to a field? That would be useful. How would you retrieve it when building the PlainObject?
2

This in normal JS behaviour. type number and text are for validations inside the input for browsers. They don't define the data-type of the value inside of them. By default they are strings. You can perform conversions for your use. The text field returns an empty string because it's by default an empty string and not null.

1 Comment

Is there a way to see what type of input field is giving me each key/value pair so that I could perform the appropriate conversions in prepFormData?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.