MtForms.js

Intro

Ver 0.8.0

MtForms.js is is a JavaScript library intended to simplify working with client-side web forms. If your app has mucho forms or if you dislike futzing with the DOM when manipulating fields, check out MtForms:

MtForms.js resides within the Minithematiq "family" but it will play nice with your own CSS, Bootstrap, or other CSS frameworks. (The only "custom" CSS you may need is a bit of styling for field validation errors.)

Easy As Pie

Dependencies: jQuery and Underscore.

First, grab the MtForms.js file from the js/ folder and include it in your project. (If you are rockin' CoffeeScript, the source is in _dev/coffee. See code comments on how to mod it into a Browserify module.)

1. Author your HTML forms with a few additional attributes, for example:

<input type="text" name="firstName" mt-model="userModel" mt-validators="require; text">
<input type="radio" name="isSubscribed" value="true" mt-actions="onCheckedShow(.success)" mt-cast="bool">
<input type="text" name="itemTotal" mt-model="costsModel" mt-actions="sum(itemSum); toCurrency($)" disabled>

2. Create a new MtForms instance and initialize your form(s):

var form = new MtForms( 'user-form' );

3. Use the MtForms API and forget about the DOM:

form.set( 'firstName', 'Matt' );
var firstName = form.get( 'firstName' );
var isValid = form.isFormValid();
var modelObj = form.getModel( 'userModel' );

Examples

Interact with the fields below to see MtForms in action. This first section demonstrates many validators (require, text, email, numRange, zip), type-casting (int, bool), a toggler action, and the getModel getter. As long as your HTML form is set up correctly, it all just works once initialized. Inspect away!

Interests
Skill Level
Subscribe
SUBSCRIBED!

The following inputs reside inside the same form but are assigned to a different model. This example also illustrates how to set up a table of inputs (multiple fields per key), with math actions (setMult, setSum), display filters (toCurrency), and more type-casting (int, float):

Description Qty Price Total
Not Valid!
isFormValid

HTML Attributes

name name="firstName"

The only attribute officially "required" by MtForms, it defines the data key under which MtForms stores the field's value(s). Groups of checkboxes and radios would naturally share the same name, but you can give a group of text inputs the same name as well. For example, you may have a table row of inputs. Such groups of values are captured by MtForms as arrays. (NOTE: Do NOT share the same name among different input types.)

mt-index mt-index="0"

For keeping track of multiple values per key, generated automatically by MtForms (unless you decide to author them manually for some specific reason). This attribute becomes important when working with tabular inputs, e.g., groups of rows or columns.

mt-model mt-model="userModel"

Define the model name to associate the field's key with. It allows you to seperate your form data by object, should you need to. (NOTE: Currently limited to one model per field.)

mt-validators mt-validators="require; numRange( 21, 100 )"

Specify which validator function(s) to apply to the field. Use semicolons to delimit multiple functions. If any validator fails, the value will not be "acquired" and other actions will not run. Error messages are injected into an absolutely-positioned .mt-input-wrap > div.mt-error which you can re-style as needed. The following validators are currently implemented (and it's fairly easy to add/mod your own):

require Field cannot be empty.

text Accepts chars A-Z only (either case).

num Accepts numeric values only (negative, decimals OK).

int Accepts integers only (negative OK).

charLength( min, max ) Strings within specified length range only. For infinity, supply a non-numeric arg.

numRange( min, max ) Numbers within specified limits only. For infinity, supply a non-numeric arg.

email Expects format <text>@<text>.<text>

zip Expects a 5-digit or ZIP plus 4 format.

match( key ) Field value must match that of specified name field

unique( key ) Value must be unique against other field(s) of the specified name field

password( min, max ) Expects at least one upper case, one lower case, and one digit, within the specified length range.

NOTE: Validator functions will not be run on hidden or disabled fields.

NOTE: Validators are run whenever a field change occurs. If all validations pass, MtForms fires event mt-forms-change on document, which you can listen on in your JS logic.

mt-actions mt-actions="validate(require, text); bindText(#title)"

Specify which additional function(s) to apply to the field. The actions will be run on any visible fields. Multiple semicolon-delimited actions per field are fine, but order matters (validate first). Action args use comma delimiters. The following actions are currently implemented (and it's fairly easy to add/mod your own):

bindText( id1, class1, ... ) On change/blur, inject the field's value into the selector(s) using .text()

bindVal( id1, class1, ... ) On change/blur, inject the field's value into the selector(s) using .val()

onCheckedHide( id1, class1, ... ) Toggler to hide the selector(s) when the input becomes checked using .hide()
onCheckedMtHide( id1, class1, ... ) Same as above, but accomplished by adding the CSS class mt-hide

onCheckedShow( id1, class1, ... ) Toggler to show the selector(s) when the input becomes checked using .show()
onCheckedMtShow( id1, class1, ... ) Same as above, but accomplished by removing the CSS class mt-hide

onCheckedVal( val, id1, class1, ... ) When the input becomes checked, inject val into selector(s) using .val()

onUncheckedVal( val, id1, class1, ... ) As above, for unchecked condition. In both actions, to clear an input, pass val of null

onValHide( val, id1, class1, ... ) Toggler to hide the selector(s) when the input value matches val using .hide()
onValMtHide( val, id1, class1, ... ) Same as above, but accomplished by adding the CSS class mt-hide

onValShow( val, id1, class1, ... ) Toggler to show the selector(s) when the input value matches val using .show()
onValMtShow( val, id1, class1, ... ) Same as above, but accomplished by removing the CSS class mt-hide

onValVal( val1, val2, id1, class1, ... ) When field's value matches val1, inject val2 into selector(s) using .val()

---------

setSum( range || key1, ... ) Calculate and set the sum into the field. Intended for disabled fields.

» range: Specify using a 'colon' e.g., keyA:keyC (all values inbetween) or keyA.2:keyB.6 (values within index range )

» keys: One or more key names e.g., keyA, keyB (all values per key) or keyA.3, keyC.3 (specific field values per key)

setMult( range || key1, ... ) Calculate and set the product into the field. Intended for disabled fields.

---------

toInt Display filter to convert field's output to an Int (default 0).

toFloat( precision ) Display filter to convert field's output to a Float of specified precision (default 0.00).

toCurrency( symbol ) Display filter to convert field's output to a comma-formatted Float with symbol prefix (default no symbol 0.00).

*Display filters do not alter the "internal" value. Intended for "text" inputs and applied only if any value is present in the field.

NOTE: When supplying selector arguments, the default behavior searches the DOM within the field's form only. To act on elements outside the form, append ':body' to the selector(s).

mt-cast mt-cast="int"

For text-based fields, specify how to typecast the value when using MtForm getters: int, float, bool, and string (default for most fields). Not to be confused with "display filters" above.

Methods

update( forms )

forms.update( 'user-form' ) forms.update( $('form') )

Update (re-initialize) one or more forms with MtForms. As long as you pass your form(s) in at instantiation, you do not need to call update. However, if your form structure changes, or you add/remove forms dynamically, you can update to re-initialize at any point (it will also clear any validation errors).

forms: [ str || str array || jQuery obj ] Form id, array of ids, or jQuery collection. If the form argument is not supplied, attempts an update on the first form previously initialized (assumes only one form is registered).

get( key, opts )

forms.get( 'firstName' ) forms.get( 'firstName', { model: 'cosigneeModel' } )

Fetch the current value of the specified name key. Radio groups always return a single value (or an empty string, if none checked), while checkbox groups return an array of checked values (or an empty array). Other groups return non-compacted arrays where the indices conform to mt-index (some entries can be null). To obtain a value of a specific field in a group, the index option must be specified.

key: [ str ] Field name.

opts.form: [ str || jQuery obj ] Optional form to narrow down key search by (id or jQuery selector, first match).

opts.index: [ int ] Optional mt-index to return the value of a specific field in a multi-field group.

opts.model: [ str ] Optional mt-model name to filter by.

set( key, value, opts )

forms.set( 'firstName', 'Annie' ) forms.set( 'interests', [ 'cycle', 'hike' ] )

Set a new value into the associated field, check/uncheck it, or disable/enable it. For multi-field keys, you can set all fields in one swoop by passing an array of values, to be applied by mt-index (except for checkbox groups which get set by value). Or, pass a single value and an index to set a specific field within the group. Returns status boolean.

key: [ str ] Field name.

value: [ any ] Single value or an array of vals to set into the corresponding field(s).

opts.index: [ int ] The field's mt-index, required if setting into a multi-field group, except radio or checkbox (0 by default).

opts.checked: [ bool ] Set false to uncheck the related input. (true by default, applies to "checkable" fields only.)

opts.disabled: [ bool ] Set false or true to disable or re-enable the corresponding field. (null by default.)

opts.model: [ str ] Filter, value will set only if field's mt-model name matches.

opts.form: [ str || jQuery obj ] Filter, value will set only if field is within the specified form (id or jQuery selector, first match).

opts.mode: [ str ]
    "default"  Skip validations but re-run logic for all fields (default mode, no need to specify).
    "manual"  Trigger standard 'change' event on the field -- will run validations and all logic.
    "silent"  No validations, no logic. Just set the value.

isValid( key, opts )

forms.isValid( 'firstName' )

Run any validate functions assigned to the associated field, return success boolean.

key: [ str || jQuery obj ] Name key, or field acquired as jQuery selector (first match).

opts.index: [ int ] Optional mt-index to validate a specific field in a multi-field group.

opts.model: [ str ] Optional mt-model name to filter by.

opts.mode: [ str ] Assign as 'silent' to suppress rendering of error messages.

setError( key, text, opts )

forms.setError( 'password', 'Too Weak', { form: 'login-form' } )

Manually trigger an error message on a specified form field.

key: [ str || jQuery obj ] Name key, or field acquired as jQuery selector (first match).

opts.index: [ int ] Optional filter to target a specific field in a multi-field group.

opts.form: [ str || jQuery obj ] Optional filter to target a specific form within the current instance (id or jQuery selector, first match).

getFormIds()

forms.getFormIds()

Fetch an array of all unique form ids currently registered in the MtForms instance.

getAll( key, opts )

forms.getAll( 'firstName', { forms: [ 'user-01', 'user-02' ] } )

Return an array of values for the specified field key, from all forms currently registered in the mtForms instance. Optionally, accepts a list of forms to filter from.

key: [ str ] Key name.

opts.forms: [ array || jQuery obj ] Array of forms ids or jQuery selector.

getForm( form )

forms.getForm( 'user-form' )

Fetch a flat data object of all key-val pairs within to the specified form. If the form argument is not supplied, assumes only one form is registered in mtForms.

form: [ str || jQuery obj ] Form id or jQuery selector (first match).

getAllForms( opts )

forms.getAllForms()

Return an array of flat data objects, representing all forms currently registered in the mtForms instance. Optionally, accepts a list of forms to filter from.

opts.forms: [ array || jQuery obj ] Array of forms ids or jQuery selector.

setForm( form, dataObj )

forms.setForm( 'user-form', { firstName: 'Charlie', skillLevel: 2 } )

Use the supplied data object to set all matching fields belonging to the specified form. If the form argument is not supplied, assumes only one form is registered in mtForms and dataObj is in the first argument.

form: [ str || jQuery obj ] Form id or jQuery selector (first match).

dataObj: [ obj ] A flat object of key-val pairs.

isFormValid( form, opts )

forms.isFormValid( 'user-form', { mode: 'silent' } )

Run all validate functions across all fields within the supplied form, return success boolean. If the form argument is not supplied, assumes only one form is registered in mtForms and the opts object is the first argument (if any).

form: [ str || jQuery obj ] Form id or jQuery selector (first match).

opts.mode: [ str ] Assign as 'silent' to suppress rendering of error messages.

getModelNames()

forms.getModelNames()

Fetch an array of all unique model names currently registered in the MtForms instance.

getModel( modelName )

forms.getModel( 'userModel' )

Fetch a flat data object of all key-val pairs within the specified model.

modelName: [ str ] The desired mt-model name.

setModel( modelName, dataObj )

forms.setModel( 'userModel', { lastName: 'Doe', interests: [ 'swim', 'hike' ], isSubscribed: false } )

Use the supplied data object to set all matching fields belonging to the specified model.

modelName: [ str ] The mt-model name.

dataObj: [ obj ] A flat object of key-val pairs.

isModelValid( modelName, opts )

forms.isModelValid( 'userModel', { mode: 'silent' } )

Run all validate functions across all fields assigned the specified mt-model, return success boolean.

modelName: [ str ] The mt-model name.

opts.mode: [ str ] Assign as 'silent' to suppress rendering of error messages.

getDiff( refObj, dataObj )

forms.getDiff( forms.getModel( 'userModel' ), { firstName: 'Jane', email: 'jane@example.com' } )

Compare refObj against the supplied dataObj and return a difference object. (Shallow comparison against refObjs's keys only.)

refObj: [ obj ] Reference object, e.g., current form or model object.

dataObj: [ obj ] Comparison object, e.g., form or model object from database.

getFieldObj( field, opts )

forms.getFieldObj( 'firstName' ) forms.getFieldObj( 'interests', { value: 'cycle' } )

Fetch a comprehensive data object for the corresponding field, including its current value, all relevant attributes, and its jQuery selector. If your fields are set up with validators and logic, it is unlikely you would need to use this method often.

field: [ str || jQuery obj ] Name key, or field acquired as jQuery selector (first match).

opts.index: [ int ] For multi-field keys, use index as identifier.

opts.value: [ any ] For multi-field keys, use value as identifier.