Sign Up for Free

RunKit +

Try any Node.js package right in your browser

This is a playground to test code. It runs a full Node.js environment and already has all of npm’s 400,000 packages pre-installed, including ngx-dynamic-form-builder with all npm packages installed. Try it out:

require("rxjs/package.json"); // rxjs is a peer dependency. require("@angular/forms/package.json"); // @angular/forms is a peer dependency. require("@angular/common/package.json"); // @angular/common is a peer dependency. require("@angular/compiler/package.json"); // @angular/compiler is a peer dependency. require("@angular/core/package.json"); // @angular/core is a peer dependency. require("class-transformer/package.json"); // class-transformer is a peer dependency. require("class-validator/package.json"); // class-validator is a peer dependency. var ngxDynamicFormBuilder = require("ngx-dynamic-form-builder")

This service is provided by RunKit and is not affiliated with npm, Inc or the package authors.

ngx-dynamic-form-builder v1.5.4

FormBuilder + class-transformer + class-validator = dynamic form group builder for Angular9+

Build Status npm version

FormBuilder + class-transformer + class-validator = dynamic form group builder for Angular9+

Installation

npm i --save class-transformer class-validator ngx-dynamic-form-builder

Links

Demo - Demo application with ngx-dynamic-form-builder.

Stackblitz - Simply sample of usage on https://stackblitz.com

Usage

app.module.ts

import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { CompanyPanelComponent } from './company-panel.component';

@NgModule({
  imports: [
    ...
    FormsModule,
    ReactiveFormsModule,
    ...
  ],
  declarations: [
    ...
    CompanyPanelComponent,
    ...
  ],
  ...
})
export class AppModule {}

company.ts

import { Validate, IsNotEmpty } from 'class-validator';
import { plainToClassFromExist } from 'class-transformer';
import { TextLengthMore15 } from '../utils/custom-validators';

export class Company {
    id: number = undefined;
    @Validate(TextLengthMore15, {
        message: 'The company name must be longer than 15'
    })
    @IsNotEmpty()
    name: string = undefined;

    constructor(data?: any) {
        plainToClassFromExist(this, data);
    }
}

company-panel.component.html

<form [formGroup]="form" *ngIf="form?.formErrors as errors" novalidate>
    <input formControlName="name" placeholder="Name">
    <p *ngIf="errors.name?.length">
      Error: {{errors.name[0]}}
    </p>
    <p>Form status: {{ form.status | json }}</p>
    <p>
      Form class-validator errors: {{errors|json}}
    </p>
    <p>
      Form native errors: {{form?.nativeValidateErrors|async|json}}
    </p>
    <p *ngIf="savedItem">
      Saved item: {{savedItem|json}}
    </p>
    <button (click)="onLoadClick()">Load</button>
    <button (click)="onClearClick()">Clear</button>
    <button (click)="onSaveClick()" [disabled]="!form.valid">Save</button>
</form>

company-panel.component.ts

import { DynamicFormGroup, DynamicFormBuilder } from 'ngx-dynamic-form-builder';
import { Company } from './../../shared/models/company';
import { Input, Component } from '@angular/core';
import { Validators } from '@angular/forms';

@Component({
  selector: 'company-panel',
  templateUrl: './company-panel.component.html'
})
export class CompanyPanelComponent {
  
  form: DynamicFormGroup<Company>;

  @Input()
  item = new Company({
    'id': 11,
    'name': '123456789012345'
  });

  fb = new DynamicFormBuilder();

  savedItem: Company;

  constructor() {
    this.form = this.fb.group(Company, {
      name: ''
    });
  }
  onLoadClick(): void {
    this.savedItem = undefined;
    this.form.object = this.item;
    this.form.validateAllFormFields();
  }
  onClearClick(): void {
    this.savedItem = undefined;
    this.form.object = new Company();
    this.form.validateAllFormFields();
  }
  onSaveClick(): void {
    this.form.validateAllFormFields();
    if (this.form.valid) {
      this.savedItem = this.form.object;
    }
  }
}

custom-validators.ts

import {
    ValidatorConstraintInterface, ValidatorConstraint
} from 'class-validator';

@ValidatorConstraint()
export class TextLengthMore15 implements ValidatorConstraintInterface {
    validate(text: string) {
        return text ? text.length > 15 : false;
    }
}

Observable Errors

the customValidateErrors property can be subscribed for cases in which your code should act on changes in errors

company-panel.component.html

<form [formGroup]="form" *ngIf="form?.customValidateErrors | async as errors" novalidate>
    <input formControlName="name" placeholder="Name">
    <p *ngIf="errors.name?.length">
      Error: {{errors.name[0]}}
    </p>
    <p>Form status: {{ form.status | json }}</p>
    <p>
      Observable validation errors: {{errors|json}}
    </p>
    <p *ngIf="savedItem">
      Saved item: {{savedItem|json}}
    </p>
    <button (click)="onLoadClick()">Load</button>
    <button (click)="onClearClick()">Clear</button>
    <button (click)="onSaveClick()" [disabled]="!form.valid">Save</button>
</form>

company-panel.component.ts

import { DynamicFormGroup, DynamicFormBuilder } from 'ngx-dynamic-form-builder';
import { Company } from './../../shared/models/company';
import { Input, Component } from '@angular/core';
import { Validators } from '@angular/forms';
import { Subscription } from 'rxjs';

@Component({
  selector: 'company-panel',
  templateUrl: './company-panel.component.html'
})
export class CompanyPanelComponent implements onDestroy {

  form: DynamicFormGroup<Company>;

  @Input()
  item = new Company({
    'id': 11,
    'name': '123456789012345'
  });

  @Input()
  strings = Company.strings;

  fb = new DynamicFormBuilder();

  savedItem: Company;

  errorChangeSubscription: Subscription;

  constructor() {
    this.form = this.fb.group(Company, {
      name: ''
    });

    this.errorChangeSubscription = this.form.customValidateErrors.subscribe((allErrors) => {
       console.log(`Errors changed: ${allErrors}`);
    })
  }
  ngOnDestroy() {
    if(this.errorChangeSubscription != null && this.errorChangeSubscription.closed === false) {
      this.errorChangeSubscription.unsubscribe();
    }
  }
  onLoadClick(): void {
    this.savedItem = undefined;
    this.form.object = this.item;
    this.form.validateAllFormFields();
  }
  onClearClick(): void {
    this.savedItem = undefined;
    this.form.object = new Company();
    this.form.validateAllFormFields();
  }
  onSaveClick(): void {
    this.form.validateAllFormFields();
    if (this.form.valid) {
      this.savedItem = this.form.object;
    }
  }
}

License

MIT

RunKit is a free, in-browser JavaScript dev environment for prototyping Node.js code, with every npm package installed. Sign up to share your code.
Sign Up for Free