All Projects → ESSS → ng-xform

ESSS / ng-xform

Licence: MIT license
esss.github.io/ng-xform/home

Programming Languages

typescript
32286 projects
javascript
184084 projects - #8 most used programming language
HTML
75241 projects

Projects that are alternatives of or similar to ng-xform

boardgame.io-angular
Angular client for boardgame.io
Stars: ✭ 52 (+188.89%)
Mutual labels:  angular6
claim-reporter-pwa-poc
Example PWA application with Angular 6 and backend with Node
Stars: ✭ 39 (+116.67%)
Mutual labels:  angular6
file-input-accessor
Angular directive that provides file input functionality in Angular forms.
Stars: ✭ 32 (+77.78%)
Mutual labels:  angular6
react-apollo-form
Build React forms based on GraphQL APIs.
Stars: ✭ 195 (+983.33%)
Mutual labels:  forms
laminas-form
Validate and display simple and complex forms, casting forms to business objects and vice versa
Stars: ✭ 65 (+261.11%)
Mutual labels:  forms
flask-wtf
Simple integration of Flask and WTForms, including CSRF, file upload and Recaptcha integration.
Stars: ✭ 1,357 (+7438.89%)
Mutual labels:  forms
spring-boot-angular-maven-starter
An example of Spring Boot and Angular 6 integration with the help of Maven and Kotlin.
Stars: ✭ 13 (-27.78%)
Mutual labels:  angular6
angular-seat-charts
Angular Seat Charts Generator
Stars: ✭ 33 (+83.33%)
Mutual labels:  angular6
ng-sunPawd
基于ng-zorro实现的Angular后台基础框架
Stars: ✭ 43 (+138.89%)
Mutual labels:  angular6
FrontendForms
A module for ProcessWire CMS to create and validate forms on the frontend easily using the Valitron library.
Stars: ✭ 0 (-100%)
Mutual labels:  forms
enform
Handle React forms with joy 🍿
Stars: ✭ 38 (+111.11%)
Mutual labels:  forms
blogging-app-with-Angular-CloudFirestore
A blogging application created with the help of Angular on front-end and Google Cloud Firestore on backend.
Stars: ✭ 45 (+150%)
Mutual labels:  forms
AuthGuard
Example repo for guarding routes post
Stars: ✭ 42 (+133.33%)
Mutual labels:  angular6
forms-bootstrap
👾 Bootstrap 4 forms for Nette framework
Stars: ✭ 17 (-5.56%)
Mutual labels:  forms
dynamic-app
Dynamic Forms Builder are reusable and make building large-scale applications easier (Easy Peasy)
Stars: ✭ 15 (-16.67%)
Mutual labels:  angular6
altinn-studio
Next generation open source Altinn platform and applications.
Stars: ✭ 91 (+405.56%)
Mutual labels:  forms
activiti-examples
Alfresco Process Services powered by Activiti Examples.
Stars: ✭ 58 (+222.22%)
Mutual labels:  forms
LC-switch
Superlight vanilla javascript plugin improving forms look and functionality
Stars: ✭ 31 (+72.22%)
Mutual labels:  forms
ng-walkthrough
A walkthrough for Angular
Stars: ✭ 21 (+16.67%)
Mutual labels:  angular6
Build-Former
This is a library for building forms dynamically in Android.
Stars: ✭ 20 (+11.11%)
Mutual labels:  forms

ng-xform - Angular library built using ngx-library yeoman generator.

npm version Build Status Coverage Status dependencies Status devDependencies Status

Demo

View all the directives in action at Demo and Demo source code

Dependencies

  • Angular (requires Angular 6, tested with 6.1.0)

Installation

Install above dependencies via npm.

Now install @esss/ng-xform via:

npm i --save @esss/ng-xform

You will need to import styles. Example: 'src/styles.scss'

@import 'bootstrap/dist/css/bootstrap.min.css';
@import 'ngx-bootstrap/datepicker/bs-datepicker.css';
@import "@ng-select/ng-select/themes/default.theme.css";

Setup the MeasureComponent adding the js file on .angular-cli.json

"scripts": [
  "../node_modules/mathjs/dist/math.js"
]

SystemJS

Note:If you are using SystemJS, you should adjust your configuration to point to the UMD bundle. In your systemjs config file, map needs to tell the System loader where to look for @esss/ng-xform:

map: {
  '@esss/ng-xform': 'node_modules/@esss/ng-xform/bundles/ng-xform.umd.js',
}

Once installed you need to import the main module:

import { NgXformModule } from '@esss/ng-xform';

The only remaining part is to list the imported module in your application module. The exact method will be slightly different for the root (top-level) module for which you should end up with the code similar to (notice NgXformModule):

import { NgXformModule } from '@esss/ng-xform';

@NgModule({
  declarations: [AppComponent, ...],
  imports: [NgXformModule, ...],  
  bootstrap: [AppComponent]
})
export class AppModule {
}

Other modules in your application can simply import NgXformModule:

import { NgXformModule } from '@esss/ng-xform';

@NgModule({
  declarations: [OtherComponent, ...],
  imports: [NgXformModule, ...], 
})
export class OtherModule {
}

Usage

Template:

 <ng-xform [horizontalForm]="horizontal" [labelWidth]="labelWidth" [fields]="fields" ></ng-xform>

Component:

export class HomeComponent implements OnInit, OnDestroy {

  @ViewChild(NgXformEditSaveComponent) xformComponent: NgXformEditSaveComponent;
  @ViewChild('customField') customFieldTmpl: TemplateRef<any>;

  private colors: any[] = [
    { id: 0, name: 'other' },
    { id: 1, name: 'blue' },
    { id: 2, name: 'yellow' },
    { id: 3, name: 'white' },
    { id: 4, name: 'black' },
    { id: 5, name: 'orange' },
    { id: 6, name: 'purple' }
  ];

  public onchangefn = new Subject<string>();

  public fields: DynamicField[];
  public horizontal = false;
  public labelWidth = 2;
  public model: any;
  public outputhelper = {'A': 1, 'B': 2, 'C': 3};
  public subscriptions: Subscription[] = [];

  constructor(private titleService: Title, private http: HttpClient) { }

  ngOnInit() {
    const minDate = new Date();
    const maxDate = new Date();

    this.subscriptions.push(this.onchangefn.asObservable().subscribe(
      (value: any) =>  this.xformComponent.setValue({'outputopt': this.outputhelper[value]})
    ));

    minDate.setDate(minDate.getDate() - 3);
    maxDate.setDate(maxDate.getDate() + 3);
    this.titleService.setTitle('Home | @esss/ng-xform');
    this.fields = [
      new TextField({
        key: 'name',
        label: 'Name',
        validators: [
          Validators.minLength(3)
        ]
      }),
      new TextField({
        key: 'email',
        label: 'E-mail',
        validators: [
          Validators.required,
          Validators.email
        ]
      }),
      new SelectField({
        key: 'color_ro',
        label: 'Color read-only',
        readOnly: true,
        searchable: true,
        options: this.colors,
        optionLabelKey: 'name',
      }),
      new SelectField({
        key: 'color',
        label: 'Color',
        searchable: true,
        options: this.colors,
        addNewOption: true,
        addNewOptionText: 'Add Color',
        optionLabelKey: 'name',
      }),
      new TextField({
        key: 'other',
        label: 'Other color',
        visibilityFn: (value: any) => value.color && value.color.id === 0
      }),
      new NestedFormGroup({
        key: 'address',
        fields: [
          new SelectField({
            key: 'country',
            label: 'Country',
            searchHandler: this.observableSource.bind(this),
            searchByValueKeyHandler: this.observableSourceByPlaceId.bind(this),
            searchOnFocus: true,
            searchable: true,
            optionLabelKey: 'name',
            optionValueKey: 'alpha3Code',
            validators: [
              Validators.required
            ]
          })
        ]
      }),
      new SelectField({
        key: 'type',
        label: 'Type',
        options: ['a', 'b'],
        validators: [
          Validators.required
        ]
      }),
      new SelectField({
        key: 'type_tags',
        label: 'Type tags',
        options: [{id: 1, description: 'A'}, {id: 2, description: 'B'}, {id: 3, description: 'C'}],
        optionLabelKey: 'description',
        optionValueKey: 'id',
        multiple: true
      }),
      new MeasureField({
        key: 'length',
        label: 'Length',
        modelUnit: 'mm',
        viewUnit: of('m').pipe(delay(200)),
        availableUnits: of(['m', 'cm', 'mm']).pipe(delay(200))
      }),
      new MeasureField({
        key: 'width',
        label: 'Width',
        modelUnit: 'inch',
        viewUnit: of('inch').pipe(delay(200)),
        availableUnits: of(['inch', 'ft']).pipe(delay(200))
      }),
      new SelectField({
        key: 'opt',
        label: 'Select an option',
        options: [{id: 'A', description: 'Option A'}, {id: 'B', description: 'Option B'}, {id: 'C', description: 'Option C'}],
        optionLabelKey: 'description',
        optionValueKey: 'id',
        onChangeFn: (value: string) => {
          this.onchangefn.next(value);
        }
      }),
      new TextField({
        key: 'outputopt',
        label: 'Output of option',
        readOnly: true,
      }),
      new CheckboxField({
        key: 'news',
        label: 'News'
      }),
      new RadioGroupField({
        key: 'gender',
        label: 'Gender',
        options: of([{id: 1, label: 'male'}, {id: 2, label: 'female'}]).pipe(delay(2000)),
        optionValueKey: 'id',
        optionLabelKey: 'label'
      }),
      new MultilineField({
        key: 'comment',
        label: 'Comment',
        rows: 4
      }),
      new DateField({
        key: 'birth',
        label: 'Date of birth',
        theme: 'blue',
        minDate: minDate,
        maxDate: maxDate,
        showWeekNumbers: true
      }),
      new DateRangeField({
        key: 'range',
        label: 'Date range',
        theme: 'blue'
      }),
      new CustomField({
        key: 'custom_amount',
        label: 'Custom Field Amount',
        tmpl: this.customFieldTmpl
      }),
    ];
  }

  ngOnDestroy() {
    this.subscriptions.forEach(sub => sub.unsubscribe());
  }

  public onSubmit(values: object) {
    this.model = values;
  }

  populate() {
    this.xformComponent.setValue({
      name: 'Customer',
      email: '[email protected]',
      type_tags: [2],
      type: 'b',
      color: { id: 3, name: 'white' },
      color_ro: { id: 3, name: 'white' },
      address: {
        street: 'ChIJn7h-4b9JJ5URGCq6n0zj1tM'
      },
      gender: 1,
      length: { value: 2, unit: 'm'},
      width: { value: 3, unit: 'ft'},
      opt: 'A',
      news: true,
      comment: 'Mussum Ipsum, cacilds vidis litro abertis. Mauris nec dolor in eros commodo tempor. Aenean aliquam molestie leo, vitae ' +
      'iaculis nisl. Quem num gosta di mé, boa gentis num é. Tá deprimidis, eu conheço uma cachacis que pode alegrar sua vidis. Em pé ' +
      'sem cair, deitado sem dormir, sentado sem cochilar e fazendo pose. Leite de capivaris, leite de mula manquis sem cabeça. Praesent ' +
      'vel viverra nisi. Mauris aliquet nunc non turpis scelerisque, eget. Casamentiss faiz malandris se pirulitá. Sapien in monti ' +
      'palavris qui num significa nadis i pareci latim.',
      birth: new Date(),
      range: [
        '2018-09-06T03:00:00.000Z',
        '2018-10-08T03:00:00.000Z'
      ],
      custom_amount: 456
    });
  }

  public observableSource(keyword: any): Observable<any[]> {
    const url = `https://restcountries.eu/rest/v2/name/${keyword}`;
    if (keyword) {
      return this.http.get(url)
        .pipe(
          map((res) => res as any[])
        );
    } else {
      return of([]);
    }
  }

  public observableSourceByPlaceId(keyword: any): Observable<any> {
    return of({
      'alpha3Code': 'BRA',
      'name': 'Brazil'
    }).pipe(delay(300));
  }
}

Custom Field

It's possible to create your own field template and set it on dynamic field list through CustomField

Example: my-component.html

<ng-template #customField let-customControl="control" let-isEditing="isEditing">
  <div class="input-group">
    <div class="input-group-addon">$</div>
    <input type="number"
      [formControl]="customControl"
      [attr.disabled]="!isEditing || null" 
      class="form-control"
      style="text-align:right" 
      id="exampleInputAmount" 
      placeholder="Amount" />
    <div class="input-group-addon">.00</div>
  </div>
</ng-template>

my-component.ts

  @ViewChild('customField') customFieldTmpl: TemplateRef<any>;
  public fields: DynamicField[];
  ...
  ngOnInit() {
    this.fields = [
      new CustomField({
        key: 'custom_amount',
        label: 'Custom Field Amount',
        tmpl: this.customFieldTmpl
      }),
    ];
  }

Typed key validation

Now it is possible to define a type that will be used to validate the key field values

Example:

class Address {
  street: string;
  city: string;
}

class User {
  name: string;
  email: string;
  address: Address;
}

export class UserComponent {

  public fields: DynamicField[];

  constructor() {

    this.fields = [
      new TextField<User>({
        key: 'name',
        label: 'Name',
        validators: [
          Validators.minLength(3)
        ]
      }),
      new TextField<User>({
        key: 'email',
        label: 'E-mail',
        validators: [
          Validators.required,
          Validators.email
        ]
      }),
      new NestedFormGroup<User>({
        key: 'address',
        fields: [
          new TextField<Address>({
            key: 'street',
            label: 'Street',
          }),
          new TextField<Address>({
            key: 'city',
            label: 'City',
          }),
        ]
      })
    ];
  }
}

In the example, the TextField is created specialized whit the User class

new TextField<User>({

the TextField key attribute will accept only keys of the class User (i.e. 'name', 'email', 'address'), and show and error if any other value is provided.

On change function

You can add a parameter onChangeFn on your DynamicField fields. This parameter receives a anonymous function, just like in the following example:

new TextField({
  key: 'phrase',
  label: 'Write a phrase',
  onChangeFn: (value: string) => {
    // push new typed value to a subject
    this.onchangefnSubject.next(value);
  }
}),

This parameter can be used to execute async functions that depends on user input or push values of a field to a Subject() just like is shown above.

Locales

DatepickerField can use different locales.

It's possible to change a locale by calling use method of BsLocaleService, list of available locales is in dropdown below.

To use a different locale, you have to import it from ngx-bootstrap/chronos first, then define it in your @NgModule using function defineLocale

Example:

import { defineLocale, LocaleData } from 'ngx-bootstrap/chronos';
import { ptBrLocale } from 'ngx-bootstrap/locale';
defineLocale(ptBrLocale.abbr, ptBrLocale);

...

export class AppModule {

  constructor(bsLocaleService: BsLocaleService) {
    // aplly locale
    bsLocaleService.use(ptBrLocale.abbr);
  }
}

Demo source code load locales.

Development

After cloning of this repository will be necessary run once npm run setup, so will be able to run npm run demo to start the demo locally

For more information view common development activities on https://github.com/tinesoft/generator-ngx-library#development

License

Copyright (c) 2018 ESSS. Licensed under the MIT License (MIT)

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].