@ng-forge/dynamic-forms 0.9.0-next.8 → 0.9.0-next.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (21) hide show
  1. package/fesm2022/{ng-forge-dynamic-forms-array-field.component-CltYGHg9.mjs → ng-forge-dynamic-forms-array-field.component-us7mQtVQ.mjs} +3 -3
  2. package/fesm2022/{ng-forge-dynamic-forms-array-field.component-CltYGHg9.mjs.map → ng-forge-dynamic-forms-array-field.component-us7mQtVQ.mjs.map} +1 -1
  3. package/fesm2022/{ng-forge-dynamic-forms-container-field.component-D4Fpr2ri.mjs → ng-forge-dynamic-forms-container-field.component-BCIQ6_Mm.mjs} +3 -3
  4. package/fesm2022/{ng-forge-dynamic-forms-container-field.component-D4Fpr2ri.mjs.map → ng-forge-dynamic-forms-container-field.component-BCIQ6_Mm.mjs.map} +1 -1
  5. package/fesm2022/{ng-forge-dynamic-forms-container-utils-BTiqZ8Np.mjs → ng-forge-dynamic-forms-container-utils-CzZlFNA0.mjs} +2 -2
  6. package/fesm2022/{ng-forge-dynamic-forms-container-utils-BTiqZ8Np.mjs.map → ng-forge-dynamic-forms-container-utils-CzZlFNA0.mjs.map} +1 -1
  7. package/fesm2022/{ng-forge-dynamic-forms-css-wrapper.component-mdfySFjX.mjs → ng-forge-dynamic-forms-css-wrapper.component-Dhlf6UxN.mjs} +2 -2
  8. package/fesm2022/{ng-forge-dynamic-forms-css-wrapper.component-mdfySFjX.mjs.map → ng-forge-dynamic-forms-css-wrapper.component-Dhlf6UxN.mjs.map} +1 -1
  9. package/fesm2022/{ng-forge-dynamic-forms-emit-initialization-Bt3kvlOY.mjs → ng-forge-dynamic-forms-emit-initialization-DqQ8BA4W.mjs} +2 -2
  10. package/fesm2022/{ng-forge-dynamic-forms-emit-initialization-Bt3kvlOY.mjs.map → ng-forge-dynamic-forms-emit-initialization-DqQ8BA4W.mjs.map} +1 -1
  11. package/fesm2022/{ng-forge-dynamic-forms-group-field.component-BxswrhOc.mjs → ng-forge-dynamic-forms-group-field.component-DKcoco0G.mjs} +3 -3
  12. package/fesm2022/{ng-forge-dynamic-forms-group-field.component-BxswrhOc.mjs.map → ng-forge-dynamic-forms-group-field.component-DKcoco0G.mjs.map} +1 -1
  13. package/fesm2022/{ng-forge-dynamic-forms-ng-forge-dynamic-forms-QdV2vcCx.mjs → ng-forge-dynamic-forms-ng-forge-dynamic-forms-CfbmSRM_.mjs} +202 -30
  14. package/fesm2022/ng-forge-dynamic-forms-ng-forge-dynamic-forms-CfbmSRM_.mjs.map +1 -0
  15. package/fesm2022/{ng-forge-dynamic-forms-page-field.component-BHNVryIq.mjs → ng-forge-dynamic-forms-page-field.component-DqWAcwhG.mjs} +3 -3
  16. package/fesm2022/{ng-forge-dynamic-forms-page-field.component-BHNVryIq.mjs.map → ng-forge-dynamic-forms-page-field.component-DqWAcwhG.mjs.map} +1 -1
  17. package/fesm2022/{ng-forge-dynamic-forms-text-field.component-Cf1mEKVW.mjs → ng-forge-dynamic-forms-text-field.component-8C1-oyU_.mjs} +2 -2
  18. package/fesm2022/{ng-forge-dynamic-forms-text-field.component-Cf1mEKVW.mjs.map → ng-forge-dynamic-forms-text-field.component-8C1-oyU_.mjs.map} +1 -1
  19. package/fesm2022/ng-forge-dynamic-forms.mjs +1 -1
  20. package/package.json +1 -1
  21. package/fesm2022/ng-forge-dynamic-forms-ng-forge-dynamic-forms-QdV2vcCx.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"ng-forge-dynamic-forms-css-wrapper.component-mdfySFjX.mjs","sources":["../../../../packages/dynamic-forms/src/lib/wrappers/css/css-wrapper.component.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, input, Signal, ViewContainerRef, viewChild } from '@angular/core';\nimport { pipe, switchMap } from 'rxjs';\nimport { derivedFrom } from 'ngxtension/derived-from';\nimport { FieldWrapperContract } from '../../models/wrapper-type';\nimport { DynamicText } from '../../models/types/dynamic-text';\nimport { dynamicTextToObservable } from '../../utils/dynamic-text-to-observable';\nimport { WrapperFieldInputs } from '../wrapper-field-inputs';\n\n/**\n * Built-in CSS wrapper component.\n *\n * Applies CSS classes from the `cssClasses` config property to the host element,\n * wrapping the inner content (next wrapper or children) in its ViewContainerRef slot.\n *\n * Receives `cssClasses` as an individual Angular input (set by the outlet via\n * `setInput()`). `fieldInputs` carries the wrapped field's mapper outputs +\n * a read-only view of its form state (via `ReadonlyFieldTree`).\n *\n * @example\n * ```typescript\n * {\n * type: 'container',\n * key: 'styled',\n * wrappers: [{ type: 'css', cssClasses: 'card p-4' }],\n * fields: [...]\n * }\n * ```\n */\n@Component({\n selector: 'df-css-wrapper',\n template: `<ng-container #fieldComponent></ng-container>`,\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n '[class]': 'resolvedClasses()',\n },\n})\nexport default class CssWrapperComponent implements FieldWrapperContract {\n readonly fieldComponent = viewChild.required('fieldComponent', { read: ViewContainerRef });\n\n readonly cssClasses = input<DynamicText>();\n readonly fieldInputs = input<WrapperFieldInputs>();\n\n readonly resolvedClasses: Signal<string> = derivedFrom([this.cssClasses], pipe(switchMap(([value]) => dynamicTextToObservable(value))), {\n initialValue: '',\n });\n}\n\nexport { CssWrapperComponent };\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ng-forge-dynamic-forms-css-wrapper.component-Dhlf6UxN.mjs","sources":["../../../../packages/dynamic-forms/src/lib/wrappers/css/css-wrapper.component.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, input, Signal, ViewContainerRef, viewChild } from '@angular/core';\nimport { pipe, switchMap } from 'rxjs';\nimport { derivedFrom } from 'ngxtension/derived-from';\nimport { FieldWrapperContract } from '../../models/wrapper-type';\nimport { DynamicText } from '../../models/types/dynamic-text';\nimport { dynamicTextToObservable } from '../../utils/dynamic-text-to-observable';\nimport { WrapperFieldInputs } from '../wrapper-field-inputs';\n\n/**\n * Built-in CSS wrapper component.\n *\n * Applies CSS classes from the `cssClasses` config property to the host element,\n * wrapping the inner content (next wrapper or children) in its ViewContainerRef slot.\n *\n * Receives `cssClasses` as an individual Angular input (set by the outlet via\n * `setInput()`). `fieldInputs` carries the wrapped field's mapper outputs +\n * a read-only view of its form state (via `ReadonlyFieldTree`).\n *\n * @example\n * ```typescript\n * {\n * type: 'container',\n * key: 'styled',\n * wrappers: [{ type: 'css', cssClasses: 'card p-4' }],\n * fields: [...]\n * }\n * ```\n */\n@Component({\n selector: 'df-css-wrapper',\n template: `<ng-container #fieldComponent></ng-container>`,\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n '[class]': 'resolvedClasses()',\n },\n})\nexport default class CssWrapperComponent implements FieldWrapperContract {\n readonly fieldComponent = viewChild.required('fieldComponent', { read: ViewContainerRef });\n\n readonly cssClasses = input<DynamicText>();\n readonly fieldInputs = input<WrapperFieldInputs>();\n\n readonly resolvedClasses: Signal<string> = derivedFrom([this.cssClasses], pipe(switchMap(([value]) => dynamicTextToObservable(value))), {\n initialValue: '',\n });\n}\n\nexport { CssWrapperComponent };\n"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { afterNextRender } from '@angular/core';
2
- import { D as DynamicFormLogger, t as ComponentInitializedEvent } from './ng-forge-dynamic-forms-ng-forge-dynamic-forms-QdV2vcCx.mjs';
2
+ import { D as DynamicFormLogger, t as ComponentInitializedEvent } from './ng-forge-dynamic-forms-ng-forge-dynamic-forms-CfbmSRM_.mjs';
3
3
 
4
4
  /**
5
5
  * Emits a component initialization event after the next render cycle.
@@ -26,4 +26,4 @@ function emitComponentInitialized(eventBus, componentType, componentKey, injecto
26
26
  }
27
27
 
28
28
  export { emitComponentInitialized as e };
29
- //# sourceMappingURL=ng-forge-dynamic-forms-emit-initialization-Bt3kvlOY.mjs.map
29
+ //# sourceMappingURL=ng-forge-dynamic-forms-emit-initialization-DqQ8BA4W.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ng-forge-dynamic-forms-emit-initialization-Bt3kvlOY.mjs","sources":["../../../../packages/dynamic-forms/src/lib/utils/emit-initialization/emit-initialization.ts"],"sourcesContent":["import { afterNextRender, Injector } from '@angular/core';\nimport { EventBus } from '../../events/event.bus';\nimport { ComponentInitializedEvent } from '../../events/constants/component-initialized.event';\nimport { DynamicFormLogger } from '../../providers/features/logger/logger.token';\n\n/**\n * Component type for initialization events.\n */\nexport type InitializationComponentType = 'dynamic-form' | 'group' | 'page' | 'array' | 'container';\n\n/**\n * Emits a component initialization event after the next render cycle.\n *\n * This utility is used by container components (group, page, array, container) to signal\n * that their child fields have been resolved and rendered. The event is dispatched\n * through the EventBus and is used by the initialization tracking system.\n *\n * @param eventBus - The EventBus instance to dispatch the event on\n * @param componentType - The type of component being initialized\n * @param componentKey - The unique key/id of the component\n * @param injector - The injector to use for afterNextRender scheduling\n */\nexport function emitComponentInitialized(\n eventBus: EventBus,\n componentType: InitializationComponentType,\n componentKey: string,\n injector: Injector,\n): void {\n const logger = injector.get(DynamicFormLogger);\n\n afterNextRender(\n () => {\n try {\n eventBus.dispatch(ComponentInitializedEvent, componentType, componentKey);\n } catch (error: unknown) {\n logger.error(`Failed to emit initialization event for ${componentType} '${componentKey}'`, error);\n }\n },\n { injector },\n );\n}\n"],"names":[],"mappings":";;;AAUA;;;;;;;;;;;AAWG;AACG,SAAU,wBAAwB,CACtC,QAAkB,EAClB,aAA0C,EAC1C,YAAoB,EACpB,QAAkB,EAAA;IAElB,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,iBAAiB,CAAC;IAE9C,eAAe,CACb,MAAK;AACH,QAAA,IAAI;YACF,QAAQ,CAAC,QAAQ,CAAC,yBAAyB,EAAE,aAAa,EAAE,YAAY,CAAC;QAC3E;QAAE,OAAO,KAAc,EAAE;YACvB,MAAM,CAAC,KAAK,CAAC,CAAA,wCAAA,EAA2C,aAAa,CAAA,EAAA,EAAK,YAAY,CAAA,CAAA,CAAG,EAAE,KAAK,CAAC;QACnG;AACF,IAAA,CAAC,EACD,EAAE,QAAQ,EAAE,CACb;AACH;;;;"}
1
+ {"version":3,"file":"ng-forge-dynamic-forms-emit-initialization-DqQ8BA4W.mjs","sources":["../../../../packages/dynamic-forms/src/lib/utils/emit-initialization/emit-initialization.ts"],"sourcesContent":["import { afterNextRender, Injector } from '@angular/core';\nimport { EventBus } from '../../events/event.bus';\nimport { ComponentInitializedEvent } from '../../events/constants/component-initialized.event';\nimport { DynamicFormLogger } from '../../providers/features/logger/logger.token';\n\n/**\n * Component type for initialization events.\n */\nexport type InitializationComponentType = 'dynamic-form' | 'group' | 'page' | 'array' | 'container';\n\n/**\n * Emits a component initialization event after the next render cycle.\n *\n * This utility is used by container components (group, page, array, container) to signal\n * that their child fields have been resolved and rendered. The event is dispatched\n * through the EventBus and is used by the initialization tracking system.\n *\n * @param eventBus - The EventBus instance to dispatch the event on\n * @param componentType - The type of component being initialized\n * @param componentKey - The unique key/id of the component\n * @param injector - The injector to use for afterNextRender scheduling\n */\nexport function emitComponentInitialized(\n eventBus: EventBus,\n componentType: InitializationComponentType,\n componentKey: string,\n injector: Injector,\n): void {\n const logger = injector.get(DynamicFormLogger);\n\n afterNextRender(\n () => {\n try {\n eventBus.dispatch(ComponentInitializedEvent, componentType, componentKey);\n } catch (error: unknown) {\n logger.error(`Failed to emit initialization event for ${componentType} '${componentKey}'`, error);\n }\n },\n { injector },\n );\n}\n"],"names":[],"mappings":";;;AAUA;;;;;;;;;;;AAWG;AACG,SAAU,wBAAwB,CACtC,QAAkB,EAClB,aAA0C,EAC1C,YAAoB,EACpB,QAAkB,EAAA;IAElB,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,iBAAiB,CAAC;IAE9C,eAAe,CACb,MAAK;AACH,QAAA,IAAI;YACF,QAAQ,CAAC,QAAQ,CAAC,yBAAyB,EAAE,aAAa,EAAE,YAAY,CAAC;QAC3E;QAAE,OAAO,KAAc,EAAE;YACvB,MAAM,CAAC,KAAK,CAAC,CAAA,wCAAA,EAA2C,aAAa,CAAA,EAAA,EAAK,YAAY,CAAA,CAAA,CAAG,EAAE,KAAK,CAAC;QACnG;AACF,IAAA,CAAC,EACD,EAAE,QAAQ,EAAE,CACb;AACH;;;;"}
@@ -1,9 +1,9 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { inject, DestroyRef, Injector, EnvironmentInjector, input, computed, linkedSignal, runInInjectionContext, untracked, ChangeDetectionStrategy, Component } from '@angular/core';
3
- import { i as injectFieldRegistry, F as FIELD_SIGNAL_CONTEXT, E as EventBus, D as DynamicFormLogger, C as CONTAINER_FIELD_PROCESSORS, g as isEqual, h as createSchemaFromFields, d as derivedFromDeferred, c as createFieldResolutionPipe, f as DfFieldOutlet } from './ng-forge-dynamic-forms-ng-forge-dynamic-forms-QdV2vcCx.mjs';
3
+ import { i as injectFieldRegistry, F as FIELD_SIGNAL_CONTEXT, E as EventBus, D as DynamicFormLogger, C as CONTAINER_FIELD_PROCESSORS, g as isEqual, h as createSchemaFromFields, d as derivedFromDeferred, c as createFieldResolutionPipe, f as DfFieldOutlet } from './ng-forge-dynamic-forms-ng-forge-dynamic-forms-CfbmSRM_.mjs';
4
4
  import { outputFromObservable, toObservable } from '@angular/core/rxjs-interop';
5
5
  import { explicitEffect } from 'ngxtension/explicit-effect';
6
- import { c as computeContainerHostClasses, s as setupContainerInitEffect } from './ng-forge-dynamic-forms-container-utils-BTiqZ8Np.mjs';
6
+ import { c as computeContainerHostClasses, s as setupContainerInitEffect } from './ng-forge-dynamic-forms-container-utils-CzZlFNA0.mjs';
7
7
  import { form } from '@angular/forms/signals';
8
8
 
9
9
  /**
@@ -183,4 +183,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
183
183
  }], ctorParameters: () => [], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], hidden: [{ type: i0.Input, args: [{ isSignal: true, alias: "hidden", required: false }] }], validityChange: [{ type: i0.Output, args: ["validityChange"] }], dirtyChange: [{ type: i0.Output, args: ["dirtyChange"] }], submitted: [{ type: i0.Output, args: ["submitted"] }] } });
184
184
 
185
185
  export { GroupFieldComponent, GroupFieldComponent as default };
186
- //# sourceMappingURL=ng-forge-dynamic-forms-group-field.component-BxswrhOc.mjs.map
186
+ //# sourceMappingURL=ng-forge-dynamic-forms-group-field.component-DKcoco0G.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ng-forge-dynamic-forms-group-field.component-BxswrhOc.mjs","sources":["../../../../packages/dynamic-forms/src/lib/fields/group/group-field.component.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n computed,\n DestroyRef,\n EnvironmentInjector,\n inject,\n Injector,\n input,\n linkedSignal,\n runInInjectionContext,\n untracked,\n} from '@angular/core';\nimport { DfFieldOutlet } from '../../directives/df-field-outlet.directive';\nimport { outputFromObservable, toObservable } from '@angular/core/rxjs-interop';\nimport { explicitEffect } from 'ngxtension/explicit-effect';\nimport { derivedFromDeferred } from '../../utils/derived-from-deferred/derived-from-deferred';\nimport { createFieldResolutionPipe, ResolvedField } from '../../utils/resolve-field/resolve-field';\nimport { computeContainerHostClasses, setupContainerInitEffect } from '../../utils/container-utils/container-utils';\nimport { CONTAINER_FIELD_PROCESSORS } from '../../utils/container-utils/container-field-processors';\nimport { isEqual } from '../../utils/object-utils';\nimport { DynamicFormLogger } from '../../providers/features/logger/logger.token';\nimport { GroupField } from '../../definitions/default/group-field';\nimport { injectFieldRegistry } from '../../utils/inject-field-registry/inject-field-registry';\nimport { FieldTree, form } from '@angular/forms/signals';\nimport { FieldDef } from '../../definitions/base/field-def';\nimport { FieldSignalContext } from '../../mappers/types';\nimport { FIELD_SIGNAL_CONTEXT } from '../../models/field-signal-context.token';\nimport { createSchemaFromFields } from '../../core/schema-builder';\nimport { EventBus } from '../../events/event.bus';\nimport { SubmitEvent } from '../../events/constants/submit.event';\n\n/**\n * Container component for rendering nested form groups.\n *\n * Creates a scoped form context with its own validation state.\n * Child fields receive a FIELD_SIGNAL_CONTEXT scoped to this group's form instance.\n * Group values are nested under the group's key in the parent form.\n */\n@Component({\n selector: 'fieldset[group-field]',\n imports: [DfFieldOutlet],\n template: `\n @for (field of resolvedFields(); track field.key) {\n <ng-container *dfFieldOutlet=\"field; environmentInjector: environmentInjector\" />\n }\n `,\n styleUrl: './group-field.component.scss',\n host: {\n '[class]': 'hostClasses()',\n role: 'group',\n '[class.disabled]': 'disabled()',\n '[class.df-container-hidden]': 'hidden()',\n '[attr.aria-hidden]': 'hidden() || null',\n '[id]': '`${key()}`',\n '[attr.data-testid]': 'key()',\n },\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport default class GroupFieldComponent<TModel extends Record<string, unknown> = Record<string, unknown>> {\n // ─────────────────────────────────────────────────────────────────────────────\n // Dependencies\n // ─────────────────────────────────────────────────────────────────────────────\n\n private readonly destroyRef = inject(DestroyRef);\n private readonly fieldRegistry = injectFieldRegistry();\n private readonly parentFieldSignalContext = inject(FIELD_SIGNAL_CONTEXT) as FieldSignalContext<TModel>;\n private readonly injector = inject(Injector);\n protected readonly environmentInjector = inject(EnvironmentInjector);\n private readonly eventBus = inject(EventBus);\n private readonly logger = inject(DynamicFormLogger);\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Memoized Functions\n // ─────────────────────────────────────────────────────────────────────────────\n\n private readonly fieldProcessors = inject(CONTAINER_FIELD_PROCESSORS);\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Inputs\n // ─────────────────────────────────────────────────────────────────────────────\n\n field = input.required<GroupField>();\n key = input.required<string>();\n className = input<string>();\n hidden = input(false);\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Computed Signals\n // ─────────────────────────────────────────────────────────────────────────────\n\n readonly hostClasses = computed(() => computeContainerHostClasses('group', this.className()));\n\n private readonly rawFieldRegistry = computed(() => this.fieldRegistry.raw);\n\n private readonly formSetup = computed(() => {\n const groupField = this.field();\n const registry = this.rawFieldRegistry();\n\n if (groupField.fields && groupField.fields.length > 0) {\n const flattenedFields = this.fieldProcessors.memoizedFlattenFields(groupField.fields, registry);\n const flattenedFieldsForRendering = this.fieldProcessors.memoizedFlattenFieldsForRendering(groupField.fields, registry);\n const fieldsById = this.fieldProcessors.memoizedKeyBy(flattenedFields);\n const defaultValues = this.fieldProcessors.memoizedDefaultValues(fieldsById, registry);\n\n return {\n fields: flattenedFieldsForRendering,\n schemaFields: flattenedFields,\n originalFields: groupField.fields,\n defaultValues,\n registry,\n };\n }\n\n return {\n fields: [],\n schemaFields: [],\n originalFields: [],\n defaultValues: {},\n registry,\n };\n });\n\n readonly defaultValues = linkedSignal(() => this.formSetup().defaultValues);\n\n /**\n * Entity computed from parent value, group key, and defaults.\n * Uses deep equality check to prevent unnecessary updates when\n * object spread creates new references with identical values.\n */\n private readonly entity = linkedSignal(\n () => {\n const parentValue = this.parentFieldSignalContext.value();\n const groupKey = this.field().key;\n const defaults = this.defaultValues();\n const groupValue = (parentValue as Record<string, unknown>)?.[groupKey] || {};\n return { ...defaults, ...groupValue };\n },\n {\n debugName: 'GroupFieldComponent.entity',\n equal: isEqual,\n },\n );\n\n private readonly form = computed(() => {\n return runInInjectionContext(this.injector, () => {\n const setup = this.formSetup();\n\n if (setup.schemaFields.length > 0) {\n const schema = createSchemaFromFields(setup.schemaFields, setup.registry);\n return untracked(() => form(this.entity, schema));\n }\n\n return untracked(() => form(this.entity));\n });\n });\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Public State Signals\n // ─────────────────────────────────────────────────────────────────────────────\n\n readonly formValue = computed(() => this.entity());\n readonly valid = computed(() => this.form()().valid());\n readonly invalid = computed(() => this.form()().invalid());\n readonly dirty = computed(() => this.form()().dirty());\n readonly touched = computed(() => this.form()().touched());\n readonly errors = computed(() => this.form()().errors());\n readonly disabled = computed(() => this.form()().disabled());\n\n private readonly nestedFieldTree = computed((): FieldTree<Record<string, unknown>> | undefined => {\n const parentForm = this.parentFieldSignalContext.form as Record<string, FieldTree<Record<string, unknown>>>;\n const groupKey = this.field().key;\n return parentForm[groupKey];\n });\n\n private readonly groupFieldSignalContext: FieldSignalContext<Record<string, unknown>> = (() => {\n const nestedFieldTree = this.nestedFieldTree;\n return {\n injector: this.injector,\n value: this.parentFieldSignalContext.value,\n defaultValues: this.defaultValues,\n get form() {\n return nestedFieldTree() ?? ({} as FieldTree<Record<string, unknown>>);\n },\n };\n })();\n\n private readonly groupInjector = Injector.create({\n parent: this.injector,\n providers: [{ provide: FIELD_SIGNAL_CONTEXT, useValue: this.groupFieldSignalContext }],\n });\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Outputs\n // ─────────────────────────────────────────────────────────────────────────────\n\n readonly validityChange = outputFromObservable(toObservable(this.valid));\n readonly dirtyChange = outputFromObservable(toObservable(this.dirty));\n readonly submitted = outputFromObservable(this.eventBus.on<SubmitEvent>('submit'));\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Field Resolution\n // ─────────────────────────────────────────────────────────────────────────────\n\n private readonly fieldsSource = computed(() => this.formSetup().fields);\n\n protected readonly resolvedFields = derivedFromDeferred(\n this.fieldsSource,\n createFieldResolutionPipe(() => ({\n loadTypeComponent: (type: string) => this.fieldRegistry.loadTypeComponent(type),\n registry: this.rawFieldRegistry(),\n injector: this.groupInjector,\n destroyRef: this.destroyRef,\n onError: (fieldDef: FieldDef<unknown>, error: unknown) => {\n const fieldKey = fieldDef.key || '<no key>';\n this.logger.error(\n `Failed to load component for field type '${fieldDef.type}' (key: ${fieldKey}) ` +\n `within group '${this.field().key}'. Ensure the field type is registered in your field registry.`,\n error,\n );\n },\n })),\n { initialValue: [] as ResolvedField[], injector: this.injector },\n );\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Constructor\n // ─────────────────────────────────────────────────────────────────────────────\n\n constructor() {\n this.setupEffects();\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Private Methods\n // ─────────────────────────────────────────────────────────────────────────────\n\n private setupEffects(): void {\n setupContainerInitEffect(this.resolvedFields, this.eventBus, 'group', () => this.field().key, this.injector);\n\n explicitEffect(\n [this.nestedFieldTree, this.field],\n ([tree, field]) => {\n if (!tree) {\n this.logger.warn(\n `Group field \"${field.key}\" not found in parent form. ` + `Ensure the parent form schema includes this group field.`,\n );\n }\n },\n { defer: true },\n );\n }\n}\n\nexport { GroupFieldComponent };\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ng-forge-dynamic-forms-group-field.component-DKcoco0G.mjs","sources":["../../../../packages/dynamic-forms/src/lib/fields/group/group-field.component.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n computed,\n DestroyRef,\n EnvironmentInjector,\n inject,\n Injector,\n input,\n linkedSignal,\n runInInjectionContext,\n untracked,\n} from '@angular/core';\nimport { DfFieldOutlet } from '../../directives/df-field-outlet.directive';\nimport { outputFromObservable, toObservable } from '@angular/core/rxjs-interop';\nimport { explicitEffect } from 'ngxtension/explicit-effect';\nimport { derivedFromDeferred } from '../../utils/derived-from-deferred/derived-from-deferred';\nimport { createFieldResolutionPipe, ResolvedField } from '../../utils/resolve-field/resolve-field';\nimport { computeContainerHostClasses, setupContainerInitEffect } from '../../utils/container-utils/container-utils';\nimport { CONTAINER_FIELD_PROCESSORS } from '../../utils/container-utils/container-field-processors';\nimport { isEqual } from '../../utils/object-utils';\nimport { DynamicFormLogger } from '../../providers/features/logger/logger.token';\nimport { GroupField } from '../../definitions/default/group-field';\nimport { injectFieldRegistry } from '../../utils/inject-field-registry/inject-field-registry';\nimport { FieldTree, form } from '@angular/forms/signals';\nimport { FieldDef } from '../../definitions/base/field-def';\nimport { FieldSignalContext } from '../../mappers/types';\nimport { FIELD_SIGNAL_CONTEXT } from '../../models/field-signal-context.token';\nimport { createSchemaFromFields } from '../../core/schema-builder';\nimport { EventBus } from '../../events/event.bus';\nimport { SubmitEvent } from '../../events/constants/submit.event';\n\n/**\n * Container component for rendering nested form groups.\n *\n * Creates a scoped form context with its own validation state.\n * Child fields receive a FIELD_SIGNAL_CONTEXT scoped to this group's form instance.\n * Group values are nested under the group's key in the parent form.\n */\n@Component({\n selector: 'fieldset[group-field]',\n imports: [DfFieldOutlet],\n template: `\n @for (field of resolvedFields(); track field.key) {\n <ng-container *dfFieldOutlet=\"field; environmentInjector: environmentInjector\" />\n }\n `,\n styleUrl: './group-field.component.scss',\n host: {\n '[class]': 'hostClasses()',\n role: 'group',\n '[class.disabled]': 'disabled()',\n '[class.df-container-hidden]': 'hidden()',\n '[attr.aria-hidden]': 'hidden() || null',\n '[id]': '`${key()}`',\n '[attr.data-testid]': 'key()',\n },\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport default class GroupFieldComponent<TModel extends Record<string, unknown> = Record<string, unknown>> {\n // ─────────────────────────────────────────────────────────────────────────────\n // Dependencies\n // ─────────────────────────────────────────────────────────────────────────────\n\n private readonly destroyRef = inject(DestroyRef);\n private readonly fieldRegistry = injectFieldRegistry();\n private readonly parentFieldSignalContext = inject(FIELD_SIGNAL_CONTEXT) as FieldSignalContext<TModel>;\n private readonly injector = inject(Injector);\n protected readonly environmentInjector = inject(EnvironmentInjector);\n private readonly eventBus = inject(EventBus);\n private readonly logger = inject(DynamicFormLogger);\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Memoized Functions\n // ─────────────────────────────────────────────────────────────────────────────\n\n private readonly fieldProcessors = inject(CONTAINER_FIELD_PROCESSORS);\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Inputs\n // ─────────────────────────────────────────────────────────────────────────────\n\n field = input.required<GroupField>();\n key = input.required<string>();\n className = input<string>();\n hidden = input(false);\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Computed Signals\n // ─────────────────────────────────────────────────────────────────────────────\n\n readonly hostClasses = computed(() => computeContainerHostClasses('group', this.className()));\n\n private readonly rawFieldRegistry = computed(() => this.fieldRegistry.raw);\n\n private readonly formSetup = computed(() => {\n const groupField = this.field();\n const registry = this.rawFieldRegistry();\n\n if (groupField.fields && groupField.fields.length > 0) {\n const flattenedFields = this.fieldProcessors.memoizedFlattenFields(groupField.fields, registry);\n const flattenedFieldsForRendering = this.fieldProcessors.memoizedFlattenFieldsForRendering(groupField.fields, registry);\n const fieldsById = this.fieldProcessors.memoizedKeyBy(flattenedFields);\n const defaultValues = this.fieldProcessors.memoizedDefaultValues(fieldsById, registry);\n\n return {\n fields: flattenedFieldsForRendering,\n schemaFields: flattenedFields,\n originalFields: groupField.fields,\n defaultValues,\n registry,\n };\n }\n\n return {\n fields: [],\n schemaFields: [],\n originalFields: [],\n defaultValues: {},\n registry,\n };\n });\n\n readonly defaultValues = linkedSignal(() => this.formSetup().defaultValues);\n\n /**\n * Entity computed from parent value, group key, and defaults.\n * Uses deep equality check to prevent unnecessary updates when\n * object spread creates new references with identical values.\n */\n private readonly entity = linkedSignal(\n () => {\n const parentValue = this.parentFieldSignalContext.value();\n const groupKey = this.field().key;\n const defaults = this.defaultValues();\n const groupValue = (parentValue as Record<string, unknown>)?.[groupKey] || {};\n return { ...defaults, ...groupValue };\n },\n {\n debugName: 'GroupFieldComponent.entity',\n equal: isEqual,\n },\n );\n\n private readonly form = computed(() => {\n return runInInjectionContext(this.injector, () => {\n const setup = this.formSetup();\n\n if (setup.schemaFields.length > 0) {\n const schema = createSchemaFromFields(setup.schemaFields, setup.registry);\n return untracked(() => form(this.entity, schema));\n }\n\n return untracked(() => form(this.entity));\n });\n });\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Public State Signals\n // ─────────────────────────────────────────────────────────────────────────────\n\n readonly formValue = computed(() => this.entity());\n readonly valid = computed(() => this.form()().valid());\n readonly invalid = computed(() => this.form()().invalid());\n readonly dirty = computed(() => this.form()().dirty());\n readonly touched = computed(() => this.form()().touched());\n readonly errors = computed(() => this.form()().errors());\n readonly disabled = computed(() => this.form()().disabled());\n\n private readonly nestedFieldTree = computed((): FieldTree<Record<string, unknown>> | undefined => {\n const parentForm = this.parentFieldSignalContext.form as Record<string, FieldTree<Record<string, unknown>>>;\n const groupKey = this.field().key;\n return parentForm[groupKey];\n });\n\n private readonly groupFieldSignalContext: FieldSignalContext<Record<string, unknown>> = (() => {\n const nestedFieldTree = this.nestedFieldTree;\n return {\n injector: this.injector,\n value: this.parentFieldSignalContext.value,\n defaultValues: this.defaultValues,\n get form() {\n return nestedFieldTree() ?? ({} as FieldTree<Record<string, unknown>>);\n },\n };\n })();\n\n private readonly groupInjector = Injector.create({\n parent: this.injector,\n providers: [{ provide: FIELD_SIGNAL_CONTEXT, useValue: this.groupFieldSignalContext }],\n });\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Outputs\n // ─────────────────────────────────────────────────────────────────────────────\n\n readonly validityChange = outputFromObservable(toObservable(this.valid));\n readonly dirtyChange = outputFromObservable(toObservable(this.dirty));\n readonly submitted = outputFromObservable(this.eventBus.on<SubmitEvent>('submit'));\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Field Resolution\n // ─────────────────────────────────────────────────────────────────────────────\n\n private readonly fieldsSource = computed(() => this.formSetup().fields);\n\n protected readonly resolvedFields = derivedFromDeferred(\n this.fieldsSource,\n createFieldResolutionPipe(() => ({\n loadTypeComponent: (type: string) => this.fieldRegistry.loadTypeComponent(type),\n registry: this.rawFieldRegistry(),\n injector: this.groupInjector,\n destroyRef: this.destroyRef,\n onError: (fieldDef: FieldDef<unknown>, error: unknown) => {\n const fieldKey = fieldDef.key || '<no key>';\n this.logger.error(\n `Failed to load component for field type '${fieldDef.type}' (key: ${fieldKey}) ` +\n `within group '${this.field().key}'. Ensure the field type is registered in your field registry.`,\n error,\n );\n },\n })),\n { initialValue: [] as ResolvedField[], injector: this.injector },\n );\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Constructor\n // ─────────────────────────────────────────────────────────────────────────────\n\n constructor() {\n this.setupEffects();\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Private Methods\n // ─────────────────────────────────────────────────────────────────────────────\n\n private setupEffects(): void {\n setupContainerInitEffect(this.resolvedFields, this.eventBus, 'group', () => this.field().key, this.injector);\n\n explicitEffect(\n [this.nestedFieldTree, this.field],\n ([tree, field]) => {\n if (!tree) {\n this.logger.warn(\n `Group field \"${field.key}\" not found in parent form. ` + `Ensure the parent form schema includes this group field.`,\n );\n }\n },\n { defer: true },\n );\n }\n}\n\nexport { GroupFieldComponent };\n"],"names":[],"mappings":"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"}
@@ -4141,9 +4141,9 @@ class PageOrchestratorComponent {
4141
4141
  }
4142
4142
  }
4143
4143
  }
4144
- `, isInline: true, styles: [":host{display:block;position:relative;width:100%}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, deferBlockDependencies: [() => [import('./ng-forge-dynamic-forms-page-field.component-BHNVryIq.mjs').then(m => m.default)], () => [import('./ng-forge-dynamic-forms-page-field.component-BHNVryIq.mjs').then(m => m.default)]] });
4144
+ `, isInline: true, styles: [":host{display:block;position:relative;width:100%}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, deferBlockDependencies: [() => [import('./ng-forge-dynamic-forms-page-field.component-DqWAcwhG.mjs').then(m => m.default)], () => [import('./ng-forge-dynamic-forms-page-field.component-DqWAcwhG.mjs').then(m => m.default)]] });
4145
4145
  }
4146
- i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "21.2.8", ngImport: i0, type: PageOrchestratorComponent, resolveDeferredDeps: () => [import('./ng-forge-dynamic-forms-page-field.component-BHNVryIq.mjs').then(m => m.default)], resolveMetadata: PageFieldComponent => ({ decorators: [{
4146
+ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "21.2.8", ngImport: i0, type: PageOrchestratorComponent, resolveDeferredDeps: () => [import('./ng-forge-dynamic-forms-page-field.component-DqWAcwhG.mjs').then(m => m.default)], resolveMetadata: PageFieldComponent => ({ decorators: [{
4147
4147
  type: Component,
4148
4148
  args: [{ selector: 'div[page-orchestrator]', imports: [PageFieldComponent], template: `
4149
4149
  @for (pageField of pageFields(); track pageField.key; let i = $index) {
@@ -9241,18 +9241,22 @@ function resolveExclusionConfig(global, form, field) {
9241
9241
  };
9242
9242
  }
9243
9243
  /**
9244
- * Determines whether a field's value should be excluded based on its reactive state
9244
+ * Determines whether a field's value should be excluded based on its reactive state,
9245
+ * the field def's static state (for fields whose `state.hidden()` isn't wired — e.g. groups),
9245
9246
  * and the resolved exclusion config.
9246
9247
  */
9247
- function shouldExcludeField(fieldState, config) {
9248
+ function shouldExcludeField(field, fieldState, config) {
9248
9249
  const state = fieldState();
9249
- if (config.excludeValueIfHidden && state.hidden()) {
9250
+ const isHidden = state.hidden() || field.hidden === true;
9251
+ if (config.excludeValueIfHidden && isHidden) {
9250
9252
  return true;
9251
9253
  }
9252
- if (config.excludeValueIfDisabled && state.disabled()) {
9254
+ const isDisabled = state.disabled() || field.disabled === true;
9255
+ if (config.excludeValueIfDisabled && isDisabled) {
9253
9256
  return true;
9254
9257
  }
9255
- if (config.excludeValueIfReadonly && state.readonly()) {
9258
+ const isReadonly = state.readonly() || field.readonly === true;
9259
+ if (config.excludeValueIfReadonly && isReadonly) {
9256
9260
  return true;
9257
9261
  }
9258
9262
  return false;
@@ -9284,14 +9288,6 @@ function filterFormValue(rawValue, schemaFields, formTree, registry, globalDefau
9284
9288
  // If the key doesn't exist in the raw value, skip
9285
9289
  if (!(key in rawValue))
9286
9290
  continue;
9287
- // Try to access the field state from the form tree
9288
- const fieldState = formTree[key];
9289
- // If no field state is available (e.g., componentless hidden fields),
9290
- // include the value as-is since we can't determine reactive state
9291
- if (!fieldState || typeof fieldState !== 'function') {
9292
- result[key] = rawValue[key];
9293
- continue;
9294
- }
9295
9291
  // Resolve per-field exclusion config
9296
9292
  const fieldExclusion = {
9297
9293
  excludeValueIfHidden: field.excludeValueIfHidden,
@@ -9299,8 +9295,19 @@ function filterFormValue(rawValue, schemaFields, formTree, registry, globalDefau
9299
9295
  excludeValueIfReadonly: field.excludeValueIfReadonly,
9300
9296
  };
9301
9297
  const resolvedConfig = resolveExclusionConfig(globalDefaults, formOptions, fieldExclusion);
9298
+ // Componentless field (no FieldTree) — decide from the static field def alone, then include if not excluded.
9299
+ const fieldState = formTree[key];
9300
+ if (!fieldState || typeof fieldState !== 'function') {
9301
+ const staticallyExcluded = (resolvedConfig.excludeValueIfHidden && field.hidden === true) ||
9302
+ (resolvedConfig.excludeValueIfDisabled && field.disabled === true) ||
9303
+ (resolvedConfig.excludeValueIfReadonly && field.readonly === true);
9304
+ if (!staticallyExcluded) {
9305
+ result[key] = rawValue[key];
9306
+ }
9307
+ continue;
9308
+ }
9302
9309
  // Check if this field should be excluded based on its state
9303
- if (shouldExcludeField(fieldState, resolvedConfig)) {
9310
+ if (shouldExcludeField(field, fieldState, resolvedConfig)) {
9304
9311
  continue;
9305
9312
  }
9306
9313
  // Handle group fields: recurse into nested structure
@@ -9795,6 +9802,77 @@ const FORM_STATE_DEPS = new InjectionToken('FORM_STATE_DEPS');
9795
9802
  function asFieldTreeRecord(tree) {
9796
9803
  return tree;
9797
9804
  }
9805
+ /** All-false baseline for the outward two-way binding filter — see `boundFormValue`. */
9806
+ const BOUND_VALUE_EXCLUSION_BASELINE = {
9807
+ excludeValueIfHidden: false,
9808
+ excludeValueIfDisabled: false,
9809
+ excludeValueIfReadonly: false,
9810
+ };
9811
+ /** True when any of the three exclusion axes is asserted (i.e. the field could be filtered out of the bound model). */
9812
+ function isFieldExcluded(axes) {
9813
+ return !!axes && (axes.hidden || axes.disabled || axes.readonly);
9814
+ }
9815
+ /**
9816
+ * Recursively populates `out` with `dottedPath → exclusion axes` for every keyed field reachable
9817
+ * from `fields`, walking into groups so nested-leaf transitions can be detected. Arrays are
9818
+ * treated as leaves (whole-array filtering only — see value-filter v1 limitation).
9819
+ */
9820
+ function collectFieldStateSnapshot(fields, treeRecord, pathParts, out) {
9821
+ for (const field of fields) {
9822
+ const key = field.key;
9823
+ if (!key)
9824
+ continue;
9825
+ const subtree = treeRecord[key];
9826
+ if (!subtree || typeof subtree !== 'function')
9827
+ continue;
9828
+ const state = subtree();
9829
+ const path = [...pathParts, key];
9830
+ out[path.join('.')] = { hidden: state.hidden(), disabled: state.disabled(), readonly: state.readonly() };
9831
+ if (isGroupField(field) && field.fields) {
9832
+ collectFieldStateSnapshot(field.fields, asFieldTreeRecord(subtree), path, out);
9833
+ }
9834
+ }
9835
+ }
9836
+ /**
9837
+ * Reads a value from a nested object by dotted-path segments. Returns undefined
9838
+ * if any intermediate segment is missing or non-object.
9839
+ */
9840
+ function getValueAtPath(source, segments) {
9841
+ let current = source;
9842
+ for (const segment of segments) {
9843
+ if (current === null || typeof current !== 'object')
9844
+ return undefined;
9845
+ current = current[segment];
9846
+ }
9847
+ return current;
9848
+ }
9849
+ /**
9850
+ * Whether a value is worth capturing into the saved-hidden-value store. `NaN` (the number-input
9851
+ * default) is excluded — restoring it would re-leak the default into the bound model when the
9852
+ * field becomes visible again, defeating the bug fix.
9853
+ */
9854
+ function isRestoreRelevant(value) {
9855
+ return !(typeof value === 'number' && Number.isNaN(value));
9856
+ }
9857
+ /**
9858
+ * Returns a new object with `value` set at the path described by `segments`.
9859
+ * Intermediate objects are cloned shallowly to preserve immutability of `target`.
9860
+ */
9861
+ function setValueAtPath(target, segments, value) {
9862
+ if (segments.length === 0)
9863
+ return target;
9864
+ const [head, ...rest] = segments;
9865
+ const next = { ...target };
9866
+ if (rest.length === 0) {
9867
+ next[head] = value;
9868
+ }
9869
+ else {
9870
+ const child = target[head];
9871
+ const childObj = child !== null && typeof child === 'object' ? child : {};
9872
+ next[head] = setValueAtPath(childObj, rest, value);
9873
+ }
9874
+ return next;
9875
+ }
9798
9876
  /**
9799
9877
  * Central service that manages all form state and coordinates the form lifecycle.
9800
9878
  * Single source of truth for lifecycle state, field resolution, form signals, and events.
@@ -9966,6 +10044,29 @@ class FormStateManager {
9966
10044
  return undefined;
9967
10045
  return new Set(schemaFields.map((f) => f.key).filter((key) => key !== undefined));
9968
10046
  }, ...(ngDevMode ? [{ debugName: "validKeys" }] : /* istanbul ignore next */ []));
10047
+ /**
10048
+ * Per-field exclusion-axis state (hidden/disabled/readonly) keyed by dotted path. Drives the
10049
+ * save-on-exclude effect's transition detection. Walks recursively into groups so nested-leaf
10050
+ * transitions are captured. Arrays are treated as leaves (whole-array preservation only).
10051
+ */
10052
+ fieldStateSnapshot = computed(() => {
10053
+ const setup = this.formSetup();
10054
+ if (!setup.schemaFields || setup.schemaFields.length === 0)
10055
+ return {};
10056
+ const snapshot = {};
10057
+ collectFieldStateSnapshot(setup.schemaFields, asFieldTreeRecord(this.form()), [], snapshot);
10058
+ return snapshot;
10059
+ }, ...(ngDevMode ? [{ debugName: "fieldStateSnapshot" }] : /* istanbul ignore next */ []));
10060
+ /**
10061
+ * Captured values for fields actively excluded from the bound model — either via
10062
+ * `excludeValueIfHidden`, `excludeValueIfDisabled`, or `excludeValueIfReadonly`. Restored when
10063
+ * the field becomes re-included (visible/enabled/editable). The save effect only writes here
10064
+ * when the field is being filtered out by `boundFormValue` — fields without explicit opt-in
10065
+ * never enter the store.
10066
+ */
10067
+ excludedValueStore = signal({}, ...(ngDevMode ? [{ debugName: "excludedValueStore" }] : /* istanbul ignore next */ []));
10068
+ /** Tracks per-path exclusion state across save-effect runs to detect newly-excluded fields. */
10069
+ prevFieldStateSnapshot = signal({}, ...(ngDevMode ? [{ debugName: "prevFieldStateSnapshot" }] : /* istanbul ignore next */ []));
9969
10070
  // ─────────────────────────────────────────────────────────────────────────────
9970
10071
  // Computed Signals - Entity & Form
9971
10072
  // ─────────────────────────────────────────────────────────────────────────────
@@ -9989,10 +10090,13 @@ class FormStateManager {
9989
10090
  const inputValue = this.deps.value();
9990
10091
  const defaults = this.defaultValues();
9991
10092
  const keys = this.validKeys();
10093
+ const saved = this.excludedValueStore();
9992
10094
  // Deep-merge so a partial nested object in `inputValue` (e.g. a group
9993
10095
  // value missing one of its declared sub-field keys) does not orphan
9994
10096
  // the absent sub-field in the Signal Forms validation graph.
9995
- const combined = deepMergeDefaults(defaults, inputValue);
10097
+ // Layer order: defaults < saved (excluded-field restorations) < inputValue.
10098
+ const withSaved = deepMergeDefaults(defaults, saved);
10099
+ const combined = deepMergeDefaults(withSaved, inputValue);
9996
10100
  if (keys) {
9997
10101
  const filtered = {};
9998
10102
  for (const key of Object.keys(combined)) {
@@ -10102,6 +10206,35 @@ class FormStateManager {
10102
10206
  const fieldTreeRecord = asFieldTreeRecord(formTree);
10103
10207
  return filterFormValue(rawValue, setup.schemaFields, fieldTreeRecord, setup.registry, this.valueExclusionDefaults, formOptions);
10104
10208
  }, ...(ngDevMode ? [{ debugName: "filteredFormValue" }] : /* istanbul ignore next */ []));
10209
+ /**
10210
+ * Form value used for the outward two-way binding sync.
10211
+ *
10212
+ * Only honors *explicit* form-level and field-level `excludeValueIf*` settings — global
10213
+ * defaults (`VALUE_EXCLUSION_DEFAULTS`) are intentionally ignored here. Rationale:
10214
+ * - Original V1 behavior: the bound model carries all values regardless of visibility.
10215
+ * - Bug fix: when a user explicitly sets `excludeValueIfHidden: true` on a field/form,
10216
+ * they expect that value to disappear from the bound model when hidden (e.g. NaN for
10217
+ * number inputs, see issue #394).
10218
+ * - Without explicit opt-in, the bound model keeps the V1 contract.
10219
+ * `filteredFormValue` (above) still applies the full Field > Form > Global hierarchy
10220
+ * for the submission output.
10221
+ */
10222
+ boundFormValue = computed(() => {
10223
+ const rawValue = this.formValue();
10224
+ const setup = this.formSetup();
10225
+ const options = this.effectiveFormOptions();
10226
+ if (!setup.schemaFields || setup.schemaFields.length === 0) {
10227
+ return rawValue;
10228
+ }
10229
+ const formTree = this.form();
10230
+ const formOptions = {
10231
+ excludeValueIfHidden: options.excludeValueIfHidden,
10232
+ excludeValueIfDisabled: options.excludeValueIfDisabled,
10233
+ excludeValueIfReadonly: options.excludeValueIfReadonly,
10234
+ };
10235
+ const fieldTreeRecord = asFieldTreeRecord(formTree);
10236
+ return filterFormValue(rawValue, setup.schemaFields, fieldTreeRecord, setup.registry, BOUND_VALUE_EXCLUSION_BASELINE, formOptions);
10237
+ }, ...(ngDevMode ? [{ debugName: "boundFormValue" }] : /* istanbul ignore next */ []));
10105
10238
  /** Whether the form is currently valid. */
10106
10239
  valid = computed(() => this.formInstance().valid(), ...(ngDevMode ? [{ debugName: "valid" }] : /* istanbul ignore next */ []));
10107
10240
  /** Whether the form is currently invalid. */
@@ -10318,6 +10451,7 @@ class FormStateManager {
10318
10451
  * Resets the form to default values.
10319
10452
  */
10320
10453
  reset() {
10454
+ this.excludedValueStore.set({});
10321
10455
  const defaults = this.defaultValues();
10322
10456
  this.form()().value.set(defaults);
10323
10457
  this.deps.value.set(defaults);
@@ -10326,6 +10460,7 @@ class FormStateManager {
10326
10460
  * Clears the form to empty state.
10327
10461
  */
10328
10462
  clear() {
10463
+ this.excludedValueStore.set({});
10329
10464
  const emptyValue = {};
10330
10465
  this.form()().value.set(emptyValue);
10331
10466
  this.deps.value.set(emptyValue);
@@ -10350,12 +10485,49 @@ class FormStateManager {
10350
10485
  this.machine.dispatch({ type: Action.ConfigChange, config });
10351
10486
  }
10352
10487
  });
10353
- // Outward sync: write entity changes back to deps.value (see entity JSDoc for full explanation).
10354
- // The isEqual guard prevents infinite ping-pong between this effect and the linkedSignal source.
10355
- explicitEffect([this.entity], ([currentEntity]) => {
10488
+ // Save-on-exclude: capture entity values for fields that boundFormValue is actively
10489
+ // filtering out via any of the three axes (hidden / disabled / readonly), so they can be
10490
+ // restored when the field becomes re-included. The transition fires once per "no axis
10491
+ // asserted → at least one axis asserted" edge; subsequent axis changes while still excluded
10492
+ // are no-ops. Comparing entity vs bound at the path limits the store to fields that are
10493
+ // actually being filtered — fields without explicit opt-in never enter the store and never
10494
+ // participate in the entity merge. `NaN` values are skipped: they're the number-input default
10495
+ // and would re-leak via the merge once the field becomes re-included.
10496
+ explicitEffect([this.fieldStateSnapshot], ([snapshot]) => {
10497
+ const currentSaved = this.excludedValueStore();
10498
+ const currentEntity = this.entity();
10499
+ const boundValue = this.boundFormValue();
10500
+ const prev = this.prevFieldStateSnapshot();
10501
+ let newSaved = currentSaved;
10502
+ for (const [path, axes] of Object.entries(snapshot)) {
10503
+ if (isFieldExcluded(axes) && !isFieldExcluded(prev[path])) {
10504
+ const segments = path.split('.');
10505
+ const inEntity = getValueAtPath(currentEntity, segments);
10506
+ const inBound = getValueAtPath(boundValue, segments);
10507
+ if (inEntity !== undefined && inBound === undefined && isRestoreRelevant(inEntity)) {
10508
+ newSaved = setValueAtPath(newSaved, segments, inEntity);
10509
+ }
10510
+ }
10511
+ }
10512
+ this.prevFieldStateSnapshot.set({ ...snapshot });
10513
+ if (newSaved !== currentSaved && !isEqual(newSaved, currentSaved)) {
10514
+ this.excludedValueStore.set(newSaved);
10515
+ }
10516
+ });
10517
+ // Schema change resets the saved store + transition tracker so values from a stale schema
10518
+ // can't leak into the new one.
10519
+ explicitEffect([this.formSetup], () => {
10520
+ this.prevFieldStateSnapshot.set({});
10521
+ if (Object.keys(this.excludedValueStore()).length > 0) {
10522
+ this.excludedValueStore.set({});
10523
+ }
10524
+ });
10525
+ // Outward sync uses boundFormValue (honors only explicit excludeValueIf* opt-ins) so
10526
+ // global defaults that target submission output don't reshape the host's bound model.
10527
+ explicitEffect([this.boundFormValue], ([currentBound]) => {
10356
10528
  const currentValue = this.deps.value();
10357
- if (!isEqual(currentEntity, currentValue)) {
10358
- this.deps.value.set(currentEntity);
10529
+ if (!isEqual(currentBound, currentValue)) {
10530
+ this.deps.value.set(currentBound);
10359
10531
  }
10360
10532
  });
10361
10533
  explicitEffect([this.formConfigValidation], ([validation]) => {
@@ -15092,31 +15264,31 @@ const BUILT_IN_FIELDS = [
15092
15264
  // `row` is a virtual field type: it maps to ContainerFieldComponent, and
15093
15265
  // the rowFieldMapper injects a `{ type: 'row' }` wrapper so the container
15094
15266
  // renders the flex/grid layout via RowWrapperComponent.
15095
- loadComponent: () => import('./ng-forge-dynamic-forms-container-field.component-D4Fpr2ri.mjs'),
15267
+ loadComponent: () => import('./ng-forge-dynamic-forms-container-field.component-BCIQ6_Mm.mjs'),
15096
15268
  mapper: rowFieldMapper,
15097
15269
  valueHandling: 'flatten',
15098
15270
  },
15099
15271
  {
15100
15272
  name: 'group',
15101
- loadComponent: () => import('./ng-forge-dynamic-forms-group-field.component-BxswrhOc.mjs'),
15273
+ loadComponent: () => import('./ng-forge-dynamic-forms-group-field.component-DKcoco0G.mjs'),
15102
15274
  mapper: groupFieldMapper,
15103
15275
  valueHandling: 'include',
15104
15276
  },
15105
15277
  {
15106
15278
  name: 'array',
15107
- loadComponent: () => import('./ng-forge-dynamic-forms-array-field.component-CltYGHg9.mjs'),
15279
+ loadComponent: () => import('./ng-forge-dynamic-forms-array-field.component-us7mQtVQ.mjs'),
15108
15280
  mapper: arrayFieldMapper,
15109
15281
  valueHandling: 'include',
15110
15282
  },
15111
15283
  {
15112
15284
  name: 'page',
15113
- loadComponent: () => import('./ng-forge-dynamic-forms-page-field.component-BHNVryIq.mjs'),
15285
+ loadComponent: () => import('./ng-forge-dynamic-forms-page-field.component-DqWAcwhG.mjs'),
15114
15286
  mapper: pageFieldMapper,
15115
15287
  valueHandling: 'flatten',
15116
15288
  },
15117
15289
  {
15118
15290
  name: 'text',
15119
- loadComponent: () => import('./ng-forge-dynamic-forms-text-field.component-Cf1mEKVW.mjs'),
15291
+ loadComponent: () => import('./ng-forge-dynamic-forms-text-field.component-8C1-oyU_.mjs'),
15120
15292
  mapper: textFieldMapper,
15121
15293
  valueHandling: 'exclude',
15122
15294
  ...DISPLAY_FIELD_TYPES_BASE,
@@ -15128,7 +15300,7 @@ const BUILT_IN_FIELDS = [
15128
15300
  },
15129
15301
  {
15130
15302
  name: 'container',
15131
- loadComponent: () => import('./ng-forge-dynamic-forms-container-field.component-D4Fpr2ri.mjs'),
15303
+ loadComponent: () => import('./ng-forge-dynamic-forms-container-field.component-BCIQ6_Mm.mjs'),
15132
15304
  mapper: containerFieldMapper,
15133
15305
  valueHandling: 'flatten',
15134
15306
  },
@@ -15136,7 +15308,7 @@ const BUILT_IN_FIELDS = [
15136
15308
  const BUILT_IN_WRAPPERS = [
15137
15309
  {
15138
15310
  wrapperName: 'css',
15139
- loadComponent: () => import('./ng-forge-dynamic-forms-css-wrapper.component-mdfySFjX.mjs'),
15311
+ loadComponent: () => import('./ng-forge-dynamic-forms-css-wrapper.component-Dhlf6UxN.mjs'),
15140
15312
  },
15141
15313
  {
15142
15314
  wrapperName: 'row',
@@ -16211,4 +16383,4 @@ function extractErrorParams(error) {
16211
16383
  */
16212
16384
 
16213
16385
  export { SubmitEvent as $, ARRAY_CONTEXT as A, BUILT_IN_FIELDS as B, CONTAINER_FIELD_PROCESSORS as C, DynamicFormLogger as D, EventBus as E, FIELD_SIGNAL_CONTEXT as F, DEFAULT_VALIDATION_MESSAGES as G, DynamicForm as H, DynamicFormError as I, EventDispatcher as J, FIELD_REGISTRY as K, FORM_OPTIONS as L, FormClearEvent as M, FormResetEvent as N, INITIALIZATION_TIMEOUT_MS as O, InsertArrayItemEvent as P, MoveArrayItemEvent as Q, RootFormRegistryService as R, NextPageEvent as S, NoopLogger as T, PageChangeEvent as U, PopArrayItemEvent as V, WRAPPER_AUTO_ASSOCIATIONS as W, PrependArrayItemEvent as X, PreviousPageEvent as Y, RemoveAtIndexEvent as Z, ShiftArrayItemEvent as _, DEFAULT_WRAPPERS as a, WRAPPER_REGISTRY as a0, applyMetaToElement as a1, applyValidator as a2, applyValidators as a3, arrayEvent as a4, arrayFieldMapper as a5, baseFieldMapper as a6, buildBaseInputs as a7, containerFieldMapper as a8, createField as a9, resolveNextButtonDisabled as aA, resolveNonFieldDisabled as aB, resolveNonFieldHidden as aC, resolveSubmitButtonDisabled as aD, resolveTokens as aE, rowFieldMapper as aF, textFieldMapper as aG, toReadonlyFieldTree as aH, withEventFormValue as aI, withLoggerConfig as aJ, withPreviousValue as aK, withValidationExecutionDefaults as aL, withValueExclusionDefaults as aM, wrapperProps as aN, createWrappers as aa, evaluateNonFieldDisabled as ab, evaluateNonFieldHidden as ac, field as ad, formConfig as ae, getArrayLength as af, groupFieldMapper as ag, hasFormValue as ah, interpolateParams as ai, isArrayField as aj, isCheckedField as ak, isContainerField as al, isContainerTypedField as am, isDisplayOnlyField as an, isFormStateCondition as ao, isLeafField as ap, isPageField as aq, isRowField as ar, isSimplifiedArrayField as as, isValueBearingField as at, isValueField as au, isWrapperTypeDefinition as av, isWrappersBundle as aw, omit as ax, pageFieldMapper as ay, provideDynamicForm as az, isSameWrapperChain as b, createFieldResolutionPipe as c, derivedFromDeferred as d, createWrapperChainController as e, DfFieldOutlet as f, isEqual as g, createSchemaFromFields as h, injectFieldRegistry as i, createRenderReadySignal as j, ARRAY_TEMPLATE_REGISTRY as k, ARRAY_ITEM_ID_GENERATOR as l, mapFieldToInputs as m, getNormalizedArrayMetadata as n, getFieldValueHandling as o, getFieldDefaultValue as p, isGroupField as q, resolveWrappers as r, createArrayItemIdGenerator as s, ComponentInitializedEvent as t, DynamicTextPipe as u, validatePageNesting as v, dynamicTextToObservable as w, AppendArrayItemEvent as x, ConsoleLogger as y, DEFAULT_PROPS as z };
16214
- //# sourceMappingURL=ng-forge-dynamic-forms-ng-forge-dynamic-forms-QdV2vcCx.mjs.map
16386
+ //# sourceMappingURL=ng-forge-dynamic-forms-ng-forge-dynamic-forms-CfbmSRM_.mjs.map