@jalik/form-parser
Parse complex forms with minimum effort.
Introduction
Parsing forms can be painful, but with this great library you can get all fields from a form, automatically parse values (boolean, number, string, array, object), remove unnecessary spaces from strings and replace empty strings with null, plus you can decide which fields are collected or ignored and even use your own cleaning function.
Getting started
Let start with a very simple form which produces a flat object :
<form id="my-form">
<input name="username" value="jalik">
<input name="email" type="email" value="jalik@mail.com">
<input name="age" type="number" value="30">
<input name="subscribeToNewsletter" type="checkbox" data-type="boolean" value="true" checked>
<input name="phone" type="tel" data-type="string" value="067123456">
<input name="token" type="hidden" value="aZ7hYkl12mPx">
<button type="submit">Submit</button>
</form>
You can get fields from this form in a single object with minimum effort by using the parseForm()
method.
Note: The form object must be an HTMLFormElement
.
import { parseForm } from "@jalik/form-parser";
const form = document.getElementById("my-form");
const fields = parseForm(form);
The fields
object will look like this :
{
"username": "jalik",
"email": "jalik@mail.com",
"age": 30,
"subscribeToNewsletter": true,
"phone": "067123456",
"token": "aZ7hYkl12mPx"
}
Below is a more complete form example, with a lot of different cases to help you understand the behavior of the parsing function (pay attention to comments, values and attributes).
<form id="my-form">
<input type="text" value="aaa">
<input name="boolean" type="radio" data-type="boolean" value="true">
<input name="boolean" type="radio" data-type="boolean" value="false" checked>
<input name="hidden_boolean" type="hidden" data-type="auto" value="true">
<input name="float" type="number" value="09.99">
<input name="hidden_float" type="hidden" data-type="number" value="09.99">
<input name="text_integer" type="text" data-type="number" value="01">
<input name="integer" type="number" value="01">
<input name="range" type="range" value="0118">
<select name="select_number" data-type="auto">
<option value="10"></option>
<option value="20"></option>
<option value="30" selected></option>
</select>
<input name="date" type="date" value="2017-11-14">
<input name="file" type="file" value="file://path/to/file.txt">
<input name="hidden_text" type="hidden" value="shadowed">
<input name="month" type="month" value="2017-11">
<input name="number_text" type="number" data-type="string" value="0123">
<input name="text" type="text" value="Hello">
<input name="url" type="url" value="http://www.github.com/">
<input name="week" type="week" value="2017-W16">
<textarea name="textarea">Hello</textarea>
<input name="password" type="password" value=" s3crEt ">
<input name="array[]" type="checkbox" value="A" checked>
<input name="array[]" type="checkbox" value="B" checked>
<select name="select_multiple" data-type="number" multiple>
<option value="10"></option>
<option value="20" selected></option>
<option value="30" selected></option>
</select>
<input name="disabled_field" value="" disabled>
<input name="input_button" type="button" value="Click me">
<input name="input_reset" type="reset" value="Reset">
<input name="input_submit" type="submit" value="Submit">
<button name="button" type="button" value="Click me"></button>
<button name="reset" type="reset" value="Reset"></button>
<button name="submit" type="submit" value="Submit"></button>
</form>
To get form fields :
import { parseForm } from "@jalik/form-parser";
const form = document.getElementById("my-form");
const fields = parseForm(form);
The fields
object will look like this :
{
"boolean": false,
"hidden_boolean": true,
"float": 9.99,
"hidden_float": 9.99,
"text_integer": 1,
"integer": 1,
"range": 118,
"select_number": 30,
"date": "2017-11-14",
"file": "file://path/to/file.txt",
"hidden_text": "shadowed",
"month": "2017-11",
"number_text": "0123",
"text": "Hello",
"url": "http://www.github.com/",
"textarea": "Hello",
"password": " s3crEt ",
"array": ["A", "B"],
"select_multiple": [20, 30]
}
Parsing arrays
To get an array of values from a form, use this syntax :
<form id="my-form">
<input name="array[]" type="checkbox" value="A">
<input name="array[]" type="checkbox" value="B" checked>
<input name="array[]" type="checkbox" value="C" checked>
<input name="colors[2]" type="checkbox" value="red" checked>
<input name="colors[1]" type="checkbox" value="blue">
<input name="colors[0]" type="checkbox" value="white" checked>
</form>
Get fields values :
import { parseForm } from "@jalik/form-parser";
const form = document.getElementById("my-form");
const fields = parseForm(form);
The fields
object will look like this :
{
"array": ["B", "C"],
"colors": ["white", undefined, "red"]
}
Parsing objects
To get an object from a form, use this syntax :
<form id="my-form">
<input name="address[street]" value="Av. Pouvanaa a Oopa">
<input name="address[city]" value="Papeete">
</form>
Get fields values :
import { parseForm } from "@jalik/form-parser";
const form = document.getElementById("my-form");
const fields = parseForm(form);
The fields
object will look like this :
{
"address": {
"street": "Av. Pouvanaa a Oopa",
"city": "Papeete"
}
}
Using numbers as object attribute (since v2.0.6)
If you need to create an object with numbers as attributes, use single or double quotes to force the parser to interpret it as a string and then creating an object instead of an array.
<form id="my-form">
<input name="elements['0']" value="Zero">
<input name="elements['1']" value="One">
<input name="elements['2']" value="Two">
</form>
Will give this :
{
"elements": {
"0": "Zero",
"1": "One",
"2": "Two"
}
}
Instead of :
{"elements": ["Zero", "One", "Two"]}
Forcing fields types
Sometimes you may want to force a number to be parsed as a string for example.
In this case, use the data-type
attribute on the input. When the parser will get fields values, it will automatically convert them to the given data-type
.
The data-type
attribute can have one of the following values : auto
, boolean
, number
or string
.
Note: The auto
data-type will convert value to the best guess type (ex: 123
=> number
).
Note: The boolean
data-type will convert "1"
and "true"
to true
, all other values are false
.
<input name="boolean" type="text" data-type="boolean" value="true">
<input name="integer" type="text" data-type="number" value="01">
<input name="float" type="text" data-type="number" value="09.99">
<input name="string" type="text" data-type="string" value="0963">
<input name="anything" type="text" data-type="auto" value="13.37">
<input name="anything_2" type="text" data-type="auto" value="false">
If no data-type
attribute is set, the type
attribute will be used (for input
elements at least), this behavior is active by default with the combination of this options {dynamicTyping: true, smartTyping: true}
in the parseForm()
function.
Parsing complex forms with nested fields
This purpose of this lib is to reconstruct an object corresponding to the form structure, so it can parse complex forms containing "unlimited" nested arrays and objects.
<form id="my-form">
<input name="phones[0][code]" type="number" data-type="string" value="689">
<input name="phones[0][number]" type="number" data-type="string" value="87218910">
<input name="phones[1][code]" type="number" data-type="string" value="689">
<input name="phones[1][number]" type="number" data-type="string" value="87218910">
<input name="deep_1[][deep_2][0][][deep_3]" value="DEEP">
</form>
To get fields :
import { parseForm } from "@jalik/form-parser";
const form = document.getElementById("my-form");
const fields = parseForm(form);
The fields
object will look like this :
{
"phones": [
{
"code": "689",
"number": "87218910"
},
{
"code": "689",
"number": "87218910"
}
],
"deep_1": [
{
"deep_2": [
[
{"deep_3": "DEEP"}
]
]
}
]
}
Filtering fields
You can get only the fields you want with filterFunction(field)
option in the parseForm()
method. The filter function will be called with all fields and must return true
to return the field.
import { parseForm } from "@jalik/form-parser";
const form = document.getElementById("my-form");
const fields = parseForm(form, {
filterFunction: (field) => field.type === "text",
});
Cleaning parsed values
All string values can be cleaned using the cleanFunction(value, field)
option in the parseForm()
method. The clean function will be called with any value that is a string of length > 0.
import { parseForm } from "@jalik/form-parser";
const form = document.getElementById("my-form");
const fields = parseForm(form, {
cleanFunction: (value, field) => {
if (field.name === "lastName" || /name/gi.test(field.name)) {
value = value.toUpperCase();
}
return value.replace(/<\/?[^>]+>/gm, "");
}
});
API
parseField(field, options)
You can parse a single field with options, it works the same way as parseForm(form, options)
but with a field.
import { parseField } from "@jalik/form-parser";
const colorsSelect = document.getElementById("colors-field");
const colors = parseField(colorsSelect, {
dynamicTyping: true,
nullify: true,
smartTyping: true,
trim: true,
});
parseForm(form, options)
You can parse a form with options to customize the behavior.
import { parseForm } from "@jalik/form-parser";
const form = document.getElementById("my-form");
const fields = parseForm(form, {
cleanFunction(value, field) {
return typeof value === 'string' ? stripTags(value) : value;
},
filterFunction(field) {
return field.type === 'text';
},
ignoreButtons: true,
ignoreDisabled: true,
ignoreEmpty: false,
ignoreUnchecked: false,
nullify: true,
dynamicTyping: true,
smartTyping: true,
trim: true
});
Changelog
History of releases is in the changelog.
License
The code is released under the MIT License.
If you find this lib useful and would like to support my work, donations are welcome :)