amvm-form-models

2.4.3 • Public • Published

amvm-form-models

Installation

npm install amvm-form-models --save

Running tests

npm test

Documentation

Example of form model

export class PersonFormModel {
    constructor() {        
        'name.first': {
            title: 'First name',
            name: 'name.first',
            value: 'John',
            validators: [
                {
                    validator: (value, formModel) => value.indexOf('error') === -1,
                    message: 'this is error for name.first',
                    type: 'error'
                },
                {
                    validator: (value, formModel) => value.indexOf('error') === -1,
                    message: 'this is error for name.first (duplicate)',
                    type: 'error'
                },
                {
                    validator: (value, formModel) => value.indexOf('warning') === -1,
                    message: 'this is warning for name.first',
                    type: 'warning'
                },
                {
                    validator: (value, formModel) => value.indexOf('info') === -1,
                    message: (value) => `this is info for name.first`,
                    type: 'info'
                }
            ],
            getJSON: function(value) { /* Optional function. Function should return value that will be saved into resulting json object */ }
        },
        'name.last': {
            title: 'Last name',
            name: 'name.last',
            value: 'Brown',
            validators: [
                {
                    validator: (value, formModel) => value.indexOf('error') === -1,
                    message: 'this is error for name.last',
                    type: 'error'
                },
                {
                    validator: (value, formModel) => value.indexOf('error') === -1,
                    message: 'this is error for name.last (duplicate)',
                    type: 'error'
                },
                {
                    validator: (value, formModel) => value.indexOf('warning') === -1,
                    message: 'this is warning for name.last',
                    type: 'warning'
                },
                {
                    validator: (value, formModel) => value.indexOf('info') === -1,
                    message: (value) => `this is info for name.last`,
                    type: 'info'
                }
            ]
        },
        'gender': {
            value: 'male',
            title: 'Gender',
            name: 'gender',
            dropdownValues: [
                { value: 'set-null', text: 'Select gender'},
                { value: 'male', text: 'Male'},
                { value: 'female', text: 'Female'}
            ]
        },        
        'isAdult': {
            title: 'Is adult',
            name: 'isAdult',
            value: true // value is boolean
        },
        'age': {
            title: 'Age',
            name: 'age',
            value: 30, // value is number
            validators: [
                {
                    validator: (value, formModel) => value != 1,
                    message: 'this is error for age',
                    type: 'error'
                },
                {
                    validator: (value, formModel) => value != 2,
                    message: 'this is warning for age',
                    type: 'warning'
                },
                {
                    validator: (value, formModel) => value != 3,
                    message: (value) => `this is info for age`,
                    type: 'info'
                }
            ]
        },       
        
        phones: {
            array: true, // set to true if object contains array of metas
            def: {
                name: 'phones[$key]', // $key will be replaced by real unique key
                title: 'Phone',
                validators: [
                    {
                        validator: (value, formModel) => value.indexOf('error') === -1,
                        message: 'this is error',
                        type: 'error'
                    },
                    {
                        validator: (value, formModel) => value.indexOf('warning') === -1,
                        message: 'this is warning',
                        type: 'warning'
                    },
                    {
                        validator: (value, formModel) => value.indexOf('info') === -1,
                        message: 'this is info',
                        type: 'info'
                    }
                ]                
            },
            getJSON: function(meta) { /* Optional function. Function should return value that will be saved into resulting json object */ },
            values: [
                {
                    value: '555',
                    key: 'key1',
                    title: 'Phone',
                    name: 'phones[key1]'
                },
                {
                    value: '333',
                    key: 'key2',
                    title: 'Phone',
                    name: 'phones[key2]'
                },
            ]
        },


        emails: {
            array: true, // set to true if object contains array of metas
            complex: true,  // set to true if object contains array of objects, where each object contains several metas
            def: {
                type: {
                    name: 'emails[$key].type',
                    title: 'E-mail type',
                    validators: [
                        {
                            validator: (value, formModel) => value.indexOf('error') === -1,
                            message: 'this is error for emails[].type',
                            type: 'error'
                        },
                        {
                            validator: (value, formModel) => value.indexOf('warning') === -1,
                            message: 'this is warning for emails[].type',
                            type: 'warning'
                        },
                        {
                            validator: (value, formModel) => value.indexOf('info') === -1,
                            message: 'this is info for emails[].type',
                            type: 'info'
                        }
                    ]
                },
                email: {
                    name: 'emails[$key].email', // $key will be replaced by real unique key
                    title: 'E-mail',
                    validators: [
                        {
                            validator: (value, formModel) => value.indexOf('error') === -1,
                            message: 'this is error for emails[].email',
                            type: 'error'
                        },
                        {
                            validator: (value, formModel) => value.indexOf('warning') === -1,
                            message: 'this is warning for emails[].email',
                            type: 'warning'
                        },
                        {
                            validator: (value, formModel) => value.indexOf('info') === -1,
                            message: 'this is info for emails[].email',
                            type: 'info'
                        }
                    ]

                }
            },
            getJSON: function(objectWithMetas) { /* Optional function. Function should return value that will be saved into resulting json object */ },
            values: [
                {
                    key: 'key1',
                    type: {
                        value: 'Work',
                        title: 'E-mail type',
                        name: 'emails[key1].type'
                    },
                    email: {
                        value: 'user@work.com',
                        title: 'E-mail',
                        name: 'emails[key1].email'
                    }
                },
                {
                    key: 'key2',
                    type: {
                        value: 'Personal',
                        title: 'E-mail type',
                        name: 'emails[key2].type'
                    },
                    email: {
                        value: 'user@personal.com',
                        title: 'E-mail',
                        name: 'emails[key2].email'
                    }
                }
            ]

        },
        
        
        
        _model: {
            validators: [
                {
                    validator: (formModel) => formModel['name.first'].value.indexOf('meta_err') === -1,
                    message: 'this is _model validator',
                    type: 'error'
                },
                {
                    validator: (formModel) => formModel['name.first'].value.indexOf('meta_err') === -1,
                    message: 'this is _model validator',
                    type: 'error'
                },
                {
                    validator: (formModel) => formModel['name.first'].value.indexOf('meta_warn') === -1,
                    message: 'this is _model validator',
                    type: 'warning'
                },
                {
                    validator: (formModel) => formModel['name.first'].value.indexOf('meta_inf') === -1,
                    message: 'this is _model validator',
                    type: 'info'
                }
            ],
            errors: [],
            warnings: [],
            infos: []
        }
    }
}

In this class, name.first property is meta object. Meta object has following properties:

Property Description
value This property will contain value for meta object
title Title of meta object. Usually value of title is used inside <label>
required If set to true, <label> tag will display *
maxlength This value will be set as maxlength attribute on <input> tag
name Value of name property is used for name atribute of input tag
errors[] Array of errors after running all validators against value property
warnings[] Array of warnings after running all validators against value property
infos[] Array of info messages after running all validators against value property
dropdownValues Array of object. Each object should have value and text property. This array can be used to build dropdown with these values.
validators Array if validators. validators property should be added to metas that are not part of array.
getJSON Optional function. If it exists, it will be used to create json for meta/array item.
def Object that describes array item. Array item might contain single meta object or object with multiple meta objects. For arrays, def should have validators array.

phones property is array. Each array item contains meta object with additional member called key.

emails property is array. Each array item contains obejct with key property, and many meta objects. Thats why name property of each meta obejct has format of emails[some_unique_key].%property_name%

_model is special property that contains errors, warnings and infos arrays. These arrays will be created by complex validators in '_model' field. Complex validation does not belong to specific meta. Complex validation validates whole form model.

Resulting JSON will have following shape:

{
    name : {
        first: 'John'
        last: 'Bown'
    },
    isAdult: true,
    age: 30,    
    phones: [
        { 
            key: 'key1', 
            value: '555'
        },
        { 
            key: 'key2', 
            value: '333'
        }
    ],
    emails: [ 
        { 
            key: 'key1', 
            value: { 
                type: 'Work', 
                email: 'user@work.com' 
            }
        },
        {
            key: 'key2',
            value: { 
                type: 'Personal', 
                email: 'user@personal.com' 
            }
        }        
    ]
}

FormModelValidator

getMetaByPath(formModel, path)

Get meta object from formModel by path string.

getValidatorsByPath(formModel, path)

Get array of validators for given path.

pathIsArray(path)

Returns true if path points to array. Example of path: labels[some_unique_key]

parsePathToArray(path)

Takes path that points to array, and returns object with information about array and array meta.

Example of calling parsePathToArray('labels[key2]'):

{
    itemKey: 'key2', //unique_key_of_array_item'
    pathToArray: 'labels', //name_of_array_property_on_form_model
    arrayItemIsMeta: true,  //true if arrray item is meta object and contains key property
    metaPropertyName: null, //name of array item property that contains meta, if arrayItemIsMeta is false    
}

Example of calling parsePathToArray('emails[key2].email'):

{
    itemKey: 'key2', //unique_key_of_array_item'
    pathToArray: 'emails', //name_of_array_property_on_form_model
    arrayItemIsMeta: false,  //true if arrray item is meta object and contains key property
    metaPropertyName: 'email', //name of array item property that contains meta, if arrayItemIsMeta is false
}

getArrayIndexByKey(formModelArray, key)

Returns index of array item that contains passed unique key

isMetaValid(formModel, path)

Function finds meta by path, and runs validators against meta's value. If validator returns false, we add message to errors or warnings or infos array depends on the type. Returns true if meta object is valid.

isModelValid(formModel, stopOnFirstError)

Function takes all validators and validates corresponding meta object in form model. While validating, errors, warnings and infos properties of each meta is filled of validation messages. If stopOnFirstError is set to true (default is false), then validation process stops after first meta object is invalid. Returns true if form model is valid.

getErrors(formModel)

Function accepts form model and return plain json object with errors, warnings and infos. Example of return value:

{
    'name.first': {
        errors: ['msg', 'msg'],
        warnings: ['msg', 'msg'],
        infos: ['msg', 'msg'],

    },
    'emails[key2].type': {
        errors: [ 'msg' ],
        warnings: [ 'msg' ],
        infos: [ 'msg' ]
    },
    'emails[key2].email': {
        errors: [ 'msg' ],
        warnings: [ 'msg' ],
        infos: [ 'msg' ]
    },
    'phones[key2]': {
        errors: [ 'msg']
    },
    '_model': {
        errors: ['msg', 'msg'],
        warnings: ['msg', 'msg'],
        infos: ['msg', 'msg'],

    },
}

replaceErrors(formModel, errors)

Function takes errors as argument, and replaces errors/warnings/infos in form model with passed errors object. errors is an object in following format:

{
    'name.first': {
        errors: ['msg', 'msg'],
        warnings: ['msg', 'msg'],
        infos: ['msg', 'msg'],

    },
    'emails[key2].type': {
        errors: [ 'msg' ],
        warnings: [ 'msg' ],
        infos: [ 'msg' ]
    },
    'emails[key2].email': {
        errors: [ 'msg' ],
        warnings: [ 'msg' ],
        infos: [ 'msg' ]
    },
    'phones[key2]': {
        errors: [ 'msg']
    },
    '_model': {
        errors: ['msg', 'msg'],
        warnings: ['msg', 'msg'],
        infos: ['msg', 'msg'],

    },
}

objectIsMeta(obj)

Returns true if object has value of type string, number or boolean.

getOrCreateNestedObjects(json, path)

Function takes json object, and adds nested object by path. Function return deepest object created.

Example: getOrCreateNestedObjects({}, 'contactInfo.address.city ') will create following object:

{
    contactInfo: {
        address: {
        }
    }
}

Warning: city will not be added as object

getOrCreateNestedArray(json, path)

Function takes json object, and adds array to json. Function returns created array.

Example: getOrCreateNestedArray({}, 'contactInfo.labels') will create following object:

{
    contactInfo: {
        labels: []
    }
}

getJSON(formModel)

Function converts form model into json object. Following rules are applied:

First, _model object is deleted from form model. It is used to display complex validation errors on web page.

Next, form models properties that are arrays, are converted into array on json. Meta properties converted into simple key/value property for json. If form model meta has function that creates custom json, it will be used to create value for json part.

getDoc(formModel, fnTypeConverter)

Function converts form model into json object that will go into database. Following rules are applied:

First, _model object is deleted from form model. It is used to display complex validation errors on web page.

Next, form models properties that are arrays, are converted into array on json. Meta properties converted into simple key/value property for json. If form model meta has function that creates custom json, it will be used to create value for json part. All keys from arrays are removed.

removeKeysFromArrays(formModelJson)

Removes keys from arrays inside JSON object

hasExistingErrors(formModel)

Function returns true if form model has errors (validators will not be run agains form model field).

createArrayValue(formModel, path, initObject)

Function creates array item based on def property. New aray item can be initialized using initObject.

deleteArrayValue(formModel, path, key)

Function deletes array item with specific key

Server helpers

Creating form model

createFormModel

createFormModel(json, fnFormModel, fnPostProcess);

This function accepts json from client and creates form model and returnes json from that form model.

Property Description
json JSON that came from client.
fnFormModel Form model constructor function. This constructor function accepts json and creates form model with values from that json. Extra properties in json are ignored when building form model. Same constructor function has to be used on the client to create json.
fnPostProcess Function that will be called after json is created. This function can be used to modify json.

Result of this function call:

 {
    isValid: true|false,
    json: {...},
    getJSON: () => json,
    getDoc: () = > json,
    errors: {...},
    formModel: {...}
}

isValid is set to true if after creating form model with json, form model can be successfully validated using fnFormModelValidators.

json is JSON object created from form model.

getJSON function that creates json and returns it.

getDoc function that creates json with correct types and returns it.

errors is errors object created by calling FormModelValidator.getErrors(formModel) is isValid is false.

formModel is form model created from json

Readme

Keywords

Package Sidebar

Install

npm i amvm-form-models

Weekly Downloads

3

Version

2.4.3

License

MIT

Last publish

Collaborators

  • amvmdev