Skip to main content

Examples

This page shows an end-to-end example:

  1. Create two field model classes: TextboxField, TextareaField
  2. Create two field components: TextboxComponent, TextareaComponent
  3. Register them in NvsDynamicFormModule.forRoot(...)
  4. Render a form in a page and handle submit

The exact HTML/CSS is up to you — the important part is the contract: each field component should be able to render based on its field model, and connect to the underlying form control.

1) Create field model classes

Create a shared base if you want, but the simplest approach is to extend whatever base types your project uses.

In this example, field model classes extend FieldBase<T> from the library.

textbox.type.ts
import { TemplateRef } from '@angular/core';
import { FieldBase } from '@nvs-dynamic-form/ng-core';

export class TextboxField extends FieldBase<string> {
override readonly fieldType? = 'textbox';

icon?: TemplateRef<any>;
onIconClick?: (value?: string) => void;
type?: 'email' | 'number' | 'password' | 'tel' | 'text' | 'url';
placeholder?: string;

constructor(options: TextboxField) {
super(options, '');
this.type = options.type ?? 'text';
this.icon = options.icon;
this.placeholder = options.placeholder ?? '';
this.onIconClick = options.onIconClick;
}
}
textarea.type.ts
import { FieldBase } from '@nvs-dynamic-form/ng-core';

export class TextareaField extends FieldBase<string> {
override readonly fieldType? = 'textarea';

minRowSize?: number;
placeholder?: string;
maxRowSize?: number;

constructor(options: TextareaField) {
super(options, '');
this.minRowSize = options.minRowSize ?? 3;
this.maxRowSize = options.maxRowSize ?? 10;
this.placeholder = options.placeholder ?? '';
}
}

2) Create field components

These are standard Angular components that should:

  • receive the field instance (your TextboxField / TextareaField)
  • bind to the correct FormControl in the form

Your project may use a shared base component for field rendering. If so, adapt the inputs accordingly.

Textbox component

textbox.component.ts
import { Component, Input } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormControl, ReactiveFormsModule } from '@angular/forms';

import { TextboxField } from './textbox.type';

@Component({
selector: 'app-textbox',
standalone: true,
imports: [CommonModule, ReactiveFormsModule],
template: `
<label class="field">
<span class="label">{{ field.label }}</span>
<input
class="input"
[type]="field.type ?? 'text'"
[placeholder]="field.placeholder ?? ''"
[formControl]="control"
/>
</label>
`,
})
export class TextboxComponent {
@Input({ required: true }) field!: TextboxField;
@Input({ required: true }) control!: FormControl;
}

Textarea component

textarea.component.ts
import { Component, Input } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormControl, ReactiveFormsModule } from '@angular/forms';

import { TextareaField } from './textarea.type';

@Component({
selector: 'app-textarea',
standalone: true,
imports: [CommonModule, ReactiveFormsModule],
template: `
<label class="field">
<span class="label">{{ field.label }}</span>
<textarea
class="textarea"
[rows]="field.minRowSize ?? 3"
[placeholder]="field.placeholder ?? ''"
[formControl]="control"
></textarea>
</label>
`,
})
export class TextareaComponent {
@Input({ required: true }) field!: TextareaField;
@Input({ required: true }) control!: FormControl;
}

3) Register fields in NvsDynamicFormModule

Register your field names and connect each name to its component + field model class.

app.config.ts
import { ApplicationConfig, importProvidersFrom } from '@angular/core';

import { NvsDynamicFormModule } from '@nvs-dynamic-form/ng-core';

import { TextboxComponent } from './components/fields/textbox/textbox.component';
import { TextboxField } from './components/fields/textbox/textbox.type';

import { TextareaComponent } from './components/fields/textarea/textarea.component';
import { TextareaField } from './components/fields/textarea/textarea.type';

import { ButtonComponent } from './components/button/button.component';

export const appConfig: ApplicationConfig = {
providers: [
importProvidersFrom(
NvsDynamicFormModule.forRoot({
formFields: {
textbox: {
component: TextboxComponent,
class: TextboxField,
},
textarea: {
component: TextareaComponent,
class: TextareaField,
},
},
submitButton: {
component: ButtonComponent,
defaultOptions: {
label: 'Save',
isFullWidth: true,
position: 'center',
visible: true,
},
},
}),
),
],
};

4) Build a page that renders the dynamic form

Create a page (or component) that constructs the fields array and renders nvs-dynamic-form.

profile-form.page.ts
import { Component } from '@angular/core';
import { Validators } from '@angular/forms';

import { NvsDynamicFormModule } from '@nvs-dynamic-form/ng-core';

import { TextboxField } from '../components/fields/textbox/textbox.type';
import { TextareaField } from '../components/fields/textarea/textarea.type';

@Component({
standalone: true,
selector: 'app-profile-form-page',
imports: [NvsDynamicFormModule],
template: `
<h1>Profile</h1>

<nvs-dynamic-form
[fields]="fields"
submitButtonLabel="Save"
(onSubmit)="onSubmit($event)"
></nvs-dynamic-form>
`,
})
export class ProfileFormPage {
fields = [
new TextboxField({
label: 'First name',
key: 'firstName',
placeholder: 'Jane',
validators: [Validators.required],
screenSize: { desktop: 6, mobile: 12 },
}),
new TextboxField({
label: 'Last name',
key: 'lastName',
placeholder: 'Doe',
screenSize: { desktop: 6, mobile: 12 },
}),
new TextareaField({
label: 'About',
key: 'about',
placeholder: 'Tell us about yourself…',
minRowSize: 6,
screenSize: 12,
}),
];

onSubmit({ values, valid }: { values: any; valid: boolean }) {
if (!valid) return;
console.log(values);
}
}