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 yet Meteor 3.0 compatible, while the previous pwix:core-app.FormChecker family was already async-ready.
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 mutualized, and so are all 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 included in a panel, and will be managed by a Forms.Checker associated to this panel.
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.
Installation
This Meteor package is installable with the usual command:
meteor add pwix:forms
Usage
1 import { Forms } from 'meteor/pwix:forms'; 2 3 const panel = new Forms.Panel({ 4 username: { 5 js: '.js-username' 6 }, 7 loginAllowed: { 8 js: '.js-login-allowed' 9 } 10 }); 11 12 const checker = new Forms.Checker( self, { 13 panel: panel.iPanelPlus( fieldsSet ), 14 data: { 15 item: Template.currentData().item 16 } 17 });
Provides
Forms
The exported Forms global object provides following items:
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.
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.
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.
Classes
Forms.Checker
This is the class which manages all the checks to be done in a panel, publishing relevant messages if any.
It should be instanciated as a ReactiveVar when the DOM is rendered.
Example:
1 Template.myPanel.onRendered( function(){ 2 const self = this; 3 // initialize the Checker for this panel as soon as we get the parent Checker 4 self.autorun(() => { 5 const parentChecker = Template.currentData().checker.get(); 6 const checker = self.APP.checker.get(); 7 if( parentChecker && !checker ){ 8 self.APP.checker.set( new Forms.Checker( self, { 9 parent: parentChecker, 10 panel: self.APP.panel, 11 data: { 12 item: Template.currentData().item 13 } 14 })); 15 } 16 }); 17 });
Instanciation arguments:
-
self:- 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
-
an optional arguments object with following keys:
name: an optional instance nameparent: an optional parent Checker instancemessager: an optional IMessager implementationthis is a caller's design decision to have a message zone per panel, or globalized at a higher level caller doesn't need to address a globalized messager at any lower panel: it is enough to identify the parent Checker (if any)
panel: an optional Panel instance which defines the managed fieldsdata: an optional data opaque object to be passed to check functions as additional argumentid: when the panel is array-ed, the row identifier; will be passed as an option to field-defined check function$ok: an optional jQuery object which defines the OK button (to enable/disable it)okFn( valid<Boolean> ): an optional function to be called when OK button must be enabled/disabledfieldTypeShow: 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 setfieldStatusShow: whether and how to display the result indicator on the right of the field; only considered if the corresponding package configured value is overridablesetForm: if set, the item to be used to fill-in the form at startup, defaulting to nonevalidityEvent: if set, the event used to advertise of each Checker validity status, defaulting to 'checker-validity'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'enabled: whether the new checker will start with checks enabled, defaulting to true; a disabled Checker also stops messages up propagationcrossCheckFn: if set, a cross check function or an array of cross check functions to be called after each individual field check when this later returnsnull(aka not any message)
Only available on the client.
crossCheckFn note:
The Checker behaviour is to call the defined field check function each time the corresponding input handler is run. The field check function should only check for an intrinsic validity as this is the source of the displayed field status. Nonetheless, cross checks are always needed to check one field against another, and so on. The result messages are pushed as usual, but do not change the fields status.
When installed at checker instanciation, the crossCheckFn function is called with the configured data.
The Checker has also a Checker.crossCheckFn() method which let any caller to add a cross check function to the checker. All functions are pushed in array, and called one by one in this same order. These functions can bring their own data arguments, which defaults to the data attached to the checker.
crosscheckFn protoype is: async crossCheckFn( data<Any>, opts<Object> ): null|Array<TypedMessage>.
Forms.Messager
Display the messages resulting from the done checks, as a stack ordered by level order first, and push time order then.
Forms.Panel
Let the calling application defines the fields managed in the panel, taking most of its values from a previously defined Field.Set object.
Usage:
1 import { Field } from 'meteor/pwix:field'; 2 import { Forms } from 'meteor/pwix:forms'; 3 4const panel = new Forms.Panel({ 5 username: { 6 js: '.js-username' 7 }, 8 loginAllowed: { 9 js: '.js-login-allowed' 10 } 11 }, myCollection.fieldsSet );
Only available on the client.
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
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:
-
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
-
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.4.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 2025, Jul. 8th