angular-formsbuilder-gen – Angular Reactive Forms Generator from OpenAPI
Generate strongly-typed Angular Reactive Forms (and optional Signals-based forms) directly from your OpenAPI / Swagger schema. This package works together with ng-openapi-gen to turn backend API contracts into ergonomic form builder services with rich validation and UI helpers.
- Build reactive forms for every model in your API in seconds.
- Keep forms in sync with your OpenAPI schema as it evolves.
- Standardize validation messages and Bootstrap 5–ready error UI across your app.
Features
- Angular reactive forms generator from OpenAPI – create
FormGroup-based builders for each schema model. - Optional Angular Signals templates – generate form builders that expose Signals-based state for Angular 17+.
- Typed field access with IntelliSense – lambda-based selectors (
a => a.email) forgetControl,setFieldValue,watchField. - Submit / loading state – built-in
submit(saveFn)with automaticisSubmittingflag management. - Form persistence –
persistTo/restoreFromfor saving drafts to localStorage/sessionStorage. - Bulk operations –
markAllTouched(),disableAll(),enableAll(),clone()out of the box. - Unsaved changes guard – auto-generated
CanDeactivateguard prompting users before leaving dirty forms. - Auto-provide – generated
provideAllFormBuilders()/provideFormBuilders(...)functions eliminate manual provider lists. - Multi-step wizard – generic
FormWizard<T>with fluent.setStep()API, IntelliSense field selection, step validation, andonStepChangeobservable. - Advanced validation ecosystem – centralized
ValidationManager, typed error keys, placeholders, and i18n-ready messages. - UI helpers for errors – pipes, reusable
<afb-validation-errors>component, andafbAutoErrorsdirective withform.showValidationErrors(). - Bootstrap 5 default styling – uses
is-invalidandinvalid-feedbackby default, fully customizable via config APIs. - Template customization – plug in your own form templates or copy the built-ins with
--customize. - Configurable generation – include/exclude models, clean up unused generated files, and emit validation messages JSON for translation tools.
- Works with ng-openapi-gen – reuse the same
swagger.jsonconfiguration to generate both API clients and form builders.
Table of Contents
- Installation
- Quick Start
- Configuration
- Configuration Options
- Generating Angular API Services and Models
- Generating Reactive FormsBuilder Classes
- Example of Generated FormBuilder Class
- Validation Ecosystem (Error Handling & Messages)
- AutoFormsBuilderModule (Angular module & config)
- FormValidator (Typed Validation Utilities)
- Conditional Validators
- Validation Summary & Focus
- Typed Field Access (IntelliSense)
- Submit / Loading State
- Bulk Operations
- Form Persistence (Drafts)
- Clone Form
- Unsaved Changes Guard
- Auto-Provide Form Builders
- Multi-Step Wizard
- Date Helper
- What Is New?
- Features (Detailed)
- LLM Guidance
Installation
Installing the Module
To install "angular-formsbuilder-gen" globally or within your project, run the following commands:
npm install -g ng-openapi-gen
npm install -g angular-formsbuilder-genQuick Start
Initialize a configuration file (optional but recommended):
ng-frmGenerator initThis creates a
swagger.jsonin the current folder with sensible defaults. You can also use a custom name:ng-frmGenerator init my-swagger.jsonGenerate Angular API services and models using
ng-openapi-gen:ng-openapi-gen -c swagger.jsonGenerate reactive form builder classes from the same config:
ng-frmGenerator swagger.jsonIf your config file is named
swagger.jsonin the current folder, you can also just run:ng-frmGeneratorUse the generated form builder in your Angular component:
@Component({ selector: 'app-user-form', templateUrl: './user-form.component.html', providers: [CustomerDtoFormBuilder.provider()] }) export class UserFormComponent { form = this.customerFormBuilder.buildForm(); constructor(private customerFormBuilder: CustomerDtoFormBuilder) {} submit() { this.form.showValidationErrors(); if (this.form.invalid) { return; } const model = this.form.value; // send model to API } }<form [formGroup]="form" afbAutoErrors (ngSubmit)="submit()"> <!-- your controls here --> <button type="submit" class="btn btn-primary">Save</button> </form>Optionally enable Signals-based templates by setting
"useSignalFormTemplates": trueinswagger.json.
Configuration
You can manually create a configuration file named swagger.json in the root of your Angular app with the following content, or let the CLI scaffold it for you (see below):
{
"$schema": "node_modules/ng-openapi-gen/ng-openapi-gen-schema.json",
"input": "https://localhost:44325/swagger/v1/swagger.json",
"output": "./src/app/api",
"ignoreUnusedModels": false,
"modelsPath": "./../api/models",
"formsOutput": "/src/app/forms",
"schemeFile": "E://swagger.json",
"useEnumValuesAsString": false,
"useSignalFormTemplates": false,
"generateFormsHelpers": true,
"generateCustomValidators": true,
"generateValidationManager": true,
"generateShowForErrorDirective": true,
"generateIFormBuilder": true,
"generateDateHelper": true,
"generateEnumHelper": true,
"customFormTemplatePath": "",
"customSignalFormTemplatePath": "",
"generateValidationUiHelpers": true,
"cleanupUnusedFiles": true,
"includeModels": [],
"excludeModels": [],
"generateValidationMessagesJson": true,
"disableTlsVerification": false,
"generateFormWizard": false
}Note: This file is also used by the ng-openapi-gen tool.
Quick start: scaffold swagger.json via CLI
Instead of creating swagger.json by hand, you can ask the generator to create an initial file for you:
ng-frmGenerator initThis will create swagger.json in the current folder using the same defaults shown above.
You can also specify a custom file name:
ng-frmGenerator init my-config.jsonIf the target file already exists, the command will print a message and exit without overwriting it.
Configuration Options
Our tool specifically uses the properties below:
- input: URL for the OpenAPI schema JSON file.
- schemeFile: Local path for the schema JSON file, which takes precedence if it exists.
- modelsPath: Path for generated models from ng-openapi-gen.
- formsOutput: Path for generated FormBuilder classes.
- useEnumValuesAsString (optional): When
true, generated enum fields will use string values instead of enum member references. - useSignalFormTemplates (optional): When
true, generates form builder classes that also expose Angular Signals-based state (formValueSignal,isValidSignal) on top of reactive forms. Intended for Angular 17+. - generateFormsHelpers (optional, default
true): Control whetherFormsHelpers.tsis generated. - generateCustomValidators (optional, default
true): Control whetherCustomeValidators.tsis generated. - generateValidationManager (optional, default
true): Control whetherValidationManager.tsis generated. - generateShowForErrorDirective (optional, default
true): Control whetherShowForErrorDirective.tsis generated. - generateIFormBuilder (optional, default
true): Control whetherIFormBuilder.tsis generated. - generateDateHelper (optional, default
true): Control whetherDateHelper.tsis generated. - generateEnumHelper (optional, default
true): Control whetherEnumHelper.tsis generated. - customFormTemplatePath (optional): Path to a Node module that exports a
getTemplate(key, services)function (orformBuilderTemplate.getTemplate). When provided anduseSignalFormTemplatesisfalse, this function is used to generate the form builder class instead of the built-in template. - customSignalFormTemplatePath (optional): Same as
customFormTemplatePath, but used whenuseSignalFormTemplatesistrue. - generateValidationUiHelpers (optional, default
true): Control whetherValidationUiHelpers.ts(pipes +<afb-validation-errors>component andafbAutoErrorsdirective) is generated. - cleanupUnusedFiles (optional, default
true): Whentrue, remove.tsfiles underformsOutputthat no longer correspond to current schema models or enabled helpers. - includeModels (optional): Array of model names to generate forms for. When set, only these models are processed.
- excludeModels (optional): Array of model names to skip when generating forms.
- generateValidationMessagesJson (optional, default
true): Whentrue, generatevalidation-messages.en.jsoncontaining default validation messages for easy integration with i18n tools. - disableTlsVerification (optional, default
false): Whentrue, disables TLS certificate verification for HTTPS schema URLs (useful for self-signed certs in development). - generateFormWizard (optional, default
false): Whentrue, generatesFormWizard.ts— a generic multi-step wizard utility with fluent API.
Generating Angular API Services and Models
First, generate services and models using ng-openapi-gen :
ng-openapi-gen -c swagger.jsonEnsure that files are generated in the "output" path defined in swagger.json.
Generating Reactive FormsBuilder Classes
To generate Angular models' FormBuilder classes, execute the following command:
ng-frmGenerator swagger.json
or
ng-frmGeneratoronly because default filename for configuration is "swagger.json"
Example of Generated FormBuilder Class
Here is an example of a generated FormBuilder class for a simple user information form:
import { Injectable } from '@angular/core';
import { DatePipe } from '@angular/common';
import { FormControl, FormArray, FormGroup, FormBuilder, AbstractControl } from '@angular/forms';
import { IFormBuilder } from './IFormBuilder';
import { CustomerDto, UserAddressDto } from './../api/models';
import { UserAddressDtoFormBuilder } from './UserAddressDto';
import { oneOfValidator, guidValidator } from './CustomeValidators';
@Injectable({ providedIn: 'root' })
export class CustomerDtoFormBuilder implements IFormBuilder<CustomerDto> {
DatePipe: DatePipe = null as any;
DateFormat: string = 'yyyy-MM-dd';
form: FormGroup = null as any;
constructor(private fb: FormBuilder
, private UserAddressDtoFormBuilderSrvc: UserAddressDtoFormBuilder
) {
this.DatePipe = new DatePipe('en-US');
}
updateCulture(culture: string = 'en-US') {
this.DatePipe = new DatePipe(culture);
}
resetForm() {
this.form.reset();
}
buildForm(model: CustomerDto | null = null) {
this.form = this.fb.group({
userName: [ '' , Validators.compose([ Validators.required, Validators.minLength(1) ]) ],
password: [ '' , Validators.compose([ Validators.required ]) ],
addresses: [ this.UserAddressDtoFormBuilderSrvc.buildForm() ],
});
if (model != null) {
this.form.patchValue({ ...model });
}
return this.form;
}
get userNameCtrl(): FormControl {
return this.form.get('userName') as FormControl;
}
get userNameValueChanges$() {
return this.userNameCtrl?.valueChanges;
}
get passwordCtrl(): FormControl {
return this.form.get('password') as FormControl;
}
get passwordValueChanges$() {
return this.passwordCtrl?.valueChanges;
}
addressesArray(): FormArray {
return this.form.controls['addresses'] as FormArray;
}
addressesControls(): AbstractControl<any, any>[] {
return this.addressesArray().controls;
}
deleteAddressesByIndex(index: number): void {
this.addressesArray().removeAt(index);
}
addNewAddresses(model: UserAddressDtoFormBuilder | null = null): FormGroup<any> {
let frm = this.UserAddressDtoFormBuilderSrvc.buildForm(model);
this.addressesArray().push(frm);
return frm;
}
addNewaddresses(model: UserAddressDto | null = null): FormGroup<any> {
let frm = this.UserAddressDtoFormBuilderSrvc.buildForm(model);
this.addressesArray().push(frm);
return frm;
}
}
---
## Validation Ecosystem (Error Handling & Messages)
This generator ships a rich validation ecosystem to help you standardize error handling across your Angular app.
### Centralized ValidationManager
Generated file: `ValidationManager.ts`
- Exposes **typed error keys** via `ErrorTypes` / `ErrorKey` / `ErrorCode`.
- Provides default English messages with placeholders (e.g. `{requiredLength}`, `{min}`, `{max}`).
- Core APIs:
```ts
ValidationManager.getErrorMessage(control: FormControl): string;
ValidationManager.getMessages(control: AbstractControl): ValidationMessageVM[];
ValidationManager.errors$(control: AbstractControl): Observable<ValidationMessageVM[]>;You can plug in your own localization/branding using the message resolver hook:
ValidationManager.setMessageResolver(({ key, code, error, defaultTemplate, control }) => {
// key: 'Required' | 'MinLength' | ...
// code: 'required' | 'minlength' | ...
// error: Angular error object (e.g. { requiredLength, actualLength })
// defaultTemplate: e.g. 'Minimum length is {requiredLength} characters'
// Example: integrate with your i18n service
const translationKey = `validation.${key}`;
return myTranslate(translationKey, error) ?? defaultTemplate;
});Global Error HTML Template
You can define a global error template that will be auto-filled with the primary error message and control key.
ValidationManager.defineGlobalTemplate(
(control, element, messages) => `
<div class="invalid-feedback" for="ctrlKey">
ErrorPlaceHolder
</div>
`,
{
message: 'ErrorPlaceHolder', // will be replaced with the first error message
controlKey: 'ctrlKey' // will be replaced with the control name
}
);At runtime you can build the resolved HTML for a specific control/element:
const html = ValidationManager.buildGlobalTemplate({
control: myControl,
element: myInputElement,
controlKey: 'userName'
});Validation UI Helpers (Pipes, Component, Directive)
Generated file: ValidationUiHelpers.ts (enabled when generateValidationUiHelpers: true). It contains:
ValidationErrorPipe– returns the first error message for a control.<div *ngIf="userNameCtrl | validationError as err"> {{ err }} </div>ValidationErrorsPipe– returns all messages (ValidationMessageVM[]).<ul *ngIf="userNameCtrl | validationErrors as errs"> <li *ngFor="let e of errs">{{ e.message }}</li> </ul>ValidationErrorsComponent– reusable error list component:<afb-validation-errors [control]="userNameCtrl" [showAll]="false"></afb-validation-errors>AfbAutoErrorsDirective– attaches to a form and automatically appends the global error template next to invalid controls and also extends theFormGroupwith a helper method:<!-- auto show errors on submit --> <form [formGroup]="form" afbAutoErrors> ... </form> <!-- manual mode: trigger from code --> <form [formGroup]="form" [afbAutoErrors]="'manual'"> ... </form>// in your component this.form.showValidationErrors(); // or without HTML injection this.form.showValidationErrors({ generateHtml: false });ForFormArray– structural directive to iterate over aFormArrayby path on the parentFormGroup:<form [formGroup]="form"> <div *ForFormArray="'addresses'; let group; index as i"> <div [formGroup]="group"> <input formControlName="street" /> <button type="button" (click)="addressesArray().removeAt(i)">Remove</button> </div> </div> </form>
By default, it uses Bootstrap 5 classes:
is-invalidfor invalid form controlsinvalid-feedbackfor auto-generated error containers
You can also customize the CSS classes used for invalid controls and auto-generated error containers:
ValidationManager.setCssConfig({
invalidClass: 'my-invalid-class',
errorContainerClass: 'my-error-container'
});These helpers let you standardize error output while still giving you full control over localization, styling, and UI.
AutoFormsBuilderModule (Angular module & config)
When generateValidationUiHelpers: true, the generator also creates AutoFormsBuilderModule.ts, which exposes a ready-to-use Angular module for all validation UI features.
- Declares and exports:
ValidationErrorPipeandvalidationErrorspipe<afb-validation-errors>componentafbAutoErrorsdirectiveForFormArraystructural directive
- Supports global configuration via a static
initmethod.
Root module usage
import { NgModule } from '@angular/core';
import { ReactiveFormsModule } from '@angular/forms';
import { AutoFormsBuilderModule, AutoFormsBuilderConfig } from './forms/AutoFormsBuilderModule';
@NgModule({
imports: [
ReactiveFormsModule,
AutoFormsBuilderModule.init({
cssConfig: {
invalidClass: 'is-invalid',
errorContainerClass: 'invalid-feedback'
},
messageResolver: ({ key, error, defaultTemplate }) => {
const translationKey = `validation.${key}`;
return myTranslate(translationKey, error) ?? defaultTemplate;
},
globalTemplate: {
template: (control, element, messages) => `
<div class="invalid-feedback">
ErrorPlaceHolder
</div>
`,
placeholders: {
message: 'ErrorPlaceHolder'
}
}
} as AutoFormsBuilderConfig)
],
bootstrap: [AppComponent]
})
export class AppModule {}In feature modules, import the module without calling init again:
@NgModule({
imports: [AutoFormsBuilderModule]
})
export class FeatureModule {}FormValidator (Typed Validation Utilities)
Generated ValidationManager.ts now includes a typed FormValidator<T> class that wraps all validation utilities with IntelliSense:
import { FormValidator } from './forms/ValidationManager';
// Create a typed validator for your model
const v = new FormValidator<UserModel>(this.userFB.form);
// All errors in the form (flat list)
const allErrors = v.getAllErrors();
// [{ field: 'email', path: 'email', errors: { required: true }, messages: ['This field is required'] }]
// Check validity + mark touched in one call
if (v.isFormValid(true)) {
this.submit();
}
// Error count (for badges)
const count = v.errorCount(); // 3
// First invalid field path (for scroll)
const path = v.getFirstInvalidField(); // 'email'
// Observable of all errors (debounced)
v.errorMessages$().subscribe(errors => {
this.errorList = errors; // auto-updates on any change
});
// Apply server errors from API 400 response
v.applyServerErrors({ email: 'Already taken', password: 'Too weak' });
v.clearServerErrors();
// Dispose all subscriptions on destroy
ngOnDestroy() { v.dispose(); }Static API (no generics needed)
import { ValidationManager } from './forms/ValidationManager';
ValidationManager.getAllErrors(this.form);
ValidationManager.errorCount(this.form);
ValidationManager.getFirstInvalidField(this.form);
ValidationManager.isFormValid(this.form, true);
ValidationManager.errorMessages$(this.form).subscribe(...);Conditional Validators
The most common form boilerplate — make fields required/validated only when another field has a certain value:
Typed (with IntelliSense)
const v = new FormValidator<UserModel>(this.form);
// Company name required only when account type is 'business'
v.setRequiredIf(a => a.companyName, a => a.accountType, 'business');
// Add custom validators conditionally
v.conditionalValidators(
a => a.taxId, // target field
a => a.accountType, // source field
val => val === 'business', // condition
[Validators.required, Validators.minLength(9)]
);
// Cross-field rule: end date must be after start date
v.crossFieldRule(
[a => a.startDate, a => a.endDate],
form => {
const start = form.get('startDate')?.value;
const end = form.get('endDate')?.value;
return start && end && end <= start ? { dateRange: 'End must be after start' } : null;
},
a => a.endDate // apply error to this field
);String-based (no generics)
ValidationManager.setRequiredIf(this.form, 'companyName', 'accountType', 'business');
ValidationManager.conditionalValidators(
this.form, 'taxId', 'accountType',
v => v === 'business',
[Validators.required]
);
ValidationManager.crossFieldRule(
this.form,
['startDate', 'endDate'],
form => { ... },
'endDate'
);Validation Summary & Focus
<afb-validation-summary> — Show all errors in one place
<afb-validation-summary [form]="form"></afb-validation-summary>
<afb-validation-summary [form]="form" [showFieldName]="false"></afb-validation-summary>afbFocusOnError — Auto-scroll to first invalid field on submit
<form [formGroup]="form" afbFocusOnError (ngSubmit)="submit()">
<!-- On invalid submit, scrolls to and focuses the first invalid input -->
</form>i18n Support
Every error message now includes an i18nKey for integration with translation systems:
// Register with i18n key
ValidationManager.addErrorType('PhoneNumber', 'phoneNumber', 'Invalid phone number', 'validation.phoneNumber');
// Access i18n keys in your resolver
ValidationManager.setMessageResolver(({ key, code, error, defaultTemplate }) => {
const i18nKey = ValidationManager.getI18nKey(key) ?? 'validation.' + code;
return this.translate.instant(i18nKey, error) ?? defaultTemplate;
});Typed Field Access (IntelliSense)
Every generated form builder includes lambda-based methods that provide full IntelliSense in VS Code:
// Get a control — autocompletes all model properties
const emailCtrl = userFB.getControl(a => a.email);
// Set a value with type safety
userFB.setFieldValue(a => a.email, 'new@example.com');
// Watch a single field's changes
userFB.watchField(a => a.email).subscribe(value => {
console.log('Email changed:', value);
});These work in both the classic and signal-based templates.
Submit / Loading State
Built-in submit lifecycle management — validates, marks touched if invalid, tracks loading state:
// In your component
save() {
this.userFB.submit(val => this.http.post<User>('/api/users', val))
.subscribe({
next: (saved) => console.log('Done!', saved),
error: (err) => console.error(err)
});
}<!-- Disable button while submitting -->
<button [disabled]="userFB.isSubmitting">
{{ userFB.isSubmitting ? 'Saving...' : 'Save' }}
</button>For signal templates, isSubmittingSignal is also available as a readonly signal.
Bulk Operations
// Mark all controls as touched + dirty (trigger all validation messages)
userFB.markAllTouched();
// Disable entire form (view-only mode)
userFB.disableAll();
// Re-enable all controls
userFB.enableAll();Form Persistence (Drafts)
Save and restore form state to localStorage or sessionStorage:
// Save current form state
userFB.persistTo('user-draft');
// Restore on page load (returns true if data was found)
const restored = userFB.restoreFrom('user-draft');
// Clear after successful save
userFB.clearPersisted('user-draft');
// Use sessionStorage instead
userFB.persistTo('user-draft', sessionStorage);Clone Form
Create a new FormGroup with the same values as the current form:
const clonedForm = userFB.clone();Unsaved Changes Guard
Auto-generated UnsavedChangesGuard.ts prevents navigation away from dirty forms:
// app-routing.module.ts
import { UnsavedChangesGuard } from './forms/UnsavedChangesGuard';
const routes: Routes = [
{
path: 'user/edit',
component: UserEditComponent,
canDeactivate: [UnsavedChangesGuard]
}
];// user-edit.component.ts — implement the HasUnsavedChanges interface
import { HasUnsavedChanges } from './forms/UnsavedChangesGuard';
export class UserEditComponent implements HasUnsavedChanges {
canDeactivateMessage = 'You have unsaved changes. Leave anyway?';
constructor(public formBuilder: UserFormBuilder) {}
}Auto-Provide Form Builders
Generated FormProviders.ts eliminates manual provider arrays:
import { provideAllFormBuilders, provideFormBuilders } from './forms/FormProviders';
// Provide ALL form builders at once
@Component({
providers: provideAllFormBuilders()
})
export class AppComponent {}
// Or provide only specific ones
@Component({
providers: provideFormBuilders(UserFormBuilder, OrderFormBuilder)
})
export class UserPageComponent {}Multi-Step Wizard
Enable with "generateFormWizard": true. Generates a generic FormWizard<T> class with:
- Fluent step definition with IntelliSense field selection
- Step validation, navigation, and progress tracking
- Custom controls per step
- Step change observable
- Step error reporting
import { FormWizard } from './forms/FormWizard';
// Define steps with IntelliSense — VS Code autocompletes model properties
const wizard = new FormWizard<User>(userFormBuilder)
.setStep(1, [a => a.userName, a => a.fullName], 'Account Info')
.setStep(2, [a => a.email, a => a.phone], 'Contact')
.setStep(3, [a => a.password, a => a.repeatPassword], 'Security');
wizard.buildForm();Step Navigation
wizard.next(); // validates current step, moves forward
wizard.back(); // moves back
wizard.goToStep(2); // jump (validates all preceding steps)
wizard.progress; // 33, 66, 100 (percentage)
wizard.isFirstStep; // boolean
wizard.isLastStep; // boolean
wizard.canProceed(); // true if current step is validBuild Step FormGroups (for templates)
// Returns a FormGroup with only step 1 controls — synced with main form
const step1Form = wizard.buildStep(1, { userName: 'John' });
// Add custom controls not in the model
const step2Form = wizard.buildStep(2, null, [
{ name: 'agreedToTerms', control: new FormControl(false, Validators.requiredTrue) }
]);<form [formGroup]="step1Form">
<input formControlName="userName" />
<input formControlName="fullName" />
</form>Step Errors & Events
// Get structured errors for a step
wizard.getStepErrors(1);
// → [{ field: 'email', errors: { required: true } }]
// React to step transitions
wizard.onStepChange.subscribe(e => {
console.log(`Step ${e.from} → ${e.to}`);
});
// Typed field access on wizard
wizard.getControl(a => a.email);
wizard.setFieldValue(a => a.email, 'x@y.com');
wizard.watchField(a => a.email).subscribe(v => ...);
// Cleanup
wizard.dispose();Add/Remove Controls with IntelliSense
wizard.addControlToStep(1, a => a.email, new FormControl(''));
wizard.removeControlFromStep(1, a => a.email);
// Or plain string for custom (non-model) controls
wizard.addControlToStep(1, 'captchaToken', new FormControl());Date Helper
Generated DateHelper.ts provides zero-dependency date utilities commonly needed in form applications:
Form Date Binding
import { dateHelper } from './forms/DateHelper';
// Convert Date to <input type="date"> value
dateHelper.toFormControlValue(new Date()); // '2024-05-15'
// Convert <input type="date"> value back to Date
dateHelper.fromFormControlValue('2024-05-15'); // Date object
// ISO date-only for API payloads (no time component)
dateHelper.toISODateOnly(new Date()); // '2024-05-15'Formatting & Parsing
// Format with simple tokens
dateHelper.format(new Date(), 'yyyy-MM-dd'); // '2024-05-15'
dateHelper.format(new Date(), 'dd/MM/yyyy HH:mm'); // '15/05/2024 14:30'
// Parse reliably — handles yyyy-MM-dd, dd/MM/yyyy, ISO 8601
dateHelper.parse('2024-05-15'); // Date
dateHelper.parse('15/05/2024'); // Date
dateHelper.parse('invalid'); // nullValidation & Comparison
dateHelper.isValid('2024-02-30'); // false
dateHelper.isValid(new Date()); // true
dateHelper.isBefore(dateA, dateB); // true/false (ignores time)
dateHelper.isAfter(dateA, dateB); // true/false
dateHelper.isBetween(date, startDate, endDate); // inclusive range checkDay Boundaries & Arithmetic
dateHelper.startOfDay(new Date()); // 2024-05-15 00:00:00.000
dateHelper.endOfDay(new Date()); // 2024-05-15 23:59:59.999
dateHelper.addDays(date, 7);
dateHelper.addMonths(date, 3);
dateHelper.addYears(date, 1);
dateHelper.diffInDays(date1, date2);
dateHelper.diffInMonths(date1, date2);
dateHelper.diffInYears(date1, date2);What Is New?
Version 2.0.01
- Multi-Step Wizard —
FormWizard<T>with fluent.setStep()API, Proxy-based IntelliSense field selectors, step validation,buildStep(),onStepChange,getStepErrors(). - Typed field access —
getControl(a => a.field),setFieldValue(a => a.field, val),watchField(a => a.field)on all form builders. - Submit / loading state —
submit(saveFn)with autoisSubmittingmanagement. - Bulk operations —
markAllTouched(),disableAll(),enableAll(). - Clone —
clone()creates a new FormGroup with current values. - Persistence —
persistTo(key)/restoreFrom(key)/clearPersisted(key)for drafts. - Unsaved Changes Guard — auto-generated
CanDeactivateguard. - Auto-Provide —
provideAllFormBuilders()/provideFormBuilders(...)barrel. - Bug fixes — CompareFields validator, memory leaks in ShowForErrorDirective and signal templates, FormsExtensions.d.ts cleanup, cross-platform paths, recursive output directory creation.
- Schema support — oneOf/anyOf merging, inline enums, nested $ref objects, additionalProperties, OpenAPI 3.1 type arrays, exclusiveMin/Max, multipleOf, uniqueItems, nested arrays, array items with allOf/oneOf/anyOf.
Version 1.0.64
- Fix generated enum keys (Git Hub: Issue #8)
Version 1.0.64
- Add Template To Handle Array Of Enum Values
Version 1.0.62
- Fix Issue Of Patching Arrays Values
- Fix Issue Of Providers Dependency
- Fix Issue Where Enums In Some Cases Injected As Form builder
- New Features
- EnumHelper
- nameToSatetment: Converts Enum Pascal Key Into Readable Text Example: UserFinanceCompleted -> 'User Finance Completed'
- getValByName: Gets Value Of Enum Key Example: { red: 2 } -> getValByName('red') return 2
- getNameByVal: Gets Value Of Enum Key Example: { red: 2 } -> getNameByVal(2) return 'red'
- getAllEnumValues: Returns All Values Of Enum Example: { red: 2, blue:5 } return [ 2, 5 ]
- getAllEnumNames: Returns All Names Of Enum Example: { red: 2, blue:5 } return [ 'red', 'blue' ]
- hasValue: Checks If Enum Has Value Example: { red: 2 } -> HasValue(2) return true
- hasName: Checks If Enum Has Name Example: { red: 2 } -> hasName('red') return true
- ToKeyValArray: Returns List Of { key, value } Of Enum Example: { red: 2, blue:5 } returns [ { key: 'red', value: 2 } ] useful in cases of using enum as data source for drop down
- DateHelper
- addDays: Add Number Of Days To Date
- addMonths: Add Number Of Months To Date
- addYears: Add Number Of Years To Date
- diffInDays: Get Diff Between Two Dates In Days
- diffInMonths: Get Diff Between Two Dates In Months
- diffInYears: Get Diff Between Two Dates In Years
- ShowForErrorDirective
- showForError: used to show dome if control has sepcific error
<form [formGroup]="myFormGroup"> <!-- Other form elements --> <div showForError="required" formControlName="controlName"> This will show if 'invalidCharacters' error exists. </div> <!-- Other form elements --> </form>
- EnumHelper
Features (Detailed)
- Generate Angular FormBuilder classes for all models defined in your OpenAPI schema.
- Extend generated classes by inheritance in a separate service file so your custom logic stays upgrade-safe.
- Get strongly-typed control getters for better IntelliSense and refactoring support.
- Dramatically increase productivity by automating repetitive reactive forms setup so you can focus on your business logic instead of boilerplate.
- Per-property accessors:
{prop}Ctrlgetter and{prop}ValueChanges$observable generated for every field. - Array helpers:
addNew{Prop}(),delete{Prop}ByIndex(),{prop}Array(),{prop}Controls(),{prop}Valuegenerated for all array properties. - Lambda selectors:
getControl(a => a.field),setFieldValue(...),watchField(...)across all builders and wizard. - Submit lifecycle: One-call
submit(saveFn)validates, tracks loading, handles errors. - Form persistence: Draft save/restore to localStorage or sessionStorage.
- Unsaved changes: Route guard with zero config beyond
canDeactivatearray. - Multi-step wizard: Define steps declaratively, navigate with validation, get per-step error reports.
- Auto-provide barrel: No more manually listing every form builder in
providers.
Roadmap
- The next version is planned to include an option for internal creation of models, so you can let this generator produce TypeScript models directly from the OpenAPI schema without relying on an external models generator.
LLM Guidance
This repository includes an LLM file at the project root. It is a plain-text guide for AI coding assistants (LLMs) that:
- Explains the overall purpose of the generator and how it works with
ng-openapi-gen. - Describes key config options (
IParsedConfig), the template system, and the generated runtime files. - Documents important conventions (no comments in generated code, stable filenames/APIs) and safe-change guidelines.
The LLM file is not used at runtime. It exists only to help AI tools understand the project and make safer, more accurate changes when you ask them to modify this codebase.