Package Exports
- goteti-forms
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (goteti-forms) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
Goteti Forms
Author: Narasimha Goteti
"GotetiForms" library is for the Angular (2+) project development.
Bootstrap 3 (or later) version is required for this Package for existing styling.
NOTE: Version 3.1.1 is not compatible with previous versions. Version 3 is re-written , has new structures and new configurations.
Caution: Information about version 3.
- type:'template' support removed in configurations.
- type : 'radio' and type: 'checkbox' support are removed in configurations , please implement custom component and use type: 'component' based configuration.
Integration Steps:
Install package in the root folder using the command,
npm i goteti-formsAdd the module to the NgModule of main application.
import { GotetiFormsModule, GotetiFormsService, GotetiCustomRulesService } from 'goteti-forms';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule,
FormsModule,
GotetiFormsModule // <--- Add the Module
],
providers: [GotetiCustomRulesService], // <-- Add the Service
bootstrap: [AppComponent]
})
export class AppModule {
constructor (private GFS: GotetiFormsService, private customrules: GotetiCustomRulesService){
GFS.addComponent(<custom_componet_key>, <Your Custom Input Component>);
customrules.setRules({
<validator_key> : <Your custom validator>
});
// If you donot add the custom rules hear and try to use it , component will not set the validator.
}
}Module contains the following:
import {
AtbrDirective, DebounceInputDirective, FilterPipe, GotetiAutoSelectComponent, GotetiFormsComponent, GotetiFormsModule, GotetiFormsService, GotetiInputFieldComponent, GotetiRecursiveFormControlComponent, GtMapBuilder, HighlightSearch, IpolatePipe, ListenerDirective, PermissionDirective, PermissionDirectiveDisable, SetFocusDirective, gtFormBuilder, gtFormControl, gtFormGroup, gtFormArray, gtAddToFormArray, gtSetValidator, sampleReactiveFormData
} from 'goteti-forms';Details of all the Components / Pipes / Directives / Utils.
1) Component : GotetiInputFieldComponent
Example:
// Supports both Template driven and Reactive forms
//app.component.html
<goteti-input-field
[config]="configuration"
[listen]="{input: onInputValue, change: onChangeValue}"
[args]="'Put the customised arguments here'"
[(ngModel)]="title" required>
</goteti-input-field>
//app.component.ts
ngOnInit(){
this.configuration = {
"label": "Name",
"type": "auto-select",
"template": null,
"class": "form-control",
"multiple": true,
"listValue": "capital",
"disable": false,
"hide": false,
"itpolate": "{name}'s last Name is {lastname} !",
"list":[{"name":"Narasimha","lastname":"Goteti"},
{"name":"Sai","lastname": "Vutukuru"}],
"atbr": {
"placeholder": "It's upto you! "
},
"errors":{
"required":{
"msg": "Name is required",
"class": "text-warning"
}
},
"validations": [{
"key": "minLength",
"value": 5
},{
"key": "required",
"value": 5
}]
};
}
onInputValue(event, args){
console.log(event) // event, 'Put the customised arguments here'
}
onChangeValue(event, args){
console.log(event) //// event, 'Put the customised arguments here'
}Properties of [config]:
| Properties | Description | Values Supported / Example |
|---|---|---|
| label | Label for Input field | String , null |
| class | Class for the Input field | ex: 'form-control classname' |
| disable | If it is 'true', input will be in disable state , Even modifing the attributes from developer tools (inspect elements ) will not work i.e still input field will be disable state | true / false |
| hide | It is NOT CSS based it is *ngIf based. | true / false |
| value | Value of input | |
| type | All basic input types additional to Library input types i.e (auto-select, fnumber), This DO NOT support 'select','radio','checkbox','template' types. | auto-select, template, component, textarea, text, number and (all input types) |
| multiple | 'true' for multi-select , 'false' for single select. multiple true works only for type='auto-select'. | true / false |
| listValue | type="auto-select" selected value should be property or whole selected object of array iteration | Property key or null |
| itpolate | type="auto-select", It is string with {key} ,format of displaying data in dropdown. | 'My name is {name} and last name is {lastname} !' |
| list | type="auto-select", Array of Objects or Array of non-objects for dropdown | Array of objects, Array of non-objects |
| atbr | Attributes for input field | ex: {step: 10} |
| random | Random number has to be updated when ever atbr value is updated inorder to update the Input field's attribute. | Math.random() |
| errors | Error messages which displays in input field | |
| validations | Validation object value for Reactive form | |
Supported 'type' values
HTML types: text , number , range ... etc (radio, checkbox are not supported)
Library supported types : auto-select, component .
Properties of [listen]:
listen attribute accept the object with key and value, where key is valid input events like 'input','change','keydown'... etc , value is the function which needs to handle in '.ts' file.
Properties of [args]:
args=Arguments of listen events, [listen] attribute is mandatory for this , so that arguments will be passed to listen events like 'input, change, keydown,keypress'.
'args' can be String, Array, Object.
type:'component'
If type:"component" follow the below structure and Make sure you add the custome input component to the GotetiFormsService.
// app.module.ts
export class AppModule {
constructor (private GFS: GotetiFormsService, private customrules: GotetiCustomRulesService){
GFS.addComponent('toggle', ToggleInputComponent);
customrules.setRules({
availableCheck: this.availableCheck, /* custom validators */
rangelimit: this.rangelimit /* custom validators*/
});
}
availableCheck(list): ValidatorFn {
return (control: AbstractControl): { [key: string]: boolean } | null => {
if ([null,undefined].includes(control.value)) {
return { 'availableCheck': true };
}
return null;
};
}
rangelimit(range): ValidatorFn {
return (control: AbstractControl): { [key: string]: boolean } | null => {
if (control.value.length < range) {
return { 'rangelimit': true };
}
return null;
};
}
/* ToggleInputComponent is project level custom input component , i.e not the part of GotetiForms. Put your custom input component in place of ToggleInputComponent */
/*
this.rangelimit and this.availableCheck are custom validators in project level.
*/
//app.component.ts
this.configuration = {
"label": "Contact Available?",
"type": "component",
"component": "toggle",
"errors":{
"availableCheck":{ /* availableCheck is custome validator */
"msg": "Contact check is required",
"class": "text-danger"
}
},
"validations":[{
key:'availableCheck',
value: null
}]
}
onChangeValue(ev){
console.log( arguments)
}
// HTML implementation.
<goteti-input-field
[config]="configuration"
[listen]="{change: onChangeValue}"
[(ngModel)]="ratingValue">
</goteti-input-field>Custom Input Component
@Component({
selector: 'toggle',
template: `
<div>
<label>{{config?.label}}</label>
<span [ngClass]="{'btn': true, 'btn-primary': value}" (click)="togglev()"> ON </span>
<span [ngClass]="{'btn': true, 'btn-primary': !value}" (click)="togglev()"> OFF </span>
</div>
`,
})
export class ToggleInputComponent implements OnInit, OnChanges{
value;
@Input() formControl: any; // this is FormControl object with 'config' property added to it.
ngOnInit(){
if (this.formControl && this.formControl.value){
this.value = this.formControl.value;
}
}
get config(){
return this.formControl && this.formControl.config;
}
setvalue(value){
this.value = val;
if (this.formControl && this.formControl.setValue){
this.formControl.setValue(this.value);
}
}
}'GotetiFormsService' methods:
getComponent(key)
getAllComponents()
addComponent(name, component)
removeComponent(key)
setComponents(componentlist)'GotetiCustomRulesService' methods:
getRule(key)
getAllRules(key)
addRule(key, value)
removeRule(key)
setRules(list)2. Pipe: IpolatePipe
Example:
this.value = {
name: 'India'
}
<span> {{ value | itpolate: 'Country name is {name}' }} </span>3. Directive: AtbrDirective , depends on [random]
Example:
this.attributes = {
step: 3,
placeholder: 'This is the place holder'
};
this.random = Math.random();
<input
[atbr]="attributes"
[random]="random"
/>4. Directive: [hide] , [disable]
this.rules = {
hide: true,
disable: true
}
<input
*hide="rules.hide"
[disable]="rules.disable"
/>[disable]="true" , Disables the element even you change the properties in developer tools i.e inspect elements.
5. Directive : [listener] (ListenerDirective)
onInputChange(event){
// some functionality
}
onKeypress(event){
// some functionality
}
<input
[listener]="{input: onInputChange, keypress: onKeypress}"
[args]="['Parameter 1', 'Parameter 2']"
/>6. Recursive Reactive FORM
// .ts implementation
import { gtFormBuilder, GotetiFormsService, gtAddToFormArray, sampleReactiveFormData } from 'goteti-forms';
export class AppComponent implements OnInit{
data = sampleReactiveFormData;
formData;
ngOnInit(){
this.formData = gtFormBuilder(this.data);
/* Now every FormControl , FormArray, FormGroup in this.formData object are added with 'config' property which has the configurtions related to the fields */
}
listenActions(btn, index, itcon, con){
switch(btn.key){
case 'add': {
let label = Math.floor(Math.random()*90000) + 10000;
gtAddToFormArray(con, {label: `PH-${label}`, value: label});
/* gtAddToFormArray : accepts two arguments . 1. Control object , 2. updated config value. */
break;
}
case 'delete':{
con.removeAt(index);
break;
}
}
}
inputListen = {
change : function(ev) {
console.log('inputListen',arguments)
}
}
}
// html implementation
<goteti-recursive-form-control
[control]="formData"
[listenActions]="listenActions.bind(_this)"
[listenInput]="inputListen"
>
</goteti-recursive-form-control> Reactive form configuration object examples:
FormControlDataExample = {
isObject: false,
isArray: false,
id: 'city',
name: 'city',
key: 'city',
label: 'City',
value: 'Hyderabad',
type: 'text',
disable: false,
hide: false,
atbr: {
tabindex: 1
}
order: 3 ,
divclass: 'col-md-3', // wrapper around the field
class:'form-control',
validations: [{
key: 'required'
}, {
key: 'minLength',
value: 10
}],
errors :{
required: {
msg: 'First Name is required'
}
}
}
FormGroupDataExample = {
isObject: true,
isArray: false,
id: 'PermanentAddress',
label: 'Permanent Address',
class: 'col-md-9',
objectClass: '', /* wrapper div class */
order: 4,
disable: false,
hide: false,
fields:[{...FormControlDataExample}], /* FormControlDataExample or FormGroupDataExample*/
validations: [],
errors: {},
actions: [{ /* Action Buttons list for object.*/
key: 'delete',
label: 'Delete',
class: 'btn btn-danger btn-sm'
}]
}
FormArrayDataExample = {
isArray: true
isObject: false,
id: 'Address',
class: 'col-md-9',
objectClass: '', /* wrapper object div class around each iteration.*/
order: 4,
disable: false,
hide: false,
prop: {...FormGroupDataExample }, /* FormGroupDataExample or FormControlDataExample */
validations: [{
key: 'rangelimit', /* custome validator */
value: 3
}],
errors: {
rangelimit: {
msg : 'Minimum 3 items are required',
class: 'text-danger'
}
},
actions: [{ /* Action buttons list for array.*/
key: 'add',
label: 'Add',
class: 'btn btn-primary btn-sm'
}]
}| Properties | Description | Values Supported / Example |
|---|---|---|
| isObject | true / false , Implementation of Formbuilder.Object, If isObject is true , "fields" property is mandatory. | gtFormBuilder(FormGroupDataExample) |
| isArray | true/false , Implementation of Formbuilder.Array. 'prop' is mandatory. | gtFormBuilder(FormArrayDataExample) |
| prop | If isArray = true , then prop is mandatory which can be either 'FormGroupDataExample' or 'FormControlDataExample' | Same like above |
| actions | Array of objects with buttons configurations | [{label:'Button name',key:'unique key of button', class:'classes of button'}] |
| validations | Array of validations objects, if array or object needs validations. 'value' property should not be added for singleton validators like 'required'. | [{"key": "rangelimit","value": 3}] |
| errors | key and value Object for validation messages. | {"errors":{ "rangeCheck":{"msg": "Mininum 2 items are required","class": "text-danger"}}} |
| class, divclass, objectClasss | wrapper div classes | |
[control]: Form builder object.
[listenActions]: Function which handles the actions events.
gtFormBuilder: It is Form builder, parameter is the configuration data object like FormGroupDataExample, FormArrayDataExample , FormControlDataExample.
Note: Every FormControl , FormGroup, FormArray objects built, will be updated with 'config' property on calling (gtFormBuilder, gtFormGroup, gtFormControl, gtFormArray) functions or using component.
Using 'goteti-recursive-form-control' component will render the all the elements dynamically.
For explanation please find the properties of 'sampleReactiveFormData' i.e console.log(sampleReactiveFormData). This document update is still in-progress to list out the all the config properties of 'goteti-recursive-form-control'.
Licence
Open Source - Free to use.