Form - globules-io/OGX.JS GitHub Wiki
Form
is a helper object to deal with fields and forms specially on mobile. It can be used as a static class to control an HTML form (static form), or to generate an instance ofFormInstance
, that will be controlled byOGX.Form
.
OGX.Form
doesn't need to be instantiated, it is built as a static class.
You can generate forms using predefined types of controls for each type of value. Here's the default configuration per type. Note that the OML tag for this object will be
FormInstance
{
templates:{
row: '<span class="row"><span class="label">{{$prop}}</span>{{$html}}</span>',
form: '<form>{{$rows}}</form>'
},
types: {
boolean : {html: '<span class="{{$name}}"></span>', oml:'{"default .{{$name}}:Switch":{"name" : "{{$prop}}", "val":{{$val}} }}'},
string : {html: '<input type="text" name="{{$prop}}" value="{{$val}}" {{$required}} {{$pattern}} {{$readonly}}>'},
number : {html: '<input type="number" name="{{$prop}}" value="{{$val}} {{$required}} {{$pattern}} {{$readonly}}">'},
array : {html: '<span class="{{$name}}"></span>', oml:'{"default .{{$name}}:Tags":{"name" : "{{$prop}}", "current_tags":{{$val}} }}'}
}
}
You can overwrite each type as you like. In this config, booleans are handled via a
Switch
, strings and number viaHTML input
, and arrays viaTags
. To overwrite, simply edit the object
OGX.Form.defaults
To create a dynamic form (from an Object) from within a
Uxi
let obj = {name:'something', weight:55, sizes:['small', 'medium', 'large']};
let form_instance = OGX.Form.fromObject(obj, this, '.my_selector');
form_instance.onChange = function(obj){ ... };
You can also pass a config object for the entire form, when creating the instance
let form_instance = OGX.Form.fromObject(obj, this, '.my_selector', {validate:true, fields:{
name:{
readonly: false,
required : true,
pattern: '[0-9]+',
fullpath: false,
... all other properties from default config
}
});
For more information about the config object, scroll down to
Config
. Note thatreadonly
,pattern
,required
,fullpath
are only available when creating a dynamic form.
fullpath
when set totrue
will display the entire path to the propery, such as
{server:{version:'1.0.0'}}
Will output as label
server.version
You can also bind a form to
Form
which will prevent the default submit behavior.
OGX.Form.bindForm(_CONFIG_);
OGX.Form.unbindForm(_SELECTOR_); //If `_SELECTOR_` is not passed, the method acts as a shortcut to `unbindAll('form')`
OGX.Form.unbindAll('form');
Note that omitting to pass a selector to
unbindForm
will unbind all forms
{
el:_SELECTOR_, //Mandatory, the selector
allowed:false, //Optional, see fields
forbidden:false, //Optional, see fields
change_cb:_FUNCTION_, //Optional, callback fired upon change
submit_cb:_FUNCTION_ //Optional, callback fired upon submit,
validate:_BOOL_, //Optional, validates the form on submit,
diff:_BOOL_, //Optional, if set to true, only triggers a change when a value of the form changes,
params: * , //Optional parameters to pass,
elem_types:_ARRAY_, //Optional, the list of element types to consider a child of the form, defaults to ['input', 'textarea'],
wait:_INT_, //Optional, overwrite the field wait time globally
}
In this case, config is an general configuration object that overrides fields settings unless specified, such as
OGX.Form.bindForm({
el:'#myForm',
forbidden:/<>/,
wait:500,
change_cb:onChange,
submit_cb:onSubmit,
fields:{
body:{
wait:50
}
}
});
You can also set any of the flags available at form level or at field level.
OGX.Form.bindForm({
el:'#myForm',
forbidden:/<>/,
wait:500,
change_cb:onChange,
submit_cb:onSubmit,
fields:{
body:{
wait:50
forbidden:/<>[0-9]/,
multiline:true
}
}
});
This configuration will listen to all fields of the form
#myForm
, forbid entry of <> chars on all fields, wait 500ms to consider that a field has changed after user last input for all fields BUT the field that has 'body' as name, which only waits 50 ms after last user input to trigger a change.
OGX.Form will return a JSON object composed by the names of the fields as properties and their value such as
<form id="myForm">
<input type="text" name="first_name" placeholder="First Name" val="John">
<input type="text" name="last_name" placeholder="Last Name" val="Green">
<input type="submit" value="send">
</form>
Will return
{
obj:{first_name:"John", last_name:"Green"},
el:_HTML_ELEMENT_
}
by either going the callback route in the form config
function onSubmit(__data, __extra_param){
console.log('user wants to send out', __data.obj);
}
or by listening for a change
OGX.Form.bindForm('#myForm');
$('#myForm').on('change', function(__e, __data){
console.log('user wants to send out', __data.obj);
});
Do not forget to unbind your form when/if you destroy your view
OGX.Form.unbindForm('#myForm');
The callback or event is going to also be fired when a field of the form changes (via bindField)
You can also update a bind configuration at runtime. To look up a bind, use
let bind = OGX.Form.getBind(SEARCH_STRING);
Note that
SEARCH_STRING
searches over selectors.
To update a bind configuration
OGX.Form.updateBind(SEARCH_STRING, OBJECT);
A practical example
OGX.Form.updateBind('zip', {mask:'%%% %%%'});
You can also populate a form given an object. Note that all input elements of the form must have a name attribute declared that matches a property of the given object. Also note that select isn't supported mainly because it is replaced by Roulette
OGX.Form.populate('#myForm', obj);
Note that
populate
also supports deep paths, such as
<input type="text" name="created.date">
will be populated from
{created:{date:'1980-01-01'}, ...}
Populate also supports an optional
map
object to be used to transform data before populating. Each value of the map object must be a function. Here we add decimals to a total.1.15.0+
OGX.Form.populate('#myForm', {total:100}, {total:OGX.Data.addDec});
You can also validate a form if the native HTML5 validation is not available (like on iOS Webview at the time this documentation is being written). Note that it still requires the
pattern
and requiredattributes
.
let validation = OGX.Form.validate(_SELECTOR_);
Will return an object composed by names of failing fields as properties, such as
{login:false, password:false, ....}
If you wish to have an automatic validation upon submit, you can set the flag
validate
to true in the form config. In this case, a property is added to the object passed to your submit call back, such as
{
obj:{first_name:"John", last_name:"Green"},
el:_HTML_ELEMENT_,
valid:true|false,
error:_OBJECT_ //only if !valid
}
You can force a bound form to trigger the
cb_change
callback by doing
OGX.Form.change('#my_form');
Binding a text field (and variants such as tel, email, password...) is generally used if you want to save the information that was entered by the end user, without requiring to tap/click on a button or any other step to save the data.
OGX.Form.bindField(_CONFIG_);
OGX.Form.unbindField(_SELECTOR_); //if `_SELECTOR_` is not passed, the method acts as a shortcut to `unbindAll('field')`
OGX.Form.unbindAll('field');
The expected CONFIG object is as follow
{
el:false, //Mandatory, the selector
allowed:Regex, //Optional, allowed chars, defaults to /[0-9a-zA-Z‘’'"à-úÀ-Ú\\-\\!\\.\\?\\#\\@\\$\\:\\(\\)\\/_,;%' ]/
forbidden:false, //Optional, regex, forbidden chars
mask:false, //Optional, see masking
mask_char:_STRING_, //Optional, the char to use for the masking, see masking
paste:true, //Optional, allow paste
autocomplete:true, //Optional, allow autocomplete
multiline:false, //Optional, multiline
submit: false, //Optinal, if the field triggers a submit when pressing enter/return
validate:false, //Optional, return a valid flag based on pattern attribute
input_cb:false, //Optional, the callback to call upon input change
change_cb:false, //Optional, the callback to call upon field value change
wait:1000, //Optional, the delay before a change is considered a change
diff:true, //Optional, only triggers change if the field value after wait differs
max:2500, //Optional, the max length for the value
type:'string|number|int|bool|json', //Optional, forces a type
params:null, //Optional extra parameters
}
Binding a field listens to its changes and broadcasts (or calls a callback) the change after a certain time. It also broadcasts (or calls a callback) if the key enter is pressed.
In the following example, we listen to a field that will call a function once the value of the field is considered final either by waiting 1500ms after the last input or by pressing return
function onFieldChange(__obj, __extra_param){
//passes
{
obj:{property:value},
property:value
value:value,
el:_HTML_ELEMENT_
}
//such as, for a field named "first_name"
{
obj:{first_name:'Jack'},
property:'first_name',
value:'Jack',
el:_HTML_ELEMENT_
}
}
OGX.Form.bindField({
el:'input[name="first_name"]',
change_cb:onFieldChange,
wait:1500
});
If you don't want to use callbacks, you can listen to your field as usual and the "change" event will be replaced by
Form
"change" event and will fire after 1500ms or by pressing the return key.
$('input[name="first_name"]').on('change', function(__e){
console.log($(this).val()); //The value of the field
});
The input_cb is fired when the user presses a key (same as 'input' event) if you wish to use this shortcut.
There are two ways to restrict inputs on fields. You either pass the allowed and/or forbidden flags in the config of a bind while binding a field, or you can use the restrictField method. It is recommended to always use the bindField method but if you only want to restrict and not listen to this field, you can use the (smaller) restrictField method.
You can also restrict the input on any element (input fields and contenteditable elements), if you wish, for instance, to allow only certain characters to be typed.
OGX.Form.restrictField(_CONFIG_);
OGX.Form.unrestrictField(_SELECTOR_);
So to restrict to letters only with a max of 100 characters, pass
let config = {el:'input[name="first_name"]', allowed:/[a-zA-Z]/, max:100};
If you'd rather work with forbidden chars, use the forbidden parameter instead and omit the allowed parameter
let config = {el:'input[name="first_name"]', forbidden:/[<>]/, max:100};
Note that if allowed if set, forbidden will be ignored.
You can also use the pattern attribute for input fields, in this case, the regular expression from this attribute super classes the options and the forbidden flag will be ignored.
Also you can set the parameter autocomplete to true if you want to allow auto complete and paste if you want to allow paste on the field.
You also mask a field by setting a mask such as (in case of a North American phone number)
{..., mask:'%%%-%%%-%%%%', mask_char:'%', ...}
Note that the default mask_char is already set to '%' but you can change it to whatever you want.
To enable all listeners
OGX.Form.enable();
To enable all fields of a form
OGX.Form.enableForm('#myform');
To enable all fields of all bound forms
OGX.Form.enableForm();
To disable all listeners
OGX.Form.disable();
To disable the fields of a form
OGX.Form.disableForm('#myform');
To disable all fields of all bound forms
OGX.Form.disableForm();
Convert form data to object by using the
name
property of fields
let obj = OGX.Form.toObj('#myForm');
To skip the disabled/readonly elements
let obj = OGX.Form.toObj('#myForm', true);
Unbind everything
OGX.Form.unbindAll(_TYPE_); //String
The expected
_TYPE_
is eitherall
,form
orfield