loading... Pacem JS

Forms are pivotal in Pacem JS. Since nobody loves implementing forms, Pacem JS aims to include functionalities for as may use case as possible. More features are yet to come.
We'll skip standard static laydown of forms and fields, since you can grasp the basics by lurking into the code of the following - hopefully more interesting - examples.

Form nesting

<pacem-form> elements can be nested so that validity and dirtyness may propagate upwards up to the containing form.

Form (auto)generation

Forms can be autogenerated via proper metadata.

"Proper" metadata are defined below:

type DisplayMetadata = {
    name: string, description?: string, short?: string, watermark?: string, null?: string, ui?: string, format?: string,
    css?: { [name: string]: string },
    cssClass?: string[],

type ValidatorMetadata = { type: string, errorMessage: string, params?: any };

type PropertyMetadata = {
    prop: string,
    type: 'object' | 'array' | string,
    display?: DisplayMetadata,
    extra?: any,
    isReadOnly?: boolean,
    dataType?: string,
    isComplexType?: boolean,
    isNullable?: boolean,
    validators?: ValidatorMetadata[],
    props?: PropertyMetadata[]
type TypeMetadata = {

    display?: DisplayMetadata,
    props: PropertyMetadata[],
    type?: 'object' | 'array'

Metadata-generated forms are convenient in many ways:

Here's the mise en place:

{ "display": { "cssClass": ["pacem-grid", "grid-tiny-colgap", "grid-no-rowgap", "pacem-margin", "margin-bottom-0"] }, "props": [ { "prop": "Username", "type": "text", "display": { "watermark": "your username here...", "cssClass": ["pacem-cell"] }, "validators": [ { "type": "required", "errorMessage": "field is required" }, { "type": "email", "errorMessage": "field is not well formed", "params": { "pattern": "^[\w\.-]+$" } }, { "type": "length", "errorMessage": "length must be between 2 and 10", "params": { "max": 10, "min": 2 } } ] }, { "prop": "Password", "type": "password", "display": { "cssClass": ["pacem-cell", "cols-6", "cols-xs-12"] }, "validators": [ { "type": "required", "errorMessage": "field is required" } ] }, { "prop": "PwdRepeat", "type": "password", "display": { "name": "Password (confirm)", "cssClass": ["pacem-cell", "cols-6", "cols-xs-12"] }, "extra": { "dependsOn": [{ "prop": "Password"}]}, "commands": [ { "name": "copy", "icon": "file_copy", "tooltip": "copy to clipboard", "cssClass": ["button"], "dependsOnValue": true }, { "name": "go", "icon": "keyboard_arrow_right", "tooltip": "dummy", "cssClass": ["button"], "prepend": false } ], "validators": [ { "type": "compare", "errorMessage": "the two password fields are not equal", "params": { "to": "Password", "operator": "equal" } } ] }, { "prop": "Height", "type": "float", "display": { "name": "Height (m)", "cssClass": ["pacem-cell"] }, "validators": [ { "type": "range", "errorMessage": "height must be between 1.0m and 2.5m", "params": { "max": 2.5, "min": 1.0 } } ] } ] }


Form usually behaves proactively to the user: by default it hints the invalid fields from the beginning and - when autogenerated - binds the submit and reset buttons to the current status of the form (validity, dirtiness, ...).
This default behavior can be changed by changing the value of the following properties:


Form fields appearance can be tweaked using the css classes embedded in the css theme:


When .form-minimal is applied to the whole form or .field-minimal is applied to a specific field:


When .field-outline is applied to a specific field:


When .form-nolabels is applied to the whole form or .field-nolabel is applied to a specific field:

Label visibility can depend on screen size: .form-xs-nolabels, .field-xs-nolabel, ..., .form-4k-nolabels, .field-4k-nolabel.
Label visibility can be punctually overridden by setting .field-label css class on a specific field (screen size dependencies also included: .field-xs-label, ...).


By default, input fields are constrained to a specific width only for large screens.
By setting the .field-stretch css class on a specific field, yo can break this rule.

{ "display": { "cssClass": ["pacem-grid", "grid-nospace", "grid-no-rowgap", "form-minimal", "form-xs-nolabels", "pacem-pad", "pad-left-1"], "name": "Sign In" }, "props": [ { "prop": "email", "dataType": "emailaddress", "type": "string", "display": { "cssClass": ["pacem-cell", "field-outline"], "name": "E-mail", "watermark": "name@email.com..." }, "validators": [ { "type": "required", "errorMessage": "required field" } ] }, { "prop": "password", "dataType": "password", "type": "string", "display": { "cssClass": ["pacem-cell", "field-outline"], "name": "Password", "watermark": "password..." }, "validators": [ { "type": "required", "errorMessage": "required field" } ] }, { "prop": "rememberMe", "type": "boolean", "display": { "cssClass": ["pacem-cell", "field-nolabel"], "watermark": "Remember me on this device" } } ] }