pwix:forms
What is it ?
A package to manage forms in Meteor.
Ideally this would be an extension of aldeed:autoform, but this later is not (at the moment) Meteor 3.0 compatible, while the previous pwix:core-app.FormChecker family was already async-ready.
It aims to provide a dynamic user interface where the user can easily see the result of his/her changes.
Conceptuals
At the root of all, we have individual fields.
Each field must be checked both on client side, and on server side. Check functions are thought to be mutualized, and so are most probably aysnc.
Fields must be checked each against others at the level of the display unit (what the user actually sees). For example, in a tabbed page, each tab should be created and organized following a business logical, and so should the checks (and the error messages).
In the above example, the whole page should be checked for consistency, so another level of checks.
And, because a tab may itself include a tab, which itself may include another level of tabs, and so on, there must not be any limit to the count of levels of checks.
So each field definition (see below) can be attached to a checker, and will be managed by the Forms.Checker.
Each Forms.Checker may itself be a child of some other Forms.Checker (for example the page of tabbed panes) up to having no more parent. We build an arbitrary depth of Forms.Checker's hierarchy.
So the Forms.Checker both manages individual fields directly attached to it, and then propagates to its collaterals and its parents.
Messages are stacked, and the most recent or the most important is shown first.
Installation
This Meteor package is installable with the usual command:
meteor add pwix:forms meteor npm install lodash @vestergaard-company/js-mixin --save
Usage
1 import { Forms } from 'meteor/pwix:forms'; 2 import { ReactiveVar } from 'meteor/reactive-var'; 3 import { Tracker } from 'meteor/tracker'; 4 5 Template.my_app_template.onCreated( function(){ 6 const self = this; 7 self.checker = null; 8 self.fields = { 9 username: { 10 js: '.js-username' 11 }, 12 loginAllowed: { 13 js: '.js-login-allowed' 14 } 15 }; 16 }); 17 18 // because checker initialization is an async task, we have to guard against re-running the same piece of code before having set the variable 19 // because app wants a single checker as soon as it has got the ad-hoc data context, the computation is stopped when done 20 // because Forms installs an autorun() to advertise of checker validity and status, we must run under the nonreactive() protection 21 22 Template.my_app_template.onRendered( function(){ 23 const self = this; 24 let running = false; 25 this.autorun(( comp ) => { 26 let checker = self.checker; 27 if( !checker && !running ){ 28 running = true; 29 Tracker.nonreactive(() => { 30 checker = new Forms.Checker( self ); 31 checker.init({ 32 parent: Template.currentData().checker.get(), 33 data: { 34 item: Template.currentData().item 35 }, 36 panel: { 37 fields: self.fields, 38 set: app.fieldSet 39 } 40 }).then(() => { 41 self.checker = checker; 42 comp.stop(); 43 }); 44 }); 45 } 46 }); 47 });
Provides
Forms
The exported Forms global object provides following items:
Classes
Forms.Checker
This is the class which manages all the checks to be done in a panel, publishing relevant messages if any.
It may be instanciated as a ReactiveVar when the DOM is rendered, so that other code can reacts when it has been instanciated.
Only available on the client.
Forms.Checker.Checker( <Blaze.TemplateInstance> ): <Forms.Checker>:
Instanciation takes a single argument which is the current Blaze.TemplateInstance instance:
-
let us defines autorun() functions
-
provides a '$' jQuery operator which is tied to this template instance
-
provides the DOM element which will act as a global event receiver
-
provides the topmost DOM element to let us find all managed fields.
async Forms.Checker.init( <Object> ): <Forms.Checker>:
Before to be useful for anything, the Forms.Checker MUST be initialized, even with no or an empty object argument.
The argument object is optional, and may contain following keys:
-
check: whether a first check() is run at end of the initialization, defaulting totrue -
crossCheckRegisterFn: if set, a cross check function or an array of cross check functions to be called when the checker is valid (aka not any message);Formspropagate this function call up to the topmost checker of the hierarchy prototype isasync crossCheckFn( data<Any>, opts<Object> ): null|Array<TypedMessage> -
data: an optional opaque object to be passed to field-defined functions as second argument, or cross check function as first argument -
enabled: whether the new checker will start with checks enabled, defaulting totrue; a disabled Checker doesn't check nor propagates -
fieldStatusShow: whether and how to display the result indicator on the right of the field, eitherfalseor a value fromForms.C.ShowStatus; only considered if the corresponding package configured value is overridable -
fieldTypeShow: whether to display a field type indicator on the left of each field; this value overrides the configured default value; it only applies if the field is itself qualified with a 'type' in the Forms.FieldType set -
messager: an optionalForms.IMessagerimplementationthis is a caller's design decision to have a message zone per form panel, or globalized at a higher level; in this later case, caller doesn't need to address the globalized messager at any lower panel level: it is enough to identify it at the parent Checker level (if any); the up-propagation will eventually feed the messager.
-
name: an optional instance name -
onFieldUpdateRegisterFn: if set, a function or an array of functions to be called on each field update; Forms propagate this function call up to the topmost checker of the hierarchy prototype isasync onFieldUpdateFn( data<Any>, opts<Object> ): void -
onValidityChangeRegisterFn: if set, a function or an array of functions to be called when the validity of the checker changes prototype isasync onValidityChangeFn( valid<Boolean> ): voidthis used to be aokFn()function argument, which has been deprecated starting with v1.6 -
panel: an optional object which describes the fields to be managed, with following keys:-
fields: the fields to be managed in this form panel, as an object indexed by the fields name -
set: an optionalField.Setobject which will provide default definitions for the fields.
-
-
parentChecker: an optional parent Checker instance this used to beparent, which has been deprecated starting with v1.6 -
parentClass: if set, the class to be set on the parent DIV inserted on top of each field, defaulting to 'form-indicators-parent' -
rightSiblingClass: if set, the class to be set on the DIV inserted just after each field, defaulting to 'form-indicators-right-sibling' -
rowId: when the panel is array-ed, the row identifier; will be passed as an option to field-defined check functions this used to be anidargument, which has been deprecated starting with v1.6 -
trace: whether to be verbose on the execution, defaulting tofalse -
validityObject: if set, a JQuery object which will be automatically enabled/disabled on validity changes this used to be a$okargument, which has been deprecated starting with v1.6
Forms.Messager
Display the messages resulting from the done checks, as a stack ordered by level order first, and push time order then.
Functions
Forms.configure()
See below.
Forms.i18n.namespace()
Returns the i18n namespace used by the package. Used to add translations at runtime.
Available both on the client and the server.
Interfaces
Forms.ICheckable
An interface whichs adds to the implementor the capability of being checked (i.e. have a check() function), and to provide the expected result. It so has too a status and a validity.
Each implementation instance is provided a random unique identifier at instanciation time. This identifier let us manages the published TypedMessage's by emitter.
Both Checker and FormField classes implement this interface.
Main available methods are:
Forms.ICheckable.iCheckableId()
Returns the internal identifier of this ICheckable.
Forms.ICheckable.iCheckableTMsResult()
Returns the last check result of this ICheckable, as an array of TypedMessage's, or null.
Forms.ICheckable.iCheckableStatus()
Returns the last FieldStatus of this ICheckable, may be FieldStatus.C.NONE.
Forms.ICheckable.iCheckableValidity()
Returns the last true|false validity of this ICheckable.
Forms.IMessager
A simple interface to let the calling application manage the stack of messages provided by the check functions.
Available methods are:
Forms.IMessager.iMessagerClear()
Clear the message displayed in the message zone.
Forms.IMessager.iMessagerDump()
Dump the full content of the messages stack.
Forms.IMessager.iMessagerFirst()
Returns the first pushed message in level order.
Forms.IMessager.iMessagerLast()
Returns the last pushed message in level order.
Forms.IMessager.iMessagerPush( message<TypedMessage>, id<String> )
Push a new message to the messages stack.
Forms.IMessager.iMessagerRemove( ids<Array> )
Remove from the messages stack those published by the provided ICheckable identifiers.
Blaze components
FormsStatusIndicator
Display an indicator about the check status of a field.
Parameters:
-
statusRv: a mandatory ReactiveVar which contains the ShowStatus to be displayed, among the possible values:Forms.FieldStatus.C.INVALID,Forms.FieldStatus.C.UNCOMPLETE,Forms.FieldStatus.C.VALID,Forms.FieldStatus.C.NONE.
-
classes: if set, a list of classes to be added to the default -
title: if set, a text to replace the default title -
invalidButton: if set to true, theForms.FieldStatus.C.INVALIDstatus is displayed as a button -
uncompleteButton: if set to true, theForms.FieldStatus.C.UNCOMPLETEstatus is displayed as a button -
validButton: if set to true, theForms.FieldStatus.C.VALIDstatus is displayed as a button -
buttonOnClick: a function to trigger on click on button
FormsTypeIndicator
Display an indicator about the type of a field.
Parameters:
-
type: a constant among:Forms.FieldType.C.INFO,Forms.FieldType.C.OPTIONAL,Forms.FieldType.C.MANDATORY,Forms.FieldType.C.WORK.
-
classes: if set, a list of classes to be added to the default -
title: if set, a text to replace the default title
FormsMessager
Display the last pushed TypedMessage, depending of its level ordering.
Parameters:
-
messager: an
Forms.IMessager-compliant object -
classes: classes to be added to the displayed message whatever be its type, defaulting to none
Events
Following events are sent by the package:
-
forms-checker-initializedOn the Blaze topmost DOM element of the checker.
Sent at the end of the initialization.
Held data is:
checkercheckableIdstatusvalidity
-
forms-checker-updateOn the Blaze topmost DOM element of the checker.
Sent each time a user input is detected after field checks.
Held data is:
checkercheckableIdstatusvalidityorigin
-
forms-checker-validityOn the Blaze topmost DOM element of the checker.
Sent each time the validity status of the checker changes.
Held data is:
checkercheckableIdstatusvalidity
Configuration
The package's behavior can be configured through a call to the Forms.configure() method, with just a single javascript object argument, which itself should only contains the options you want override.
Known configuration options are:
-
checkerInitializationEventThe event to be fired when a checker is successfully initialized, defaulting to
forms-checker-initialized. -
checkerValidityEventThe event to be fired when the validity of the checker changes, defaulting to
forms-checker-validity. -
fieldStatusShowWhether input fields should have a check status (none/valid/uncomplete/invalid) indicator, where available values are:
-
Forms.C.ShowStatus.NONEDo not show any status indicator
-
Forms.C.ShowStatus.BOOTSTRAPUses the Bootstrap classes to indicate the status. Only applies to fields.
-
Forms.C.ShowStatus.INDICATORUses an icon indicator.
On fields, the package is able to automatically append the indicator on the right of the field.
-
Forms.C.ShowStatus.TRANSPARENTDo not show any status indicator, but make it transparent allowing the user interface to keept a consistent width.
Defaults to
Forms.C.ShowStatus.INDICATOR.pwix:formsis able to automagically add a status indicator on the right of each field, unless this feature is disabled by the package configuration, or at theCheckerlevel, or individually for each field.If the caller wishes an indicator at the panel level, it can use, in place or besides of fields indicators, the
FormsStatusIndicatorBlaze component. -
-
fieldTypeShowWhether input fields should default to be prefixed with a type (mandatory/optional) indicator.
Defaults to
true.This default value can be overriden at the Checker level.
This option only applies if the field is specified with a
typevalue among:Forms.FieldType.C.INFOForms.FieldType.C.MANDATORYForms.FieldType.C.OPTIONALForms.FieldType.C.WORKForms.FieldType.C.NONE
-
showStatusOverridableWhether the previous
fieldStatusShowis overridable when instanciating aCheckeror specifying a field in the panel.Defaults to
true. -
showTypeOverridableWhether the previous
fieldTypeShowis overridable when instanciating aCheckeror specifying a field in the panel.Defaults to
true. -
verbosityDefine the expected verbosity level.
The accepted value can be any or-ed combination of following:
-
Forms.C.Verbose.NONEDo not display any trace log to the console
-
Forms.C.Verbose.CONFIGURETrace
Forms.configure()calls and their result.This is the default.
-
-
warnOnDuplicateNameWhether to warn when a checker duplicate name is detected, defaulting to
false.
Please note that Forms.configure() method should be called in the same terms both in client and server sides.
Remind too that Meteor packages are instanciated at application level. They are so only configurable once, or, in other words, only one instance has to be or can be configured. Addtionnal calls to Forms.configure() will just override the previous one. You have been warned: only the application should configure a package.
Forms.configure() is a reactive data source.
NPM peer dependencies
Starting with v 0.3.0, and in accordance with advices from the Meteor Guide, we no more hardcode NPM dependencies in the Npm.depends clause of the package.js.
Instead we check npm versions of installed packages at runtime, on server startup, in development environment.
Dependencies as of v 1.6.0:
1 'lodash': '^4.17.0', 2 '@vestergaard-company/js-mixin': '^1.0.3'
Each of these dependencies should be installed at application level:
meteor npm install <package> --save
Translations
New and updated translations are willingly accepted, and more than welcome. Just be kind enough to submit a PR on the Github repository.
Cookies and comparable technologies
None at the moment.
Issues & help
In case of support or error, please report your issue request to our Issues tracker.
P. Wieser
- Last updated on 2026, Apr. 2nd