Formwork Configuration
Formwork Configuration vs. Schematics Configuration
Section titled “Formwork Configuration vs. Schematics Configuration”There are two configuration files used by ngx-formwork
- Formwork Configuration:
formwork.config.ts - Schematics Configuration:
formwork.config.json
The schematics configuration is only used for the schematics and therefore only hold default values. This file is not relevant during runtime. All relevant options are shown on the schematics pages Generators and Register.
Formwork Configuration Object
Section titled “Formwork Configuration Object”The configuration object that is used by the provideFormwork function has these properties
| Property | Type | Required | Description |
|---|---|---|---|
| componentRegistrations | Record<string, Type | Yes | Mapping between keys and controls. |
| validatorRegistrations | [key]: (ValidatorFn | ValidatorKey | No | Mapping between keys and validators. |
| asyncValidatorRegistrations | [key]: (AsyncValidatorFn | ValidatorKey | No | Mapping between keys and async validators. |
| updateOn | ’change’ | ‘blur’ \ | ‘submit’ | No | Specifies when to update the control’s value. |
| globalConfig | NgxFwGlobalConfiguration | No | Configuration that is used for all controls. |
NgxFwGlobalConfiguration
Section titled “NgxFwGlobalConfiguration”This configuration provides a global runtime configuration that is used by all controls, groups or blocks.
| Property | Type | Required | Description |
|---|---|---|---|
| testIdBuilderFn | (content: NgxFwBaseContent,name: string,parentTestId?: string,) => string; | Yes | Function that is used to build the test id for a control |
Code Splitting
Section titled “Code Splitting”Registering all controls, validators, etc. directly in the app.config.ts is not ideal. ngx-formwork provides multiple approaches to organize your code better.
If you ran ng add with default parameters to install ngx-formwork your setup already is using split configurations.
This section assumes that you have read and understood the Registration Concepts and now how you need to set the configuration.
Using defineFormworkConfig
Section titled “Using defineFormworkConfig”Create a file next to your app.config.ts with this content to get started. The defineFormworkConfig function is a helper that provides type support when defining the configuration in a separate file.
import { defineFormworkConfig } from 'ngx-formwork';
export const formworkConfig = defineFormworkConfig({ componentRegistrations: { // Component registrations go here }, // validatorRegistrations are optional validatorRegistrations: { // Validator registrations go here }, // asyncValidatorRegistrations are optional asyncValidatorRegistrations: { // Async Validator registrations go here },});In app.config.ts use it like this:
import { formworkConfig } from './formwork.config.ts';
export const appConfig: ApplicationConfig = { providers: [ // other providers provideFormwork(formworkConfig), ],};Using Injection Tokens
Section titled “Using Injection Tokens”For more advanced code organization, you can leverage Angular’s dependency injection system by providing the tokens directly.
Component Registration with Tokens
Section titled “Component Registration with Tokens”import { Type } from '@angular/core';import { NGX_FW_COMPONENT_REGISTRATIONS } from 'ngx-formwork';import { TextControlComponent } from './components/text-control.component';import { GroupComponent } from './components/group.component';import { InfoBlockComponent } from './components/info-block.component';
export const componentRegistrationsProvider = { provide: NGX_FW_COMPONENT_REGISTRATIONS, useValue: new Map<string, Type<unknown>>([ ['text-control', TextControlComponent], ['group', GroupComponent], ['info', InfoBlockComponent], // more registrations... ]),};Validator Registration with Tokens
Section titled “Validator Registration with Tokens”import { ValidatorFn, AsyncValidatorFn } from '@angular/forms';import { NGX_FW_VALIDATOR_REGISTRATIONS, NGX_FW_ASYNC_VALIDATOR_REGISTRATIONS } from 'ngx-formwork';import { Validators } from '@angular/forms';import { letterValidator, noDuplicateValuesValidator, forbiddenLetterAValidator } from './validators';import { asyncValidator, asyncGroupValidator } from './async-validators';
// Synchronous validatorsexport const validatorRegistrationsProvider = { provide: NGX_FW_VALIDATOR_REGISTRATIONS, useValue: new Map<string, ValidatorFn[]>([ ['min-chars', [Validators.minLength(3)]], ['letter', [letterValidator]], ['combined', [Validators.minLength(3), Validators.required, letterValidator]], ['no-duplicates', [noDuplicateValuesValidator]], ['forbidden-letter-a', [forbiddenLetterAValidator]], // more registrations... ]),};
// Asynchronous validatorsexport const asyncValidatorRegistrationsProvider = { provide: NGX_FW_ASYNC_VALIDATOR_REGISTRATIONS, useValue: new Map<string, AsyncValidatorFn[]>([ ['async', [asyncValidator]], ['async-group', [asyncGroupValidator]], // more registrations... ]),};In app.config.ts use them like this:
import { componentRegistrationsProvider } from './component-registrations.provider';import { validatorRegistrationsProvider, asyncValidatorRegistrationsProvider } from './validator-registrations.provider';
export const appConfig: ApplicationConfig = { providers: [ // other providers provideFormwork(), // Custom providers MUST come after provideFormwork() componentRegistrationsProvider, validatorRegistrationsProvider, asyncValidatorRegistrationsProvider, ],};Multiple Configurations with Injection Tokens
Section titled “Multiple Configurations with Injection Tokens”You can also provide multiple configuration objects that will be merged according to their resolution strategy:
import { NGX_FW_COMPONENT_REGISTRATIONS, NGX_FW_VALIDATOR_REGISTRATIONS, NGX_FW_CONFIG } from 'ngx-formwork';
// First set of componentsexport const baseComponentsProvider = { provide: NGX_FW_COMPONENT_REGISTRATIONS, useValue: new Map([ ['text', TextComponent], ['number', NumberComponent], ]),};
// Additional components from a different moduleexport const extraComponentsProvider = { provide: NGX_FW_COMPONENT_REGISTRATIONS, useValue: new Map([ ['date', DateComponent], ['select', SelectComponent], ]),};
// Multiple global configs will be deep mergedexport const baseConfigProvider = { provide: NGX_FW_CONFIG, useValue: { testIdBuilderFn: (baseName, controlName) => `${baseName}-${controlName}`, },};
export const moduleConfigProvider = { provide: NGX_FW_CONFIG, useValue: { extraSettings: { theme: 'dark', }, },};Traditional Code Splitting
Section titled “Traditional Code Splitting”For simpler scenarios, you can still split your registration files by type while using the provideFormwork() function.
Controls Registration
Section titled “Controls Registration”Create a file with the following content, at whatever location makes sense.
export const componentRegistrations: ComponentRegistrationConfig = { 'text-control': TextControlComponent, group: GroupComponent, info: InfoBlockComponent, // more regsitrations...};In app.config.ts use it like this
import { componentRegistrations } from './controls.registerations.ts';
export const appConfig: ApplicationConfig = { providers: [ // other providers provideFormwork({ componentRegistrations, }), ],};In formwork.config.ts use it like this
import { componentRegistrations } from './controls.registerations.ts';
export const formworkConfig = defineFormworkConfig({ // other providers componentRegistrations,});Validators Registration
Section titled “Validators Registration”Create a file with the following content, at whatever location makes sense. You can also further split the files between sync and async validators
export const validatorRegistrations: ValidatorConfig<RegistrationRecord> = { 'min-chars': [Validators.minLength(3)], letter: [letterValidator], combined: ['min-chars', Validators.required, 'letter'], 'no-duplicates': [noDuplicateValuesValidator], 'forbidden-letter-a': [forbiddenLetterAValidator],};
export const asyncValidatorRegistrations: AsyncValidatorConfig<RegistrationRecord> = { async: [asyncValidator], 'async-group': [asyncGroupValidator],};In app.config.ts use it like this
import { validatorRegistrations, asyncValidatorRegistrations } from './validators.registerations.ts';
export const appConfig: ApplicationConfig = { providers: [ // other providers provideFormwork({ validatorRegistrations, asyncValidatorRegistrations, }), ],};In formwork.config.ts use it like this
import { componentRegistrations } from './controls.registerations.ts';
export const formworkConfig = defineFormworkConfig({ // other providers componentRegistrations: { validatorRegistrations, asyncValidatorRegistrations, },});export const validatorRegistrations: ValidatorConfig<RegistrationRecord> = { letter: [letterValidator], // ⚠️ letter only spelled with one T. // This will give an TS error in the provideFormwork function, but not in this case combined: [Validators.required, 'leter'],};Global Configuration with Injection Tokens
Section titled “Global Configuration with Injection Tokens”For advanced scenarios, you can provide global configuration options using the NGX_FW_CONFIG injection token.
import { NGX_FW_CONFIG } from 'ngx-formwork';import { TestIdBuilderFn } from 'ngx-formwork';
// Example test ID builder functionconst testIdBuilder: TestIdBuilderFn = (baseName, controlName) => { return `${baseName}-${controlName}`;};
export const globalConfigProvider = { provide: NGX_FW_CONFIG, useValue: { testIdBuilderFn: testIdBuilder, },};In app.config.ts use it like this:
import { globalConfigProvider } from './global-config.provider';
export const appConfig: ApplicationConfig = { providers: [ // other providers provideFormwork(), globalConfigProvider, ],};