FormGear is a framework engine for dynamic form creation and complex form processing and validation for data collection.

Overview

FormGear is a framework engine for dynamic form creation and complex form processing and validation for data collection. It is designed to work across multiple data collection platforms such as CAPI, CAWI, and PAPI.

About

FormGear is a framework engine for form creation, processing, and validation. FormGear is designed to support official statistics data collection in BPS - Statistics Indonesia, Indonesia's National Statistics Office. It was done by a team under the direction of BPS. This requirement calls for dynamic form creation, complex processing and validation, and ease of use in the data collection process.

FormGear uses a defined JSON object template, thus is easy to build, use, and efficiently handle nested inquiries to capture everything down to the last detail. Unlike other similar framework, validation is handled in a FALSE condition in which each field is validated against a test equation. This leads to a more efficient and effective way of validating each component.

Features

  • Easily create complex form with various form controls.
  • Divide form into several sections for ease during data collection.
  • Create nested form inquiry to accommodate recurring fields.
  • Add conditions to enable form control.
  • Validate answer given during data collection with your own test function.
  • Add remark to record additional information.
  • Add preset to provide information acquired prior to data collection.

Usage

Table of Content

Online examples

Develop on JS Framework examples:

Installation

FormGear can be installed via package manager like npm or yarn, or it can be used directly via CDN.

npm install form-gear
import { FormGear } from 'form-gear'
import {  } from './node_modules/form-gear/dist/style.css'

const data = Promise.all([
                fetch("./data/template.json").then((res) => res.json()),
                fetch("./data/preset.json").then((res) => res.json()),
                fetch("./data/response.json").then((res) => res.json()),
                fetch("./data/validation.json").then((res) => res.json())
                fetch("./data/remark.json").then((res) => res.json())
            ]);

data.then(([template, preset, response, validation, remark]) => initForm(template, preset, response, validation, remark));

function initForm(template, preset, response, validation, remark){
        
   let config = {
      clientMode: 1, // CAWI = 1, CAPI = 2
      token: ``,
      baseUrl: ``,
      lookupKey: `key%5B%5D`,
      lookupValue: `value%5B%5D`,
      username: 'AdityaSetyadi',
      formMode: 1 // 1 => OPEN ; 2 => REJECTED ; 3 => SUBMITTED ; 4 => APPROVED ;
   }
   
   let uploadHandler = function (setter) {
      console.log('camera handler', setter);
      cameraFunction = setter;
      openCamera();
   }

   let GpsHandler = function (setter, isPhoto) {
      console.log('camera handler', setter);
      isPhoto = true,
         cameraGPSFunction = setter;
      openCameraGPS(isPhoto);
   }

   let onlineSearch = async (url) =>
      (await fetch(url, setBearer())
         .catch((error: any) => {
            return {
               success: false,
               data: {},
               message: '500'
            }
         }).then((res: any) => {
         if (res.status === 200) {
            let temp = res.json();
            return temp;
         } else {
            return {
               success: false,
               data: {},
               message: res.status
            }
         }
         }).then((res: any) => {
            return res;
         }
      ));

   let setResponseMobile = function (res, rem) {
      respons = res
      remarks = rem

      console.log('respons', respons)
      console.log('remarks', remarks)
   }

   let setSubmitMobile = function (res, rem) {
      respons = res
      remarks = rem

      console.log('respons submit', respons)
      console.log('remarks submit', remarks)
   }

   let openMap = function (koordinat) {
      koordinat = koordinat

      console.log('coordinat ', koordinat)
   }

   let form = FormGear(template, preset, response, validation, remark, config, uploadHandler, GpsHandler, onlineSearch, setResponseMobile, setSubmitMobile, openMap);
   
   return form;
   
}

Template

FormGear use defined template which is based on JSON Object. This allows for dynamic form creation, letting you to easily build your form with various form controls simply by expanding the JSON object. This also allows FormGear to create nest other form control in other form control, making it easy for you to create recurring questions based on the nested form control. Below is the structure and example of the JSON object that FormGear uses as its form template.

template.json
│   description
│   dataKey
│   title
│   acronym
│   ...
└───components
│   │   section
│   └───components
│       │   textInput
│       │   checkboxInput
│       │   selectInput
│       │   ...
└───
│   │   section
│   └───components
│       │   textInput
│       │   checkboxInput
│       │   nestedInput
│       └───
│           │   sourceQuestion
│           └───components
│               │   textInput
│               │   checkboxInput
│               │   nestedInput
│               └───
│                   │   sourceQuestion
│                   └───components
│                       │   textInput
│                       │   dateInput
│                       │   ...
│               │   ...
│       │
│       │   dateInput
│       │   ...
└───
│   │   section
│   └───components
│       │   textInput
│       │   checkboxInput
│       │   selectInput
│       │   ...
│

[
    {
        "label":"Hobbies",
        "dataKey":"hobbies",
        "type":29,
        "cols":3,
        "options":[
            {
                "label":"Sleeping",
                "value":"1"
            },
            {
                "label":"Play Games",
                "value":"2"
            },
            {
                "label":"Watching Movie",
                "value":"3"
            },
            {
                "label":"Cooking",
                "value":"4"
            },
            {
                "label":"Working",
                "value":"5"
            },
            {
                "label":"Travelling",
                "value":"6"
            },
            {
                "label":"Other",
                "value":"13",
                "open":true
            }
        ]
    },
    {
        "label": "Province",
        "dataKey": "l2_r322_prov_1",
        "typeOption" : 2,
        "type": 27,
        "enableCondition":"Number(getValue('[email protected]$ROW$')) > 0",
        "componentEnable":["[email protected]$ROW$"],
        "sourceSelect":[{
            "id": "f796a32a-36df-4554-bb79-bf8065e28c52",
            "tableName": "kode_kab_ppkk",
            "value": "kode_prov",
            "desc": "nama_prov",
            "parentCondition": [
            
            ]  
        }]
    },
    {
        "label":"Healthy neighborhood rating",
        "dataKey":"rating",
        "type":26,
        "cols":5,
        "options":[
            {
                "label":"",
                "value":"1"
            },
            {
                "label":"",
                "value":"2"
            },
            {
                "label":"",
                "value":"3"
            },
            {
                "label":"",
                "value":"4"
            },
            {
                "label":"",
                "value":"5"
            }
        ]
    },
    {
        "label":"Happiness Index",
        "dataKey":"happy",
        "type":18,
        "range":[
        {
            "min":0,
            "max":100,
            "step":5
        }
        ]
    },
    {
        "label":"Chld nested",
        "dataKey":"childnested",
        "description":"ChildNested",
        "type":2,
        "sourceQuestion":"hobbies",
        "components":[
            [
                {
                    "label":"name--- $NAME$",
                    "dataKey":"name_",
                    "type":4,
                    "expression":"let nm = ''; let list = getValue('hobbies'); if(list !== undefined && list.length > 0) { let rowIndex = getRowIndex(0); let filter = list.filter(obj => obj.value == rowIndex); nm=filter[0].label }; nm;",
                    "componentVar":["hobbies"],
                    "render":true,
                    "renderType":1
                }
            ]
        ]
    }
]

Control Type


FormGear allows you to work with a lot of possible HTML input types. To add a control type, you can simply add the code as a value of the type component as a JSON object and add other corresponding components:

{
   "description":"Interviewing family characteristics individually",
   "dataKey":"family-characteristics-2022",
   "title":"Family Characteristics",
   "acronym":"FC-22.Individu",
   "version":"0.0.1",
   "components":[
		    {
                        "label":"Full Name",
                        "dataKey":"full_name",
                        "hint":"Full name including his degree, position, etc",
                        "answer":"Ignatius",
                        "enableRemark":true,
                        "type":25
                    }
		]
}

FormGear uses numbers as code to define each control type. Below is a table of control types and their corresponding code and description.

Control Type Code Description
Section 1 Adds section to form.
NestedInput 2 Adds nested input field to existing field.
InnerHTML 3 Adds text written in HTML format.
VariableInput 4 Variable input.
DateInput 11 Date input.
DateTimeLocalInput 12 Date and time input field with no time zone.
TimeInput 13 Time input field.
MonthInput 14 Month input field.
WeekInput 15 Week input field.
SingleCheckInput 16 Checkbox input field, lets user choose only one option out of limited choices.
ToggleInput 17 Toggle input.
RangeSliderInput 18 Range slider input, lets user to select a value or range of value from a specified min and max.
UrlInput 19 URL input field.
CurrencyInput 20 Currency input field, limited to IDR and USD.
ListTextInputRepeat 21 Text input field, creating a list by letting user add more written input as needed.
ListSelectInputRepeat 22 Dropdown input field, creating a list by letting user add more choices as needed.
MultipleSelectInput 23 Drop-down input, lets user to choose one or more options of limited choices.
MaskingInput 24 Number input with certain formatting, such as phone number and taxpayer identification number.
TextInput 25 Single-line input field.
RadioInput 26 Radio button, lets user choose one options of limited choices.
SelectInput 27 Drop-down input.
NumberInput 28 Numeric input field.
CheckboxInput 29 Checkbox input field, lets user choose one or more options of limited choices.
TextAreaInput 30 Adjustable text area input field.
EmailInput 31 Email address input field.
PhotoInput 32 Photo input, lets user add picture with .jpg, .jpeg, .png, and .gif format.
GpsInput 33 GPS input.
CsvInput 34 CSV input, lets user upload .csv file to be stored as .json format in the Response. The .csv file can later be downloaded again in the same format.

Component Type


To customize each form control further, you can use components . Below are the components, the corresponding ControlType in which the component can be used, the input or value type of each component, and the description.

Component Type Corresponding ControlType Input Type Description Notes
dataKey All string Component identifier.
label All string Component label that will show up in the form.
hint All string Provide hint on how to fill the corresponding field.
type All ControlType any Define the ControlType of a field.
components 1, 2 ComponentType Store components inside a Section or NestedInput.
rows 30 number Define the number of rows needed in TextAreaInput.
cols 26, 29 number Define the number of columns the options in RadioInput and CheckboxInput will be divided to.
options 22, 23, 26, 29 Option[] Define options for ListSelectInputRepeat, MultipleSelectInput, RadioInput, and CheckboxInput.
range 18 Range[] Define the min, max, and value of each step for a RangeSliderInput.
description 1, 2 string Adds description for a Section or NestedInput.
answer All any Storing answer collected on data collection. ListSelectInputRepeat and MultipleSelectInput must add: [{"label": "lastId#0","value": "0"}]
sourceQuestion 2 string Define the source question for a NestedInput field.
sourceOption 22, 23, 26, 27, 29 string Source of the options used in the field.
typeOption 22, 23, 26, 27, 29 number Type of the options used in the field. 1: Its component, 2: A lookup table, 3: Other component.
currency 20 string Define the currency that will be used in a CurrencyInput field, limited to IDR and USD.
separatorFormat 20 string Define the separator that will be used in a CurrencyInput field.
isDecimal 20 boolean Define whether or not a CurrencyInput field allows decimal.
maskingFormat 24 string Define the format of maskingInput used. 9 for numbers, a for letters, and * for alphanumeric format. e.g. : 'maskingFormat' : '9999-aa99'
expression 4 string A variable expression. getValue function can be used to get the value of other field.
componentVar 4 string[] Define the component(s) used in VariableInput.
render 4 boolean Define whether or not the variable will be rendered.
renderType 4 number Variable output type. 1: single output, 2: array output
enable All boolean Define whether or not a component have a condition(s) that need to be fulfilled before it can be filled.
enableCondition All string An expression to define a condition enabled for the field to be filled. getProp function can be used to get the client mode, getValue function can be used to get the value of other field.
componentEnable All string[] A list of component(s) used in a condition expression.
enableRemark All boolean Define whether or not a component allows a remark.
titleModalDelete 21, 22 string Title of the warning that will show up when user tries to delete an item in ListTextInputRepeat or ListSelectInputRepeat.
contentModalDelete 21, 22 string Content of the warning that will show up when user tries to delete an item in ListTextInputRepeat or ListSelectInputRepeat.

Input for ListSelectInputRepeat, MultipleSelectInput, RadioInput, and CheckboxInput


Option[] defines option components for ListSelectInputRepeat, MultipleSelectInput, RadioInput, and CheckboxInput input.

  • label: label of an option that will show up in the form.
  • value: value of an option that will be recorded.
  • open: define whether or not an option is open-ended. The value recorded will be both the value of an option and the label entered on data collection.
[
    {
        "label":"Hobbies",
        "dataKey":"hobbies",
        "type":29,
        "cols":3,
        "options":[
            {
                "label":"Sleeping",
                "value":"1"
            },
            {
                "label":"Play Games",
                "value":"2"
            },
            {
                "label":"Watching Movie",
                "value":"3"
            },
            {
                "label":"Cooking",
                "value":"4"
            },
            {
                "label":"Working",
                "value":"5"
            },
            {
                "label":"Travelling",
                "value":"6"
            },
            {
                "label":"Other",
                "value":"13",
                "open":true
            }
        ]
    }
]

Input for RangeSliderInput


Range[] defines components of RangeSliderInput input.

  • min: minimum of a range.
  • max: maximum of a range.
  • step: added value for each step.
[
   {
       "label":"Happiness Index",
       "dataKey":"happy",
       "type":18,
       "range":[
            {
                "min":0,
                "max":100,
                "step":5
            }
        ]
    }
]

Input for sourceSelect


sourceOption defines components of sourceSelect input.

  • id: unique identifier of the lookup table that will be used.
  • tableName: the name of the lookup table that will be used.
  • value: the column name in the lookup table that will be recorded as the option’s value.
  • desc: the column name in the lookup table that will be shown as the option’s label.
  • parentCondition: an array consisting of key and value. key refers to the parent lookup table’s value, while value refers to the parent lookup table’s desc.
[
    {
        "label":"Child nested",
        "dataKey":"childnested",
        "description":"ChildNested",
        "type":2,
        "sourceQuestion":"hobbies",
        "components":[
            [
                {
                    "label":"name--- $NAME$",
                    "dataKey":"name_",
                    "type":4,
                    "expression":"let nm = ''; let list = getValue('hobbies'); if(list !== undefined && list.length > 0) { let rowIndex = getRowIndex(0); let filter = list.filter(obj => obj.value == rowIndex); nm=filter[0].label }; nm;",
                    "componentVar":["most_fav"],
                    "render":true,
                    "renderType":1
                }
            ]
        ]
    }
]

Preset

Preset is used to provide prefilled data given prior to data collection. This prefilled data usually obtained from previous data collection or a listing conducted before the actual data collection. Preset consists of dataKey of the corresponding field and the prefilled answer to that field.

preset.json
│
└───predata
│   │
│   └───
│       │   dataKey
│       │   answer
│   │
│   └───
│       │   dataKey
│       │   answer
│
{
   "description":"sample template",
   "dataKey":"sample_tpl1",
   "predata":[
      {
         "dataKey":"nama_lengkap",
         "answer":"Setyadi"
      }
   ]
}

Response

Response is initially empty, and is used to store any response given later during data collection. Response consists of dataKey of the corresponding field and the answer collected from that field. answer from a field that has both label and value will record both. answer will only be collected if the value entered to the corresponding field satisfied both the condition enabled and validation test function. Below is the structure and example of the response JSON object:

response.json
│
│   description
│   dataKey
│   templateVersion
│   validationVersion
│   createdBy
│   editedBy
│   createdAt
│   lastUpdated
└───answers
│   	   │
│   	   └───
│       	│   dataKey
│       	│   answer	
│   	   │
│   	   └───
│       	│   dataKey
│       	│   answer
│

{
   "description":"sample template",
   "dataKey":"sample_tpl1",
   "answers":[
      {
         "dataKey":"agree",
         "answer":true
      },
      {
         "dataKey":"full_name",
         "answer":"Agung"
      },
      {
         "dataKey":"members",
         "answer": {
            "value" : "3",
            "label" : "Clementine Bauch"
         }
      },
      {
         "dataKey":"address",
         "answer":"Jalan Otista"
      },
      {
         "dataKey":"field_usage",
         "answer":[
            {
               "label": "lastId#1",
               "value": "0"
            },
            {
               "label": "Farm",
               "value": "1"
            },
            {
               "label": "Meadows",
               "value": "3"
            }
         ]
      },
   ]
}

Validation

Validation is used to validate the answer given during data collection against a test function. Unlike other similar framework, validation is handled in a FALSE condition, meaning the test function is a condition where the value entered to a form control would be false. Validation has several components you can add:

  • dataKey: component identifier.
  • validations: store validation for each dataKey.
  • componentValidation: a list of the dataKey of components used in the test function.
  • test: the test function. A getValue function can be used to get the value of other field.
  • message: the warning message that will show up when the value entered did not fulfill the test function.
  • type: define whether the validation will be just a warning or an error.

Below are the structure and example of the validation JSON object:

validation.json
│
└───description
│   dataKey
│   version
│   testFunctions
│   │
│   └───
│       │   dataKey
│       │   componentValidation
│       │   validations
│			│
│			└───
│			    │   test
│			    │   message
│			    │   type	
│			│
│			└───
│			    │   test
│			    │   message
│			    │   type
│
{
    "description":"sample template",
    "dataKey":"sample_tpl1",
    "version":"0.0.1",
    "testFunctions":[
        {
            "dataKey":"age",
            "componentValidation":["age"],
            "validations": [
                {
                    "test":"getValue('age') >= 8 && getValue('age') < 10",
                    "message":"Min.10 y.o.",
                    "type":1
                },
                {
                    "test":"getValue('age') < 8",
                    "message":"Min.8 y.o.",
                    "type":2
                }
            ]
        }
    ]
}

Remark

Remark is initially empty and used to store notes on each field collected later during data collection. This note can be used to provide additional information of a field and bypass validation if the data found during data collection doesn’t satisfy the test function. Below is the structure and example of the remark JSON object:

remark.json
│
└───dataKey
|   notes
│   │
│   └───
│       │   dataKey
│       │   comments
│		    │
│		    └───
│		        │   sender
│		        │   dateTime
│		        │   comment	
│		    │
│		    └───
│		        │   sender
│		        │   dateTime
│		        │   comment
│
{
    "dataKey": "",
    "notes": [
        {
            "dataKey": "full_name",
            "comments": [
                {
                    "sender": "AdityaSetyadi",
                    "datetime": "2022-03-17 15:09:54",
                    "comment": "Based on the ID Card"
                },
                {
                    "sender": "AdityaSetyadi",
                    "datetime": "2022-03-18 10:10:40",
                    "comment": "Not the same with his driving license"
                }
            ]
        },
        {
            "dataKey": "land_area#1",
            "comments": [
                {
                    "sender": "AdityaSetyadi",
                    "datetime": "2022-03-18 01:09:15",
                    "comment": "Unknown"
                }
            ]
        }
    ]
}

Contributing

Your assistance is greatly appreciated if you want to contribute and make it better.

Further development ideas:

  • FormGear templates design platform
  • FormGear validation creator platform

License

FormGear is licensed under MIT License.

Our Team

Comments
  • create referenceMap, and mitigation for eval js error in load

    create referenceMap, and mitigation for eval js error in load

    • referenceMap is lookup dictionary for reference index position in list, so i make it to make performace slightly better
    • in formgear there is no mitigation for js eval error, error eval can happen when creating variable input, validation condition, and enable condition, so imake one.
    • Enable condition default value true (in global function)
    • validation condition default value true (in global function)
    • variable input if error, make variabel have value undefined
    opened by cloudwalkerid 1
  • fix wrong blank count

    fix wrong blank count

    The blank count is wrong and in many cases 0. One } is misplaced. I'm not quite sure why we need

    !(JSON.parse(JSON.stringify(element.index[element.index.length - 2])) == 0 && element.level > 1)

    but it does lead to many questions inside sections uncounted.

    opened by jameslao 0
  • Possibility to render nested questions on the same page

    Possibility to render nested questions on the same page

    Would it be possible to render nested questions on the same page instead of going into another page? This can be very helpful for 1 or 2 follow-up questions.

    opened by jameslao 0
  • penambahan informasi periode pendataan

    penambahan informasi periode pendataan

    untuk kegiatan rutin pasti berulang, untuk itu perlu mekanisme untuk menyimpan informasi periode pendataan. misal ketika submit bisa menyimpan informasi periode yang berasal dari template.json Semoga fitur ini bida ditambahkan di kemudian hari. terima kasih

    invalid 
    opened by wirjoadmodjo 1
  • Decouple font from the package?

    Decouple font from the package?

    Hi, the included Montserrat font is lovely but makes the dist CSS file quite large. Would it make sense to remove it from the package so we can load the fonts separately?

    enhancement 
    opened by jameslao 1
  • MultipleSelectInput with open-end answers?

    MultipleSelectInput with open-end answers?

    Is it possible to have open-ended ("Others") answer for MultipleSelectInput? Adding "open" as an option doesn't seem to do anything. Also, adding [{"label": "lastId#0","value": "0"}] seems to put lastId#0 into the box?

    image

    good first issue question 
    opened by jameslao 3
Releases(1.1.1)
  • 1.1.1(Aug 27, 2022)

    FormGear | Ver. 1.1.1

    August 27, 2022

    Optimized Performance

    • Only run validation when it is needed (stop when the component doesn't have any validations or when creating new nested)
    • Remove unnecessary copied variable
    • Change declaration from {} to new Object()
    • Change for ... in with forEach on running validation
    • Use get_compValid filtering
    • Prevent comparing answer and before answer when both values are zero or undefined

    Added

    • Counter attribute in response.json.
      	"counter": 
      		[
      			{
      				"render": 1,
      				"validate": 5
      			}
      		]
      
    • PAPI entry module. Special thanks to Muhammad Qadri - @mqad21 for the idea on pull request #8.
    • Add loader when uploading csv file
    • Add size range for CsvInput
      	"sizeInput": 
      		[
      			{
      				"min": 1,
      				"max": 5
      			}
      		]
      
    • Add decimal input component
      	"label":"Galon",
      	"dataKey":"galon",
      	"decimalLength":3,
      	"type":38
      
    • Trigger save on change section from sidebar and nested button click

    Changed

    • Set view version attribute only available in CAPI
    • Optimize usability of referenceIndexLookup
    • Remove hardcode in CSV and photo input
    • Prevent non-numerical input on numeric input
    • Set SignatureInput background to white with a rounded border

    Fixed

    • Fix absolute bootstrap css (on Client) overwriting Checkbox and SingleCheck Input
    • Prevent running variable component on the first load
    • Fix on run sourceOption when there is a response file.
    • Fix bug on finding blank answers when revalidating
    • Fix bug overflow hidden on sm and md width
    • Validate Email and URL input on change
    Source code(tar.gz)
    Source code(zip)
  • 1.1.0(Aug 11, 2022)

    FormGear | Ver. 1.1.0

    August 11, 2022

    Optimized Performance

    • Reuse Auxiliary type from ResponseStore in RemarkStore, PrincipalStore, and MediaStore
    • Reduce item in reference.json
    • Change the logic for creating components on nested

    Added

    • Add media to store all media response, eg.: PhotoInput and SignatureInput

    • Add UnitInput with form type = 37

      	"label": "Height :",
      	"dataKey": "height",
      	"type": 37,
      	"typeOption" : 1,
      	"options": [
      	{
      		"label": "centimeter",
      		"value": "cm"
      	},
      	{
      		"label": "meter",
      		"value": "meter"
      	}
      	]
      
    • Handle default json

      reference

      	{
      		"details": [],
      		"sidebar": []
      	}
      

      preset

      	{
      		"description": "",
      		"dataKey": "",
      		"predata": []
      	}
      

      response

      	{
      		"description": "",
      		"dataKey": "",
      		"answers": []
      	}
      

      remark

      	{
      		"dataKey": "",
      		"notes": []
      	}
      

      media

      	{
      		"dataKey": "",
      		"media": []
      	}
      
    • Add name atribut for every dataKey

    • Add console.log FormGear version

    Fixed

    • Fix cannot delete nestedNumber
    • Fix cannot read property of null canvas on SignatureInput

    Changed

    • Change the way to combine validation in nested component
    Source code(tar.gz)
    Source code(zip)
  • 1.0.3(Aug 2, 2022)

    FormGear | Ver. 1.0.3

    August 1, 2022

    Optimized Performance

    • Redeploy set enable from on value change to after saving answer
    • Reengineer code for setSummary
    • Reengineer code to filter components which not run any expression on disabled components

    Added

    • Add signature input
      	"label":"Signature",
      	"dataKey":"signa",
      	"required":true,
      	"type":36
      
    • Add api validation for type string or number input by add urlValidation property to the component
      	"label":"Email",
      	"dataKey":"email",
      	"urlValidation": "http://localhost:8000/validate/email/",
      	"type":31
      
    • Add input range for DateInput and DateTimeLocalInput
      	"rangeInput": 
      		[
      			{
      				"min": "2022-01-25",
      				"max": "today"
      			}
      		]
      
    • Add loader on page change
    • Add cursor pointer on summary, radio, checkbox, and nested button
    • Add email validation
    • Add error message toast on evaluate expression failure

    Changed

    • Update view
    • Update Gps value response
      	[
      		{
      			"value": {
      				"latitude": -6.165237,
      				"longitude": 106.8376027
      			},
      			"label": "https://maps.google.com/maps?q=-6.165237,106.8376027&output=embed"
      		},
      		{
      			"label": "map",
      			"value": "https://maps.google.com/maps?q=-6.165237,106.8376027&output=embed"
      		},
      		{
      			"label": "latitude",
      			"value": -6.165237
      		},
      		{
      			"label": "longitude",
      			"value": 106.8376027
      		}
      	]
      
    • Update URL encode for online lookup

    Fixed

    • Fix enablingSidebar including section and nested
    • Fix duplicate sidebar when creating nested
    • Fix sidebar sorting
    • Handle get the undefined sidebar
    • Fix checkbox options to type string
    Source code(tar.gz)
    Source code(zip)
  • 1.0.2(Jun 27, 2022)

    FormGear | Ver. 1.0.2

    June 24, 2022

    Added

    • Add Timezone and GMT attribute in principal, resonse, and remark output.
    • Filter condition on saveAnswer that will do nothing if no changes. Special thanks to Budi Setiawan Akkas - @cloudwalkerid for the idea on pull request #5.
    • Set clickable error on Summary to open ListError or even validate the whole questionnaire before submission.
    • Add referenceEnableFalse to handle reactive enable conditions for each component on trigger save, submit, or show ListError.
    • Add load spinner while running setReferenceEnableFalse

    Changed

    • Update to lighter colors on the checked options in RadioInput and CheckboxInput on formMode preview and close.
    • Update disable color for SelectInput and MultipleSelectInput as the same as other.
    • Update border color on MaskingInput as the same as other.
    • Update header width divided by 6 parts, only applied on mobile.
    • Update PhotoInput value to base64.
    • Update set response output with deeper filtration on enable condition on the parent of each component.

    Fixed

    • Update ListTextInput and ListSelectInput delete modal position from the bottom to the center of the screen.
    • Update handling nested questions from numeric 0 value input.
    • Update CheckboxInput default options.
    • Fix nested sourceOption on MultipleSelectInput.
    • Fix sorting sidebar on insert nester child.
    Source code(tar.gz)
    Source code(zip)
  • 1.0.1(Jun 8, 2022)

    FormGear | Ver. 1.0.1

    June 8, 2022

    Added

    • Add templateDataKey on response, principal, remark to identify what template is belonging to.
      "templateDataKey": "family-characteristics-2022",
      
    • Add metadata such as gearVersion, templateVersion, validationVersion response, principal, remark to identify what version is used to create these files.
      "gearVersion": "1.0.1",
      	"templateVersion": "1.0.0",
      	"validationVersion": "1.0.0"
      
    • Add metadata such as createdBy, createdAt, updatedBy, updatedAt on response, principal, remark to identify time and user identity that creates these files.
      "createdBy": "adty",
      "updatedBy": "adty",
      "createdAt": "2022-06-08 07:00:19",
      "updatedAt": "2022-06-08 10:07:04",
      
    • Add ListBlank Modal to provide the list of blank component during data collection.
    • Add ListRemark Modal to provide the list of component with remark during data collection.

    Changed

    • Clickable summary to open ListBlank and ListRemark
    • Update nested button label to 'view' on formMode > 1
    Source code(tar.gz)
    Source code(zip)
  • 1.0.0(Jun 6, 2022)

    FormGear | Ver. 1.0.0

    June 6, 2022

    Optimized Performance

    • Optimize on create nested component.

    Added

    • Add summary to response.
      "summary": {
          "answer": 2,
          "blank": 15,
          "error": 0,
          "remark": 1
      },
      
    • Add click on label on SingleCheckInput and ToggleInput.
    • Add list blank.

    Changed

    • Rename lastUpdated to updatedAt on response output.
    • Rename editedBy to updatedBy on response output.
    • Disable ListTextInput and ListSelectInput button on formMode > 1.

    Fixed

    • Fix missed code in if statement on FormGear.tsx and in set answer GlobalFunction.
    • Fix disable remark on formMode == 3 and without any comments in it on each component.
    • Fix bug not load updated remarks when reuse reference.
    • Fix overflow bug on list error when user cannot see the lookinto button.
    • Fix bug createComponent on insertNestedNumber
    Source code(tar.gz)
    Source code(zip)
  • 0.1.3(May 31, 2022)

    FormGear | Ver. 0.1.3

    May 31, 2022

    Changed

    • Update formMode:
      • 1 => OPEN

        This mode is used for data collection activities in general, and it allows users to modify all components of questions and remarks according to the template's constraints.

      • 2 => REVIEW

        This mode is used to review the questionnaire post-data collection, and it only allows users to add remarks on each component based on the examination findings.

      • 3 => CLOSE

        This mode is used just to review the questionnaire upon post-data collection and examination findings.

    • Update label view css on SelectInput inline with required and hint instruction.
    • Set clickable label on nested input button to enter the nested section.
    • Remove reformat answer onValueChange on MaskingInput.
    • Update error list css on MaskingInput as other.
    • Reactive changes in related components when dependent selectInput change.

    Added

    • Trigger save (including response, principal, remark, and reference) on post remark.
    • Add cols and rows property to specify in a grid layout on components.
      	"label":"Address",
      	"dataKey":"address",
      	"type":30,
      	"rows":3
      
      	"label":"Healthy neighborhood rating",
      	"dataKey":"rating",
      	"type":26,
      	"cols":5,
      

    Fixed

    • Fix function eval expression on enableSection
    • Fix copied attribute enableCondition while creating sidebar component
    Source code(tar.gz)
    Source code(zip)
  • 0.1.2(May 24, 2022)

    FormGear | Ver. 0.1.2

    May 24, 2022

    Optimized Performance

    • Multi-thread on initial loop.

      FormGear integrates a collection of JSON templates into a single source of truth called reference. As seen in the picture below:

      Recursive looping is required for the reference construction process to ensure that the looping procedure is completed down to the smallest nested root. This procedure takes a long time, thus we use a multi-thread looping process between sections, which is bridged with numerous process timeouts to prevent each process from executing at the same time.

      Although Javascript is known for running its processes sequentially and in single threads, multi-threaded process tuning can be stated to be successful in practice. As a result, the initial rendering process is reduced by up to 25 % faster.

    • Optimize FormGear with reference utilization.

      The multi-thread tuning process is proven to reduce the looping process in the beginning but is not fast enough for the data collection needs. FormGear, as is well known, exploits reference as the single source of truth, thus all it needs to do in the process is communicate with it to render, enable, validate, or save the answer for each component.

      Previously, reference was considered to be quite large, thus all that was required for the output of data collection results was the principal, response, and remark. However, for optimal process optimization, the initial loop process, which used multi threads at the beginning, can now be avoided by simply reusing the stored reference. This method, however, is confined to the same version of template and response, and if the template version is updated, the reference generation process must be recreated from the beginning.

    • Offline Lookup is used to retrieve data from mobile device.

      The process of rendering options for select inputs can now be optimized with the lookup process for data on CAPI (proven on Android).

      It can be set on client mode config with lookupMode set to 1 for online, or 2 for offline

      	"lookupMode" : 2
      

      Here is the function to fetch Data from local device

      	let offlineSearch = function (id, version, dataJson, setter) 
      
      • id => lookup id to fetch
      • version => lookup data version to fetch, it depends on local endpoint
      • dataJson => params to filter the data
      • setter => params to be used to pass the data retrieved from the local endpoint

    Added

    • FormLoader with spinner and backdrop blur has been added for better experience while waiting for the component to complete the action of render, enable, validate, or save the answer for each component.

    • LookInto on List Error has been added for better experience to jump into component which still has the invalid answer.

    • InitialMode has been added to be used to indicate whether the data collection process is in initial mode (=> 1) or assign mode (=> 2). On CAPI (proven on Android), this mode can be used to trigger initial data collection just simply use neighbor preset to get the initial data required.

      	initialMode : 1
      
    • In conjunction with initialMode, the presetMaster and disableInitial attributes have been added to the type options for templates.

      When initialMode is set to 1, FormGear will search from the given neighbor preset pass from CAPI where the component with presetMaster attribute will show the initial data required for initial data collection.

      	"presetMaster" : true
      

      On the other hand, disableInitial will be used as a disabled input flag when initialMode is set to 1, which actually overrides the disableInput flag if the same component contains these two types of options.

      	"disableInitial" : false
      

    Changed

    • Debounce on CurrencyInput to wait user input finish
    • Clickable label on RadioInput and CheckboxInput
    • Submit principals on mobile
    • When the data on a component changes, the following rangeInput validation and with related components are triggered for checking.
    • On submit, it will be triggered to check the required components before being allowed to continue to submit the data.

    Fixed

    • Fix on enable section bug.
    • When modifying or deleting a nested component, the associated components are also checked including their child components for adjustments as well.
    • Fix bug on the process of rendering options from other component, it is now being set to auto change and re-render the component when the sourceOption component answer are triggered change.
    • In validate or enable, to validate component with the array return type, it is better to check whether it is undefined or not with the following sample code:
      	"test":"let values = getValue('hobbies'); if(values[0] !== undefined) values[0].value == 1",
      
    Source code(tar.gz)
    Source code(zip)
  • 0.1.1(May 10, 2022)

    FormGear | Ver. 0.1.1

    May 10, 2022

    Added

    • Add a condition to check private or public lookup for Select Input.
    • Update MaskingInput placeholder fit to the format in the template.
    • Add HTML input attributes on the JSON template to enrich validation with input component validation, as well as optimize rendering performance.
      	"rangeInput":
      		[
      		     {
      			  "min":0,
      			  "max":100,
      			  "step":5
      		     }
      		]
      
      	"lengthInput":
      		[
      		     {
      			  "minlength":3,
      			  "maxlength":120
      		     }
      		]
      
    • Add PrincipalStore to save notable responses. Principal markers can be added to certain components selected in the JSON template in numeric types, and starting with 1 denotes the most important principal.
      	"principal":1
      
    • Add ListError Modal to provide the list of error component during data collection.
    • Add NowInput to get the current time post trigger button click: Type #35.
    • Add required label on input component to specifies that an input field must be filled out before submit.
      	"required":true
      
    • Add LocaleStore to handle dialog messages. Each message which is by default in English can be adjusted manually one by one with the local language. The language can be added equivalently to the components, i.e. at the first level of the JSON template.
      	"language": 
      		[
      		     {
      		         "componentAdded": "Komponen berhasil ditambahkan",
      		         "componentDeleted": "Komponen berhasil dihapus",
      		         "componentEdited": "Komponen berhasil diubah",
      		         "componentEmpty": "Komponen tidak boleh kosong",
      		         "componentNotAllowed": "Hanya ada 1 komponen yang boleh diubah",
      		         "componentRendered": "Komponen yang berhubungan sedang dibentuk",
      		         "componentSelected": "Komponen ini telah dipilih",
      		         "fetchFailed": "Gagal mengunduh data",
      		         "fileInvalidFormat": "Harap masukkan fail dengan format yang sesuai",
      		         "fileUploaded": "File berhasil diunggah",
      		         "locationAcquired": "Lokasi berhasil didapatkan",
      		         "remarkAdded": "Remark berhasil ditambahkan",
      		         "remarkEmpty": "Remark tidak boleh kosong",
      		         "submitEmpty": "Pastikan isian terisi semua",
      		         "submitInvalid": "Pastikan isian terisi dengan benar",
      		         "submitWarning": "Masih terdapat warning pada isian",
      		         "summaryAnswer": "Terjawab",
      		         "summaryBlank": "Kosong",
      		         "summaryError": "Salah",
      		         "summaryRemark": "Catatan",
      		         "validationMax": "Nilai maksimal adalah",
      		         "validationMaxLength": "Maksimal panjang karakter adalah",
      		         "validationMin": "Nilai minimal adalah",
      		         "validationMinLength": "Minimal panjang karakter adalah",
      		         "validationRequired": "Wajib diisi",
      		         "verificationInvalid": "Masukkan verifikasi dengan benar",
      		         "verificationSubmitted": "Data berhasil dikirimkan"
      		     }
      		]
      

    Changed

    • In JSON validations, it is a must to use getRowIndex() to get the level of the component.
      	{
      	   "test":"let row0 = getRowIndex(0); let row1 = getRowIndex(1); let row2 = getRowIndex(2); let val406 = getValue('l2_r406#'+row2+'#'+row1+'#'+row0); let val407 = getValue('l2_r407#'+row2+'#'+row1+'#'+row0); console.log('406', val406); console.log('407',val407);if(val406 !== undefined && val407 !== undefined && val406 !== '' && val407 !== ''){ (Number(val406[0].value) > 4 && Number(val407[0].value) == 2022)}",
      	   "message":"If R406 > 4, then R407 must in 2022",
      	   "type":2
      	},
      

    Fixed

    • Update modal position from the bottom to the center of the screen.
    • Update version marker display to show the version of the library.
    Source code(tar.gz)
    Source code(zip)
  • 0.1.0(Apr 10, 2022)

    FormGear | Ver. 0.1.0

    April 10, 2022

    Initial minor version release

    Features

    • Render data collection form separated by section.
    • Provide general input fields for data collection.
    • Provide nested form inquiries for recurring fields.
    • Efficiently validate entry on FALSE condition.
    • Enable form control through expression.
    • Provide variable input from expression.
    • Provide remarks to record additional details.
    • Provide preset entry prior to data collection.
    • Provide CSV input then consume it as a JSON value.
    • Able to access image files or utilize native camera function to provide Photo Input.
    • Able to utilize native GPS function to provide Location Input.
    • Work across multiple data collection platforms, including CAPI and CAWI.
    Source code(tar.gz)
    Source code(zip)
Owner
Ignatius Aditya Setyadi
Ignatius Aditya Setyadi
4WEB is a collection & creation of codebase, frameworks, libraries and various resources dedicated to web development 📦🌐

?? Vous pouvez également contribuer à ajouter/créer votre propre collection dans ce référentiel ... Table des matières ?? Codebase ?? NPM packages ??

Raja Rakotonirina 5 Nov 14, 2022
4Web is a collection&creation of codebase, frameworks, libraries dedicated to web development 📦

?? You can also contribute to add / create your own collection in this repository Collection name Description ?? blinke

Raja Rakotonirina 5 Nov 14, 2022
RenderIf is a function that receives a validation as a parameter, and if that validation is true, the content passed as children will be displayed. Try it!

RenderIf RenderIf is a function that receives a validation as a parameter, and if that validation is true, the content passed as children will be disp

Oscar Cornejo Aguila 6 Jul 12, 2022
The jQuery plugin for validation and post form data to server

NiceForm The jQuery plugin for validation and post form data to server (http://ducdhm.github.io/jquery.niceform/) Shortcuts Dependencies Rules Configu

Duc Doan (Bobby) 17 Jul 27, 2022
A robust form library for Lit that enriches input components with easy-to-use data validation features.

EliteForms A robust form library for Lit that enriches input components with easy-to-use data validation features. Installation npm install elite-form

OSLabs Beta 33 Jun 28, 2022
Grupprojekt för kurserna 'Javascript med Ramverk' och 'Agil Utveckling'

JavaScript-med-Ramverk-Laboration-3 Grupprojektet för kurserna Javascript med Ramverk och Agil Utveckling. Utvecklingsguide För information om hur utv

Svante Jonsson IT-Högskolan 3 May 18, 2022
Hemsida för personer i Sverige som kan och vill erbjuda boende till människor på flykt

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

null 4 May 3, 2022
Kurs-repo för kursen Webbserver och Databaser

Webbserver och databaser This repository is meant for CME students to access exercises and codealongs that happen throughout the course. I hope you wi

null 13 Jul 1, 2022
Dynamic-web-development - Dynamic web development used CSS and HTML

Dynamic-web-development ASSISNMENT I just used CSS and HTML to make a mobile int

null 1 Feb 8, 2022
Theme Redone is a custom WordPress theme starter/framework with its own Gutenberg blocks solution and a CLI that speeds up the block creation process.

Theme Redone The Framework for Developing Custom WordPress Themes with its own Gutenberg Blocks creation solution. Theme Redone is a custom WordPress

null 97 Nov 28, 2022
All five assignments and the final group project is done in class CSCI5410 (Serverless Data Processing) Fall 2021 of MACS at Dalhousie University.

Dalhousie University | Fall 2021 | CSCI5410 | SDP (Serverless Data Processing) All five assignments and the final group project is done in class CSCI5

Dhrumil Shah 1 Dec 26, 2021
Typesafe API for processing iterable data in TypeScript and JavaScript.

Stream API Type-safe API for processing iterable data in TypeScript and JavaScript similarly to Java 8 Stream API, LINQ or Kotlin Sequences. Unlike Rx

Norbert Szilagyi 31 Aug 4, 2022
A slick loader to use during your AJAX calls or data processing

Slick Loader A slick loader to use during your AJAX calls or data processing Doc Installation Simply import slick-loader into your HTML. <link rel="st

Zenoo 1 Jan 21, 2022
ndarray/tensor data processing for modern browsers

nadder Easy n-dimensional data manipulation with NumPy syntax. Installation npm i nadder # or yarn add nadder, or pnpm add nadder Usage import { ndarr

null 15 Nov 15, 2022
✏️ A small jQuery extension to turn a static HTML table into an editable one. For quickly populating a small table with JSON data, letting the user modify it with validation, and then getting JSON data back out.

jquery-editable-table A small jQuery extension to turn an HTML table editable for fast data entry and validation Demo ?? https://jsfiddle.net/torrobin

Tor 7 Jul 31, 2022
Simple and lightweight form validation for Svelte with no dependencies.

Svelidate Simple and lightweight form validation for Svelte with no dependencies Installation // npm npm install svelidate // yarn yarn add svelidate

null 26 Nov 15, 2022
A simple Form Validation Utility for Bootstrap 3, Bootstrap 4, and Bootstrap 5 for Humans.

bootstrap-validate A simple Form Validation Utility for Bootstrap 3, Bootstrap 4, and Bootstrap 5 for Humans. ?? Support us with Developer Merchandise

null 137 Oct 28, 2022
Javascript Library providing form validation helpers

Javascript-Form-Validation Javascript Library providing form validation helpers Table of contents Installation Usage Include Library Use components Co

Benoit Gambier 13 Mar 25, 2022
Composition API & Yup Powered Form Validation

vue-yup-form Composition API & Yup Powered Form Validation. This tiny library allows Vue and Yup to be a best friend. Requirements The following versi

Masaki Koyanagi 11 Oct 29, 2022