Coming from ngx-formly? The migration guide maps defaultProps, extends, and the formly extensions API to their ng-forge equivalents.

Configure global defaults for all forms at provider level, or per-form via defaultProps.

The Cascade

ng-forge applies props in priority order — more specific always wins:

Library-level
withXxxFields({...})All forms
Form-level
defaultPropsOne form
Field-level
propsOne field


Custom Adapter Config

Custom adapters define their own config interface. The cascade pattern works the same way — implement a config merger in your adapter to support library-level and form-level defaults. See Building an Adapter for a full guide.

Library-level (provider)

// Define your own config interface:
export interface MyAdapterConfig {
  variant?: 'primary' | 'secondary';
  size?: 'sm' | 'lg';
}

// Pass it to withCustomFields():
provideDynamicForm(
  ...withCustomFields({ variant: 'primary', size: 'sm' })
)

Form-level (defaultProps)

Use (your form config type) from (your adapter package) for type-safe defaultProps with autocomplete.

// Define a typed FormConfig alias using your config:
import { FormConfig } from '@ng-forge/dynamic-forms';
import { MyAdapterConfig } from './my-adapter';

type MyFormConfig = FormConfig<any, any, MyAdapterConfig>;

const config = {
  defaultProps: {
    variant: 'secondary',
  },
  fields: [
    { type: 'my-input', key: 'name', label: 'Name' },
  ],
} as const satisfies MyFormConfig;


Field-level Props

Each field type also accepts its own adapter-specific props. See Field Types for the full per-field reference.

Nullable values

Value fields accept an optional nullable?: boolean flag. When true:

  • value accepts null in addition to the field's normal type (e.g. string | null).
  • An omitted value resolves to null instead of the type-specific empty default ('', NaN, [], …).
  • nullable stays orthogonal to required — they describe different layers. nullable declares that the model accepts null (data shape). required is a validation constraint. Angular's Validators.required treats null as invalid, so a field that is both nullable and required will fail required-validation when the value is null. The flags are independent OpenAPI concepts; combine them if that matches your schema, but understand the runtime interaction.
{
  key: 'middleName',
  type: 'input',
  label: 'Middle Name',
  nullable: true,
  value: null,       // allowed; also the resolved default when omitted
}

Read-side caveat. A user clearing a text input reads back as "", not null — this is a DOM/Web IDL contract, identical to classic Reactive Forms. nullable is a contract for accepted values, not a guarantee of emitted ones. If your backend distinguishes null from empty string, handle the coercion at submission.

Next Steps