@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 collect and parse all fields in a single object with parseForm()
.
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="disabled_field" value="hello" 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>
<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="hidden_float" type="hidden" data-type="number" value="09.99">
<input name="text_integer" type="text" data-type="number" value="01">
<select name="select_number" data-type="number">
<option value="10"></option>
<option value="20"></option>
<option value="30" selected></option>
</select>
<input name="float" type="number" value="09.99">
<input name="integer" type="number" value="01">
<input name="range" type="range" value="0118">
<input name="number_text" type="number" data-type="string" value="0123">
<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="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" data-type="number" value=" 1337 ">
<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="array[]" type="checkbox" value="A" checked>
<input name="array[]" type="checkbox" value="B" checked>
</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": " 1337 ",
"array": [
"A",
"B"
],
"select_multiple": [
20,
30
]
}
Parsing arrays
To get an array of values, append []
to a field name:
<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, write attributes like [attribute]
:
<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 keys in objects (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"
]
}
Fields parsing
To define the type of field, you can use the attribute data-type
or type
.
The attribute data-type
takes precedence over type
if both of are defined.
When using data-type
attribute, the value can be:
auto
to convert the value to the best guess type (ex: 123
=> number
, true
=> boolean
)boolean
to convert the value to a boolean (ex: true
, 1
, yes
, on
, false
, 0
, no
, off
)number
to convert the value to a number
When using type
attribute on <input>
, only number
and range
are parsed to numbers.
<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">
Parsing complex forms with nested fields
It is possible to reconstruct an object corresponding to the form structure, so it can
parse complex forms containing 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
When parsing a form, you can filter values with filterFunction(field, parsedValue)
option in the parseForm(form, options)
.
The filter function 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, parsedValue) => field.type === 'text'
});
Cleaning
Values can be cleaned by passing cleanFunction(value, field)
to parseForm(form, options)
.
Note that only strings are passed to this function and that password fields are ignored.
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)
To parse a single field.
<form>
<select data-type="number" name="values" multiple>
<option>1</option>
<option selected>2</option>
<option selected>3</option>
</select>
</form>
import { parseField } from '@jalik/form-parser'
const field = document.getElementById('values')
const values = parseField(field)
parseForm(form, options)
To parse a form with all fields.
<form id="my-form">
<input type="number" name="age" value="35" />
<select data-type="number" name="values" multiple>
<option>1</option>
<option selected>2</option>
<option selected>3</option>
</select>
</form>
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'
},
nullify: true,
parsing: 'none' | 'type' | 'data-type' | 'auto',
trim: true
})
Changelog
History of releases is in the changelog.
License
The code is released under the MIT License.