goteti-forms
v5.2.13
Published
Author: Narasimha Goteti
Downloads
356
Maintainers
Readme
Goteti Forms
Author: Narasimha Goteti
"GotetiForms" library is for the Angular (2+) project development.
Dox / Discussions / Issue tracker:
https://github.com/gsnr-narasimha-edu/goteti-forms-discussions/issues
JSON builder for blueprints
https://gotetinetwork.github.io/gtwiki
Updates:
GtFormStatus directive, GtFormStatusService, GtLoadComponent directive, GtLoadTemplate directive, GtRef, Gtfref directive added
"errorsText" property available for GtControl, [ OtherData ] attribute available for GtFormStatusDirective. [ formStatus ] attribute available for gt-error-msg component, GtFun pipe that accepts function as angular template pipe.
Removed templates Input binding for gt-reactive-form and gt-input-field, instead use GtFormStatus directive (Refer )
index property added for the template , component and gt-reactive-form .
Removed support for auto-select
'skip' control in gt-reactive-form functionality supported.
"GtFormHub" class added, Support added for Async Validators. (Refer: B1.1 Implementation)
'commonInputTemplate' support added for the gt-reactive-form (Refer B1.2.1 Implementation)
control attribute added to 'gt-error-msg' component for rendering the AbstractControl errors (Refer: B1.2.3).
Added {type: 'template', template: 'customtemplate' } support for the GtGroupBP & GtArrayBP, so that custom templates used for GtGroup, GtArray while rendering in gt-reactive-form .
Added additional properties to GtControl, GtGroup, GtArray (Refer: B1.2.4).
"GtCustomRulesService" support removed.
GtFormHub, gtFormBuilder, gtUpdateControl supports 'AbstractControlOptions' i.e {updateOn: 'blur'}.
In upcoming versions: gtFormBuilder, gtUpdateControl will be removed instead use 'GtFormHub' (build, update methods in GtFormHub) ;
NOTE: Versions 5+ are re-written which have new structures and new configurations so not compatible with previous versions.
Caution: Information about version 4.
- type : 'radio' needs 'list' property as array of objects with (label, value) properties ex: list: [{ label: 'Yes', value: true}, {label:'No',value: false}]
- All services , components selectors and names are changed.
- if type:'auto-select' then list: [{id:1,...otherProperties}] . 'id' property is mandatory and unique value.
A1) Integration Steps:
Install package in the root folder using the command,
npm i goteti-forms
Add the module to the NgModule of main application.
import { GotetiFormsModule, GtFormsService, GtFormHub} from 'goteti-forms';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule,
FormsModule,
GotetiFormsModule // <--- Add the Module
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {
constructor (private GFS: GtFormsService){
GFS.addComponent(<custom_componet_key>, <Your Custom Input Component>);
}
}
Module contains the following:
import {
AtbrDirective, DebounceInputDirective, FilterPipe, GtAutoSelectComponent, GotetiFormsModule, GtFormsService, GtFormHub, GtInputFieldComponent, GtRecursiveFormControlComponent, GtErrorMsgComponent, GtMapBuilder, HighlightSearch, IpolatePipe, ListenerDirective, PermissionDirective, PermissionDirectiveDisable, SetFocusDirective, gTrefDirective, gtLoadTemplate, GtLoadComponentDirectives, gtFormBuilder, gtFormControl, gtFormGroup, gtFormArray, gtAddToFormArray, gtSetValidator, sampleReactiveFormData
} from 'goteti-forms';
A2) Details of all the Components / Pipes / Directives / Utils.
A2.1) Component : GotetiInputFieldComponent
Example:
// Supports both Template driven and Reactive forms
//app.component.html
<gt-ifield
[runAction]="runAction"
[config]="configuration"
[listen]="{input: onInputValue, change: onChangeValue}"
[args]="'Put the customised arguments here'"
[(ngModel)]="title" required>
</gt-ifield>
/* runAction variable is trigger the updated validations it as to be toggled as '' then wait for 500ms then 'VALIDATIONS' on upting the validations in config object. */
//app.component.ts
ngOnInit(){
this.configuration = {
"label": "Name",
"type": "text",
"template": null,
"class": "form-control",
"multiple": true,
"listValue": "capital",
"disable": false,
"hide": false,
"itpolate": "{name}'s last Name is {lastname} !",
"list":[{id:1, "name":"Narasimha","lastname":"Goteti"},
{id:2,"name":"Sai","lastname": "Vutukuru"}],
"atbr": {
"placeholder": "It's upto you! "
},
"errors":{
"required":{
"msg": "Name is required",
"class": "text-warning"
}
},
"validations": [{
"key": "minLength",
"asyncfn" : false, /* <== This value should be true for custom Async validators else false */
"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 | | heading| It is for gt-reactive-form heading with index value| heading: "{index} I am Header for a form group"| | 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','template' types). For type:'radio', list:[{label:'Yes', value: true},{label:'No',value:false}] format is required. | 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 (example: {type:'auto-select', listValue:'value',list:[{id:1, label:'India',value:'IND'}]) or Array of non-objects for dropdown | Array of objects('id' property is mandatory which is unique.), 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() | | controlOptions | {updateOn:'submit'} (change/blur/submit)| | | errors| Error messages which displays in input field | | | validations | Validation object value for Reactive form which supports both sync & async validators| [{ key: 'customValidator', asyncfn: false, value: 'test'},{key:'customAsyncValidator', asyncfn: true, value: 'test'}]| | inputs | For type component, inputs is the keyValue pairs that acts like Input bindings to component| ex: {type: 'component', component:'< component that added to GtFormService >', inputs:{title: '@input binding title of the component'}}|| ||||
A2.2) Supported 'type' values
HTML types: text , number , range ... etc
| type | Description | example | |-|-|-| | < any html input type> | like type is 'text' or 'number' or 'checkbox' ..etc ... | {type:'text', label:'Firsta Name', name:'firstname',class:'form-control',divclass:'col-md-3',disable:false, hide: false,atbr:{placeholder:'Name'}, validations:[{key:'required'}], errors: {required:{msg:'First Name is required'}}}| |radio|config should contain 'list' property with array of objects (label and value ) format .|list: [{label:'yes',value: true},{label:'no',value: false}]| |select| NOT-SUPPORTED| NOT-SUPPORTED|
Library supported types :
|type| Description| example | |-|-|-| |auto-select (removed)| 1. If list is array of objects ('id' property with unique values are mandatory), If 'listValue' property is present result value will be 'listValue' mentioned value else result will be whole selected object. 2. If list is array of values , then no need of 'listValue' property. |Array of objects {type:'auto-select',multiple: false,list:[{id:1,label:'India', value:'IND'},{id:1,label:'USA', value:'US'}], listValue:'value', itpolate:'{label} shortcode is {value}'} Array of values {type:'auto-select',multiple: true,list:['India', 'USA'], listValue:'value'}| |component| If type is component , then component property with custome component name is mandatory. You can add your additional properties required for the custom component. Custom component should be added to the 'GotetiFormsService' service. For reference please follow the below 'component' example.| {type:'component', component:'toggle', customeproperty:'customepropertyvalue'}| |template|For reference please follow the below 'template' example.||
auto-select (ex:{type:'auto-select',list:[{id:1, label:'India',value:'IND'}]), component, template .
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.
A2.3) type:'component' Implementation
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: GtFormsService){
GFS.addComponent('toggle', ToggleInputComponent);
GFS.formbuilder = new GtFormHub({
availableCheck: this.availableCheck.bind(this),
rangelimit: this.rangelimit.bind(this)
});
}
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.
<gt-ifield
[config]="configuration"
[listen]="{change: onChangeValue}"
[(ngModel)]="ratingValue">
</gt-ifield>
Creating 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);
}
}
}
A2.4) type:'template' Implementation
//app.component.ts
this.configuration = {
"label": "Contact Available?",
"type": "template",
"template": "testtemplate",
"divclass":"col-md-5",
"errors":{
},
"validations":[]
}
onChangeValue(ev){
console.log( arguments)
}
gtFormHub = new GtFormHub({customeValidator: Function})
this.gtFormStatus = {
submitted: false,
checkOnSubmit: true,
checkOnDirty: false,
checkOnTouch: false,
gtErrorsView: true, /* this will show default message view if you want to customize the errors views make this false and create your own view */
showAllErrors: false, /* Default its true, when it is true, all error messages will shown ingoring checkOnSubmit,checkOnDirty,checkOnTouch booleans*/
formName: 'MyForm'
onControlLoad: function(this: any, control: any, args: any){}.bind(this),
onControlUpdate:function(this: any, control: any, args: any){ // This function fires on every control value updates when [(ngModel)] attribute is used.
// console.log(control, this)
console.log(this.gtFormStatus.isNgFormValid('valid')) // valid | touched | dirty
/* isNgFormValid only works for [(ngModel)] based elements, for [formControl] use this.formGroup.valid based validations */
}.bind(this),
onControlDestroy:function(this: any, control: any, args: any){}.bind(this)
}
//onSubmit make gtFormStatus.submitted = true
<div [GtFormStatus]= "gtFormStatus" [templates]="{testtemplate: templatename}" [GtFormHub]="gtFormHub" [OtherData]="OtherData">
// HTML implementation.
<gt-ifield
[config]="configuration"
[listen]="{change: onChangeValue}"
[args]="'customeargs'"
[(ngModel)]="ratingValue">
</gt-ifield>
</div>
<ng-template #templatename let-control="control" let-config="config" let-formStatus="formStatus" let-con="control" let-listen="listen" let-args="args" let-all>
/* control is the formControl or NgModel object with config property.*/
<button *ngFor="let l of control?.config?.list" (click)="control.setValue(l.value)">{{l.label}} </button>
{{con?.errorsText}}
</ng-template>
(OR)
<ng-template gtref="templatename" let-control="control" let-config="config" let-formStatus="formStatus" let-con="control" let-listen="listen" let-args="args" let-all>
/* control is the formControl or NgModel object with config property.*/
<input [formControl]="control"/>
{{con?.errorsText}}
</ng-template>
(OR)
<ng-template #templatename let-listen="listen" let-config="config" let-formStatus="formStatus" let-con="control" let-args="args" let-valueModel="valueModel" let-disabled="disabled" let-all>
/* valueModel.update is the function which updates the value of NgModel.*/
<button *ngFor="let l of control?.config?.list" (click)="valueModel.update(l.value)">{{l.label}} </button>
{{con?.errorsText}}
</ng-template>
(OR)
<ng-template gtref="templatename" let-config="config" let-formStatus="formStatus" let-con="control" let-listen="listen" let-args="args" let-valueModel="valueModel" let-disabled="disabled" let-all>
<input [(ngModel)]="valueModel.value" />
{{con?.errorsText}}
</ng-template>
'GtFormsService' methods:
getComponent(key)
getAllComponents()
addComponent(name, component)
removeComponent(key)
setComponents(componentlist)
getTemplate(key)
getAllTemplates()
addTemplate(name, Template)
removeTemplate(key)
setTemplates(Templatelist)
'GtFormStatusService':
FormStatus:GtFormStatusInterface = {};
FormHub?: GtFormHub = undefined;
getComponent(key)
getAllComponents()
addComponent(name, component)
removeComponent(key)
setComponents(componentlist)
getTemplate(key)
getAllTemplates()
addTemplate(name, Template)
removeTemplate(key)
setTemplates(Templatelist)
Note1: GtFormStatusService scope is inside GtFormStatus directive.
Note2: Template/component search order is GtFormStatusService if not found then searches in GtFormService
Note3: If you use <ng-template [gtref]="<customTemplate>">...</ng-template> , then this customTemplate Ref will be added to GtFormService.
B1) GtFormHub
class methods: (alternative to GtFormBuilder & gtUpdateControl)
1. constructor(<custom Validators as object of functions>)
2. build(blueprint) /* alternative to GtFormBuilder, blueprint is configuration as shown in above examples */
3. update(updatedObject, blueprint) /* alternative to gtUpdateControl */
B1.1) 'GtFormHub' Implementation:
|class, divclass, objectClasss| wrapper div classes| | |inputs|acts like @Inputs for component if type:"component" and component:"< componentToLoad >"| {< key >: < value >}| ||||
[control]: Form builder object.
GtFormHub: It is Form builder generator, constructor accepts object with list of Validators and Async Validators as parameter.
Using 'gt-reactive-form' 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'.
B1.2.2 Alternative to actions in 'gt-reactive-form'
< div [GtFormStatus]= "gtFormStatus" [templates]="{
commonInputTemplate: ownGenericInput,
arrayIterateTemplate: arrayIterateTemplate,
postArrayTemplate: postArrayTemplate,
groupIterateTemplate: groupIterateTemplate,
postGroupTemplate: postGroupTemplate,
postInputTemplate: postInputTemplate
}" [GtFormHub]="gtformhub">
<gt-reactive-form
[control]="formData"
[listenInput]="inputListen"
></gt-reactive-form>
</ div>
<ng-template gtref="ownGenericInput" let-con="control" let-all>
<customisedCommonInputField [control]="con"></customisedCommonInputField>
/* console.log(all) to view all properties available*/
</ng-template>
<ng-template #arrayIterateTemplate let-con="control" let-all>
/* Place your actions here */
/* console.log(all) to view all properties available*/
</ng-template>
<ng-template #groupIterateTemplate let-con="control" let-all>
/* Place your actions here */
/* console.log(all) to view all properties available*/
</ng-template>
<ng-template #postGroupTemplate let-con="control" let-all>
/* Place your actions here */
/* console.log(all) to view all properties available*/
</ng-template>
<ng-template #postInputTemplate let-con="control" let-all>
/* Place your actions here */
/* console.log(all) to view all properties available*/
</ng-template>
B1.2.3 'gt-error-msg' component : GtErrorMsgComponent
<gt-error-msg [errors]="control?.errors" [errormessages]="control?.config?.errors" [control]="control"></gt-error-msg>
(OR)
{{control?.errorsText}} shows the errors message text when <gt-reactive-form> or <gt-ifield> is used.
B1.2.4 Added new properties to GtControl , GtGroup, GtArray (instances)
1. random - String - Generates random String value when fireRandom or updateAtbr functions are triggered, which can be used as setter inbounds to the component.
ex: <custom-element [random]="control.random"><custom-element >
@Input()
set random(){
this.callTheRefreshFunctionalityOrUpdateFunctionality()
}
2. fireRandom() - Function - Generates the random string value and assigns to random property of object.
3. updateAtbr(atbr: GtAttributeBP) - Function - Updates the attribute property in 'control.config.atbr' object and fires the fireRandom()
4. updateValidatorsList(validations: Array<GtValidationBP>, gtFormhubInstance: GtFormHub, checkValidation ?: boolean) - Function - Sets the new sync and async validators to the existing GtFormControl, GtFormGroup, GtFormArray instance objects using GtFormHub instance.
ex: (this.firstname as GtControl).updateValidatorsList([{key: 'required'}, {key:'customasyncvalidator': asyncfn: true}], this.formhub)
5. insertToArray(index:Number,GtFormHub_Instance?: any, prop?: GtControlBP | GtGroupBP ) - Function - Inserts the new GtControl / GtGroup to the GtArray at the specific index using GtFormHub instance.
6. pushToArray(GtFormHub_Instance?: any, prop?: GtControlBP | GtGroupBP) - Function - Pushes the new GtControl / GtGroup to the GtArray at the end using GtFormHub instance.
7. control.toggleView('hide', true/false) => this will hide/show the control and disable/enable it.
control.toggleView('skip', true/false, true/false) => this will skip/unskip the control from gt-reactive-form rendering, third argument decides to handle the disable state when skipped/unskipped.
8. control.errorsText : this is all errors message text for the control.
NOTE:
GtControl : random, fireRandom() , updateAtbr(), updateValidatorsList(), toggleView()
GtGroup : random, fireRandom() , updateValidatorsList(), toggleView()
GtArray : random, fireRandom() , updateValidatorsList(), insertToArray(), pushToArray(), toggleView()
B1.3) Pipe: ItpolatePipe
Example:
this.value = {
name: 'India'
}
<span> {{ value | itpolate: 'Country name is {name}' }} </span>
B1.4) 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"
/>
B1.5) 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.
B1.6) Directive : [listener] (ListenerDirective)
onInputChange(event){
// some functionality
}
onKeypress(event){
// some functionality
}
<input
[listener]="{input: onInputChange, keypress: onKeypress}"
[args]="['Parameter 1', 'Parameter 2']"
/>
B1.7 Directive: [gtLoadTemplate] :
< ng-template [gtLoadTemplate]="< 'templateNameString' >"></ ng-template > Inputs: config, listen, args, control, valueModel, templates, random, templateData, gtLoadTemplate(v: string); Note: Always use the gtLoadTemplate attribute at last if multiple attributes are given to the ng-template. Note: This directive loads the template from GtFormStatusService or else GtFormService by searching the template string gtLoadTemplate property
B1.8 Directive [gtLoadComponent] :
< ng-template [gtLoadComponent]="< 'componentNameString' >" >< /ng-template >
Inputs: config, listen, args, control, valueModel,templateData, random(r: string, gtLoadComponent(v: string)
Note: Always use the gtLoadTemplate attribute at last if multiple attributes are given to the ng-template.
Note: This directive loads the component from GtFormStatusService or else GtFormService by searching the component string gtLoadComponent property
B1.9 Directive [gtref]
<ng-template gtref="CustomeTemplateName" let-valueModel="valueModel" let-control="control" let-config="config" let-formStatus="formStatus" let-listen="listen" let-args="args">
<input [formControl]="control" [atbr]="config?.atbr" [random]="control?.random"/>
(OR)
<input [(ngModel)]="valueModel.value" [atbr]="config?.atbr" [random]="control?.random"/>
</ng-template>
Note: This directive will add this template to the current scope of GtFormService
B1.10 Directive [gtfref]
This gtfref should be used inside [GtFormStatus] block as this gtfref will be added to GtFormStatusService scope.
<ng-template gtfref="CustomeTemplateName" let-valueModel="valueModel" let-control="control" let-config="config" let-formStatus="formStatus" let-listen="listen" let-args="args">
<input [formControl]="control" [atbr]="config?.atbr" [random]="control?.random"/>
{{control?.errorsText}}
(OR)
<input [(ngModel)]="valueModel.value" [atbr]="config?.atbr" [random]="control?.random"/>
</ng-template>
B1.11 Directive (oninit) :
Event emits when element is initialized / destroyed
<gt-ifield
(oninit)="onElementinit()"
(ondestroy)="onElementdestroy()"
></gt-ifield>
C1. InputDebounce Decorator.
<input type="text" (input)="onInput($event)"/>
onInput(e){
this.onInputDebounce(e.target.value)
}
@InputDebounce(1500) // 1500 is the delay
onInputDebounce(...args){
console.log(args)
}
Experimental Features
Alternatively you can use the following components for form elements rendering and [goteti-js-forms](https://www.npmjs.com/package/goteti-js-forms) library for Form builders.
Form Elements rendering directives / components :
1. Directive [gtEref] for storing the Template ref to the GtElementsService globally for rendering it any where in app using [gtLoadElement] attribute
2. Directive [gtBref] for storing the Template ref to the GtBoxElementsService Box/Block level for rendering it with in [GtFormBox] div block using attribute [GtLoadElement] attribute
3. Directive [GtFormBox] for creating the Block/Box level form that uses the GtBoxElementsService for storing the block level templates
4. Directive [gtLoadElement] , loads the template / component that stored in GtElementsService, GtBoxElementsService using the config in Control.
5. Component <gt-loop-elements [control]="formData"></gt-loop-elements>
for rendering all the form elements from the form control using blueprint that built by goteti-js-form builder.
6. Directive [GtFocusBlur] (onIn) (onOut) , directive that detects the focus within the element or not.
CSS class 'gtfocused' is added if focused else not.
example :
<div GtFocusBlur
[disabled]="disabled"
(onIn)="onFocusIn($event)"
(onOut)="onFocusOut($event)">
<input class="focusit" [disabled]="disabled" />
</div>
8. Use <gt-default-templates></gt-default-templates> for the library based default template refs in Root component, but be sure to use the template: 'Group' | 'List' | 'Input' in blueprints.
7. Material based input wrapper Component
<gt-mat-wrap
[floatLabel]="false"
[wrapClass]="'class'"
[appearance]="'outline'" // "standard" | "fill" | "outline"
[hasError]="false"
[hasWarning]="false"
(focusIn)="$event" // focusin, click
(focusOut)="$event" // focusout, click
>
<div class="header">
<span>{{config?.label || config?.name}}</span>
</div>
<div class="data">
<input class="focusit" [(ngModel)]="control.value" [placeholder]="config.placeholder || ''">
/*use "focusit" for auto focus on click of div */
</div>
<div class="footer">
<small> {{control.hint}}</small>
<small *ngFor="let err of control.errors | keyvalue">
{{err.value}}
</small>
</div>
</gt-mat-wrap>
Example:
const RegisterBluePrint:GtsObjectBP = {
name: 'testings',
isObject: true,
type:'template',
template: 'group', // or 'Group'
label: 'Testing Group',
fields: [{
name: 'firstname',
label: 'First Name',
type: 'template',
template: 'input', // or 'Input'
validations: [
{
key: 'limit',
value: 6,
message: 'Limit exceeded'
}
]
},{
name: 'username',
label: 'user name',
type: 'component',
component: 'customcomponent',
validations: [
{
key: 'limit',
value: 6,
message: 'Limit exceeded'
}
]
},{
name:'contacts',
isArray: true,
type:'template',
template: 'List',
fieldinfo: {
name: 'primary',
type: 'template',
template: 'Input',
label: 'Contact no',
placeholder: 'contact',
}
}]
}
// app.module.ts export class AppModule {
constructor(private gtElementService: GtElementsService){ this.gtElementService.addComponent('customcomponent', CustomComponent); }
}
// CustomComponent.ts
export class CustomComponent{
@Input() control: any;
@Input() config: any;
@Input() set hashid(){
} _hashid = ''; }
// CustomComponent.html < label> {{config?.label}} </ label> <input [(ngModel)]="control.value" />
// Register.component.ts
import {GtsFormHub, GtsList, GtsGroup, GtsControl} from 'goteti-js-forms';
formStatus = {
checkOnSubmit: true,
submitted: false
}
formHub = new GtsFormHub({
limit: (validation: any, con: GtsList | GtsGroup | GtsControl)=>{
if(${con.value}
.length > validation.value){
return {
limit: con.message
}
}
return null;
}
},(...args)=>{
// form changes
}, this.formStatus);
formData = this.formHub.update({firstName: 'Narasimha'}, RegisterBluePrint);
// Register.component.html Method 1:
<gt-loop-elements [control]="formdata"></gt-loop-elements>
/* You can place these gtEref templates ref any where in root components that loads prior to Register.component*/
<ng-template gtEref="group" let-control="control" let-config="config">
<ng-container *ngFor="let item of control.Fields">
<gt-loop-elements [control]="item"></gt-loop-elements>
</ng-container>
</ng-template>
<ng-template gtEref="input" let-control="control" let-config="config">
<label>{{config?.label}}</label>
<input [(ngModel)]="control.value" [placeholder]="config.placeholder || ''"/>
</ng-template>
(OR)
Method 2:
<ng-template
gtEref="group"
let-control="control"
let-config="config">
<ng-container *ngFor="let item of control.Fields">
<ng-template
style="display: inline-block;"
[control]="item"
[type]="item?.config?.type"
[template]="item?.config?.template"
[component]="item?.config?.component"
gtLoadElement></ng-template>
</ng-container>
</ng-template>
<ng-template gtEref="input" let-control="control" let-config="config">
<label>{{config?.label}}</label>
<input [(ngModel)]="control.value" [placeholder]="config.placeholder || ''"/>
</ng-template>
<ng-template
[control]="formdata"
[type]="formdata?.config?.type"
[template]="formdata?.config?.template"
[component]="formdata?.config?.component"
gtLoadElement></ng-template>
(OR)
Method 3:
<div GtFormBox>
/* You should place these gtBref templates ref within this GtFormBox */
<ng-template gtBref="group" let-control="control" let-config="config">
<ng-container *ngFor="let item of control.Fields">
<gt-loop-elements [control]="item"></gt-loop-elements>
</ng-container>
</ng-template>
<ng-template gtEref="input" let-control="control" let-config="config">
<div style="display: inline-block;vertical-align: top;padding:3px;">
<gt-mat-wrap
#element
[disabled]="control.disabled"
[hasError]="control.errors"
[hasWarning]="control.warnings"
[floatLabel]="control.value"
[stopDefaultFocus]="false" // true will ignores the focus onclick of element.
[bypassFocused]="false" // true will ignores setting focused flag.
[focused]="<variable>" // or use element.setFocused(boolean) , use only if bypassFocused is true.
[appearance]="'outline'"
(focusIn)="$event"
(focusOut)="$event"
[wrapClass]="'wrapClass'">
<div class="header">
<span>{{config?.label || config?.name}}</span>
</div>
<div class="data">
<input [(ngModel)]="control.value" [placeholder]="config.placeholder || ''">
</div>
<div class="footer">
<small> {{control.hint}}</small>
<small *ngFor="let err of control.errors | keyvalue">
{{err.value}}
</small>
</div>
</gt-mat-wrap>
</div>
</ng-template>
<gt-loop-elements [control]="formdata"></gt-loop-elements>
</div>
</div>
(OR)
Method 4:
<gt-default-templates></gt-default-templates>
<gt-loop-elements [control]="formdata"></gt-loop-elements>
(OR)
Method 5:
/* This method is dependent on 'goteti-js-forms' npm library */
<ng-template
gtLoadElement
[config]="{name: 'firstname',label: 'First Name', validations: [{key: 'required'}]}"
type="template"
template="defaultInputRef"
[required]="true"
[validators]="validators"
[(gtModel)]="firstName"
[hubClass]="GtsFormHub"></ng-template>
Typeahed Component :
<div class="datalist-wrap">
<input #sampleinput/>
(OR)
<input [(ngModel)]="search">
<span (click)="datalist.tall();" >
<span class="caret-down"></span>
</span>
<span (click)="test = null; sampleinput.value = '';" >
X
</span>
<gt-datalist
#datalist // datalist.tall() = toggle() + showAll()
class="dropdown"
[inputref]="sampleinput" // input template ref (donot use [search])
[search]="search" // search text to filter list (donot use [inputref])
[(value)]="test" // ngModel value
[freetext]="true" // true will update ngModel on input change after delay of 1000 milliseconds.
[rerun]="''" // manual check for list filteration and on selection
[rerunOnSelect]="false" // rerun check after selecting option
[open]="false" // true to show options always
[disabled]="false"
multiple="true" // multiple or single value
uidprop="key" // unique key property for list of objects enabling selection.
retext="{ftext} - {key}" // default interpolation text for list of objects when value is not in list.
(viewChange)="title = $event; Console.log($event)" // selected option label
(onChange)="''" // catches event on option selection.
>
<gtoption
*ngFor="let item of list"
[uid]="item.key" // unique id used for selection option
[ftext]="item.ftext + ' ' + item.key" // Filters the list based on ftext value
[value]="item" // actual value that updates the ngModel
[valueview]="item.label" #gto> // label that shows on input selection
<div>
{{item.label}}
</div>
</gtoption>
<div class="norecords" *ngIf="datalist.empty">
No Records
</div>
</gt-datalist>
</div>
Other Usages:
<div (gtoptionUpdate)="Console.log($any($event).detail);">
<gtoption *ngFor="let item of list"
[uid]="item.id"
[ftext]="item.searchText"
[value]="item"
[valueview]="item.label" #gto
[hidden]="false"
[disabled]="false"
(gtoptionUpdate)="$any($event).detail.gtoption.selected = $any($event).detail.selected;" #gto>
{{gto.selected}}
{{ item.label }}
</gtoption>
</div>
Licence
Open Source.
The author is NOT liable for any liabilities.