goteti-forms
TypeScript icon, indicating that this package has built-in type declarations

6.0.1 • Public • Published

Goteti Forms

Author: Narasimha Goteti

"GotetiForms" library is for the Angular (2+) project development.

Note: goteti-forms@6.0.0 is re-written and removed the previous versions deprecated functionalities.

Supported Functionalities are

import {
    GotetiFormsModule, GtLoadElementDirectives,
    GtElementRefDirective,GtLoopElementsComponent,
    GtDefaultTemplatesComponent, GtDatalistComponent,
    AtbrDirective, DebounceInputDirective, FilterPipe, ,  HighlightSearch, IpolatePipe, ListenerDirective, PermissionDirective, PermissionDirectiveDisable, SetFocusDirective,  
} from 'goteti-forms';

Dox / Discussions / Issue tracker:

https://github.com/gsnr-narasimha-edu/goteti-forms-discussions/issues

Note: "goteti-forms" is Angular2+ based library , "goteti-js-forms" is vanilla JS based Form Builder based on JSON config.

Sandbox Implementation :

https://stackblitz.com/edit/stackblitz-starters-gotetiforms?file=src%2Fapp%2Fcomponents%2Fhome%2Fhome.component.html

A1) Integration Steps:

Documentation for goteti-js-forms (https://www.npmjs.com/package/goteti-js-forms)

JSON Biulder https://gotetinetwork.github.io/gtwiki

Install package in the root folder using the command,

npm i goteti-forms
npm i goteti-js-forms

Sample Code for Implementation :

app.module.ts

import { GotetiFormsModule, GtElementsService } from 'goteti-forms';
import { RatingComponent } from "./components/RatingComponent";
import { MasterTemplatesComponent } from ".components/MasterTemplatesComponent";


@NgModule({
declarations: [
    AppComponent
],
imports: [
    BrowserModule,
    AppRoutingModule,
    FormsModule,
    GotetiFormsModule  // <--- Add the Module ,
    RatingComponent // <-- Custom Input Component
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {
    constructor (private GES: GtElementsService){
        GES.addComponent('rating', RatingComponent);
    }
}

app.component.ts

import { Component } from '@angular/core';

@Component({
    selector: 'app-root',
    template: `
        <master-templates></master-templates>
        <app-register-form></app-register-form>
    `,
    style: ``,
    })
export class AppComponent {}

./components/register-form/register.blueprint.ts

import { GtsInputBP, GtsListBP, GtsObjectBP } from 'goteti-js-forms';

    export const getRegisterBluePrint = ():
    | GtsInputBP
    | GtsObjectBP
    | GtsListBP => {
    return {
        name: 'register',
        isObject: true,
        type: 'template',
        template: 'Group',  // gtEref="Group" from master-templates
        fields: [
        {
            name: 'firstname',
            label: 'First Name',
            type: 'template',
            template: 'Input', // gtEref="Input" from master-templates
            skip: false, // Skips the rendering on page.
            hide: false // disables and hides the element on page
            disable: false // disables the element 
            validations: [
            {
                key: 'required',
            },
            ],
        },
        {
            name: 'username',
            label: 'User Name',
            type: 'template',
            template: 'Input',
            validations: [
            {
                key: 'required',
            },
            {
                key: 'nospace',
            },
            ],
        },
        {
            name: 'contacts',
            lable: 'Contacts',
            isArray: true,
            type: 'template',
            template: 'List', // gtEref="List" from master-templates
            init: 1,
            fieldinfo: {
            name: 'primary',
            label: 'Primary Contact',
            type: 'template',
            template: 'Input',
            },
        },
        {
            name: 'rating',
            type: 'component',
            component: 'rating', 
            /* GES.addComponent('rating', RatingComponent); from AppModule.ts */
            validations: [
            {
                key: 'minrating',
                minvalue: 4,
            },
            ],
        },
        {
            name: 'yesno',
            label: 'Do you accept it ?',
            type: 'template',
            template: 'yesnoRef',
            list: ['YES', 'NO'],
            validations: [],
        },
        {
            name: 'actions',
            type: 'template',
            template: 'Actions',
            list: [
            {
                key: 'submit',
                label: 'Submit',
            },
            {
                key: 'cancel',
                label: 'Cancel',
            },
            ],
        },
        ],
    };
};

./components/register-form/register.component.ts

import { Component } from '@angular/core';
    import { GtsFormHub, GtsFormInput, GtsFormList, GtsFormObject, GtsFormStatusInf, } from 'goteti-js-forms';
    import { getRegisterBluePrint } from './register.blueprint';
    import { GotetiFormsModule } from 'goteti-forms';
    import { MasterTemplatesComponent } from '../master-templates/master-templates.component';
    import { CommonModule, JsonPipe, KeyValuePipe, NgFor } from '@angular/common';

    @Component({
        selector: 'app-register-form',
        templateUrl: './register.component.html',
        styleUrl: './register.component.css',
    })
    export class RegisterComponent {
    customValidator = {
        minrating: (validation: any, control: any) => {
            if (validation.minvalue > control.value) {
                return {
                minrating: 'Minimum rating required',
                };
            }
            return null;
        },
    };
    formStatus: GtsFormStatusInf = {
        submitted: false,
        checkOnSubmit: true,
        checkOnDirty: false,
        checkOnTouch: false,
        checkOnLoad: false,
    };
    formhub: GtsFormHub = new GtsFormHub(
        this.customValidator,
        (control: any, type: any) => {
        // Callback that Detect form input changes
        console.log(control?.config?.name, type, control?.value, control);
         switch (type) {
                    case 'submit': {
                    this.formStatus.submitted = true;
                    if (this.formdata.isValid) {
                    }
                    }
                }
        },
        this.formStatus
    );
    initialData: any = {
        firstname: 'John',
    };
    otherData: any = {};
    formdata: GtsFormObject | GtsFormList | GtsFormInput = this.formhub.update(
        this.initialData,
        getRegisterBluePrint()
    );
    }

./components/register-form/register.component.html

<p>Register !</p>
    <gt-loop-elements
        [control]="formdata"
        [otherData]="otherData"
    ></gt-loop-elements>

    <ng-template
        gtEref="yesnoRef"
        let-control="control"
        let-config="config"
        let-otherData="otherData"
    >
    {{ config?.label }} (Custom Template)
    <div>
        <button
            type="button"
            *ngFor="let item of config.list"
            (click)="control.value = item"
            [ngClass]="{ active: control.value == item }"
        >
        {{ item }}
        </button>
        <div *ngIf="control?.showErrors" style="color:red">
            <small *ngFor="let err of control?.errors | keyvalue" class="gt-block">
                {{ err.value }}
            </small>
        </div>
    </div>
    </ng-template>

    <pre>
    {{ formdata?.value | json }}
    </pre>

./components/master-templates.component

You can find it at (https://stackblitz.com/edit/stackblitz-starters-gotetiforms?file=src%2Fapp%2Fcomponents%2Fmaster-templates%2Fmaster-templates.component.html)

./components/RatingComponent.ts

You can find it at (https://stackblitz.com/edit/stackblitz-starters-gotetiforms?file=src%2Fapp%2Fcomponents%2Frating%2Frating.component.ts)

Major updates information

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

3. Directive [gtLoadElement] , loads the template / component that stored in GtElementsService, GtBoxElementsService using the config in Control.

4. 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.

5. 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>

6. 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>

8. If config has skip, hide, disable booleans configured with boolean   values  then  control.skipped , control.hidden, control.disabled will be updated accordingly.

    8.1. If control.skipped is true, form element rendering will be skipped but its 'hidden' and 'disabled' functionality will not be effected i.e no change in hidden and disabled behaviour.

    8.2. If control.hidden is true, form element will be hidden and disabled is set to true so that validation checks will not be triggered.

    8.3. If control.disabled is true, then validation checks will be skipped 

gtLoadElement : To load the templateRef / component.

    /* 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"
            [open]="false" // true to show options always 
            [search]="search"   // search text to filter list (donot use [inputref])
            [(value)]="test" // ngModel value
            [rerun]="''" // manual check for list filteration and on selection
            [rerunOnSelect]="false" // rerun check after selecting option
            [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>

Obsolete Notice:
    1. Removed [inputref]="sampleinput" support for gt-datalist component. 
    2. Removed [freetext]="true" support for gt-datalist component.

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.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)
}

Licence

Open Source.

The author is NOT liable for any liabilities.

/goteti-forms/

    Package Sidebar

    Install

    npm i goteti-forms

    Weekly Downloads

    9

    Version

    6.0.1

    License

    none

    Unpacked Size

    641 kB

    Total Files

    62

    Last publish

    Collaborators

    • gsnr-narasimha-edu