json-form-generator
v1.0.13
Published
Library for generating html form using json.
Downloads
11
Maintainers
Readme
Description
Angular 7 library for generating forms dynamically using JSON.
See Demo
- Consumer component of `my-form.component.ts` which is called page comoponent. Page component can have multiple forms.
`app.component.ts`
```typescript
import { Component, OnInit } from '@angular/core';
export class AppComponent implements OnInit {
public instance;
public forms = {}; // Always define this property because in this property `simple-form` component instance will be set for each form.
ngOnInit(){
this.instance = this;
}
}
app.component.html
<my-form [pageComponent]="instance"> </my-form>
<!-- ... <another-form [pageComponent]="instance"> </another-form> -->
Without dedicated component for each form.
- Directely use
simple-form
inapp.component.ts
which is called page comoponent. Page component can have multiple forms.
app.component.ts
import { Component, OnInit } from '@angular/core';
export class AppComponent implements OnInit {
public instance;
public schema1: any;
public schema2: any;
public formData1: any; // Data to be populated just after generating form.
public forms = {}; // Always define this property because in this property `simple-form` component instance will be set for each form.
constructor(protected _schemaService: SchemaService) {}
ngOnInit() {
this._init();
}
protected _init() {
try {
this.instance = this;
this.formData1 = {
'my-text-field1': 'Field Value',
'my-number-field2': 123,
// ...
};
this.schema1 = this._schemaService_.getFormSchema('form1-code');
this.schema2 = this._schemaService_.getFormSchema('form2-code');2
} catch (error) {
console.log(error);
}
}
public afterInitForm(simpleFormComponentInstance: any) {}
public onFormGenrated(simpleFormComponentInstance: any) {}
}
app.component.html
<simple-form [schema]="schema1" [pageComponent]="instance" [formData]="formData"
(afterInit)="afterInitForm($event)" (afterGenerateForm)="onFormGenrated($event)"></simple-form> <!-- [formData] and [formComponent] are optional input.-->
<simple-form [schema]="schema2" [pageComponent]="instance"
(afterInit)="afterInitForm($event)" (afterGenerateForm)="onFormGenrated($event)"></simple-form> <!-- [formData] and [formComponent] are optional input.-->
schema
structure.
Form level properties.
{
"code": "my-form-code",
"label": "My Form Label",
"name": "my_form",
"type": "simple", // Not in use now
"hideLabel": false, //Hide form label.
"hidden": false,
"helpText": [ //Instructions for filling the form.
"Help text 1.",
"Help text 2.",
//...
],
"collapse": false, // Whether form is collapsible or not.
"columns": 2, // Form field column supported 1, 2 and 3. Default 2.
"order": 1, // If there are multiple forms with same schema on a single page then give different order value for each form.
"fieldsDefaultProps": { // Common for all fields.
"disabled": false, // If true then all fields will be disabled.
"labelPosition": "left", // Supported left, right, bottom and top. Default: top
"labelAlignment": "right" // Supported right, left and center. Default left.
},
"onParentFieldValueChange": { // Define this property if there is parent child relationship in the fields.
"name": "onParentValueChange", /* any method name defined in "handlerFnOwner".
Arguments: (...your arguments, formCode: string, parentFieldName: string, childFieldsNameArr: string[], changeValue: SimpleChange)
*/
"arguments": ["any", "argument", "..."],
"handlerFnOwner": "'F' | 'P' | object" /*Default: 'P'. There are three possible values:
First-> 'P' - Page Component, It means event handler 'onNameChange' is the method of page component (which is passed as [pageComponent] input in simple-form).
Second-> 'F' - Form Component, It means event handler 'onNameChange' is the method of form component (which is passed as [formComponent] input in simple-form).
Third -> object : It means event handler 'onNameChange' is the method of passed object.*/
},
"fields": [
{
//...field1 or fieldset1 definition. Structure explained below.
},
{
//...field2 or fieldset2 definition. Structure explained below.
},
//....
],
"buttons": [
{
//...button1 definition. Structure explained below.
},
{
//...button2 definition. Structure explained below.
},
//....
]
}
Field schema.fields[i]
structure - Each field structure.
Before understanding JSON structure, understand following points first:
Field type alias.
| Field Type | Type Alias | | ------------------------- | ----------- | | Text | TXT | | Number | NUM | | Password | PWD | | Hidden | HID | | Anchor (Link) | ANC | | Radio Button | RAD | | Checkbox | CHK | | Text Area | TXA | | Dropdown | SEL | | Dropdown (Multiple Select)| MSL | | Autocomplete (Server) | ACS | | Button | BTN | | Rick Text Editor | HTML | | Datepicker | DAT | | Monthpicker | MONTH | | Date Time picker | DATETIME | | Timepicker | TIME | | Fieldset | FST | | Blank | BLK |
External plugins:
- Plugin for
SEL, MSL, ACS
is@ng-select/ng-select
. Sovalidations
andevents
supported by this plugin are supported. - Plugin for
HTML
isngx-quill
.Sovalidations
andevents
supported by this plugin are supported. - Plugin for
DAT, DATETIME
isngx-bootstrap
datepicker. Sovalidations
andevents
supported by this plugin are supported. - Plugin for
TIME
isngx-bootstrap
timepicker. Sovalidations
andevents
supported by this plugin are supported. - Plugin for
validations
for all fields, isngx-custom-validators
. So the validations supported by used external plugin orngx-custom-validators
are supported. - Icon library:
Material Design
.
Field Definition JSON common properties (Not for fieldset (FST));
{
"code": "FIELD1", // Unique for each field
"type": "TXT", // Field type aliase
"label": "First Name",
"name": "first_name", // Unique for each field
"defaultValue": "", // Initiale value.
"placeholder": "",
"helpText": "", // Any help for this field.
"hidden": false,
"disabled": false,
"validations": [ // Validations supported by field plugin or 'ngx-custom-validators'
{
"name": "maxlength",
"value": 50
},
{
"name": "minlength",
"value": 5
},
{
"name": "required",
"value": ""
}
],
"events": [ // Events supported by field plugin or javascript plugin.
{
"name": "change", // Javascript event. Example: for button event will be 'click'. For most of the fields Javacript Events will work, but for some such as Datepicker event will be dependant on plugin..
"callbacks": [{ // array of callbacks
"name": "onNameChange",
"arguments": ["argument1", "argument2", 22, "...argument4"],
"handlerFnOwner": "'F' | 'P' | object" /*There are three possible values:
First-> 'P' - Page Component, It means event handler 'onNameChange' is the method of page component (which is passed as [pageComponent] input in simple-form).
Second-> 'F' - Form Component, It means event handler 'onNameChange' is the method of form component (which is passed as [formComponent] input in simple-form).
Third -> object : It means event handler 'onNameChange' is the method of passed object.*/
}]
}],
"isParent": true, // boolean, if there are some fields whose value/options depend on this field value then this field will be parent field. In this case this property will be true otherwise false.
"children": ['child_field1_name', 'child_field2_name'], // Children fields names.
"order": 1// Recommended incremental number.
}
Specific properties for TXT, NUM
{
//...
prefix: '$', // For example: for currency you may want to show currency sign. This will not affect value.
suffix: '@', // For example: for email type field you may want to show '@'. This will not affect value.
//...
}
Specific Properties for SEL, MSL, RAD, ACS
// Witnout grouping options
{
//...
"options" : [
{
"label": "Option1 Label",
"value": "value1"
},
{
"label": "Option2 Label",
"value": "value2"
},
{
"label": "Option3 Label",
"value": "value2",
"disabled": true // If you want to disable this option.
},
//...
]
//...
}
// With grouped options.
{
//...
"options": [
{
"label": "Group 1",
"options" : [
{
"label": "Option1 Label",
"value": "value1"
},
{
"label": "Option2 Label",
"value": "value2"
},
{
"label": "Option3 Label",
"value": "value2",
"disabled": true // If you want to disable this option.
},
//...
]
},
{
"label": "Group 2",
"options" : [
{
"label": "Option4 Label",
"value": "value4"
},
{
"label": "Option5 Label",
"value": "value5"
},
{
"label": "Option6 Label",
"value": "value6"
},
//...
]
},
// ...
]
//...
}
Note: Do not use group and non-grouped options together.
Specific properties for Autocomplete Server: ACS
{
//...
"searchData": {
"url": "http://yourserver.domain/uri/", /* This url will be hit when user types something in the field.
Request params:
{
searchTerm: string,
fieldCode: string
}
Desired response:
{
options: [
//...array of options (explained in previous point)
]
}
*/
"methodType": "GET | POST", // When server is hit then what method will be user. Default 'GET'
"fetchFn": { /* If this is given then instead of hiting "url" , this method will be called for fetching options.
Arguments: (...your arguments, searchTerm: string, fieldCode: string)
Desired return type:
{
options: [
//...array of options (explained in previous point)
]
}
*/
"name": "fetchACSOptions", // any name defined in "handlerFnOwner"
"arguments": ['from', 'fetch-acs', 'search'], // array of any type of values whill be passed as Arguments in method.
"handlerFnOwner": "'F' | 'P' | object " // Explained above.
},
"beforeFetchFn": { /* callback which will be called before fetching options.
Arguments: (...your arguments, searchTerm: string, fieldCode: string)
Desired Return type: boolean, if false is returned then options will not be fetched.*/
"name": "preFetchACS", // any name defined in "handlerFnOwner"
"arguments": ['any', 'argume', 'here'],
"handlerFnOwner": "'F' | 'P' | object"
},
"afterFetchFn": { /* callback which will be called after fetching options.
Arguments: (...your arguments, {
searchTerm: string,
fieldCode: string,
formCode: string,
response: any (response from server or returned data from 'fetchFn')
})
Desired Return type:
{
options:[...array of options (explained in previous point.)]
}
*/
"name": "postFetchACS", // any name defined in "handlerFnOwner"
"arguments": ['from', 'post-acs', 'search'],
"handlerFnOwner": "'F' | 'P' | object"
}
},
"multiple": true // Whether multiple selection will be allowed or not
}
Specific properties for Anchor Field: ANC
{
//...
defaultValue: "https://your.redirect.link.com/...."
//...
}
Specific properties for Button: BTN
{
//...
theme: "", // Bootstrap theme class. Example1: theme: 'primary' . Example2: theme: 'info
events: [ // always bind click event.
{
"name": "click",
"callbacks": [
{
"name": "onFormSubmit",
"arguments": [],
"handlerFnOwner": "'F' | 'P' | object"
}
]
}
],
icon: "material desgin icon content", // Internally material design icon library is being used. So icon content will be passed here.
//...
}
Specific perperties for Rich Text Editor: 'HTML'
{
//...
quillConfig: null // By default default quill config is applied. But if you want to customize it then define here. Default value is null.
//...
}
Properties for Fieldset (FST
)
This is for grouping fields inside a form. For example address, for address there will be multiple fields, you definitely want to group them for better UI/UX. This will also be in the array of fields.
{
"code": "MYFST1",
"type": "FST", // Always give it 'FST'
"label": "My Fieldset",
"collapse": true, // boolean. Collapsable or not.
"hideLabel": false, // If you want to hide label then pass it true.
"fields": [
//... fields/fieldsets same as in schema.fields[i]
],
"order": 12 // Incremental number
}
Accessibility
You can access simple-form
component instance which gives you control on the form. As emphasized that define forms
property in app.component.ts
and form
property in my-form.component.ts
so that instances can be set in this property.
How to access instance of simple-form
component form.
In AppComponent.forms
, AppComponent.forms['MyFORMCODE']
will be an instance of simple-form
for the form with code 'MyFormCode'
.'
In MyFormComponent.form
will be an instance of simple-form
component.
Important public
properties of SimpleFormComponent
and FieldComponent
class SimpleFormComponent {
public formGoup: FormGroup; // This is the most important property for manipulating fields.
public fieldsComponent: any; /* This contains instances of all fields component.
{
'field-name': FieldComponent
}
*/
public readonly code: string;
public readonly label: string;
public readonly valid: boolean;
public value: any; // Getter and Setter for group value.
public readonly formRef: HTMLElement;
public enable: boolean; //Setter
public disable: boolean; //Setter
public hidden: boolean; // Getter Setter
}
class FieldComponent {
public readonly code: string;
public readonly label: string;
public readonly valid: boolean;
public value: any; // Getter and Setter for group value.
public readonly fieldRef: HTMLElement;
public enable: boolean; //Setter
public disable: boolean; //Setter
public hidden: boolean; // Getter Setter
public readonly control: FormControl;
public readonly inputContainerRef: HTMLElement;
public readonly labelRef: HTMLElement;
public hideLabel: boolean; // Getter Setter
public options: boolean; // Getter Setter for setting options of ACS, SEL and MSL
}