@ng-forge/dynamic-forms 1.2.0-next.5 → 1.2.0-next.7

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 (39) hide show
  1. package/fesm2022/{ng-forge-dynamic-forms-array-field.component-D-VWBM-t.mjs → ng-forge-dynamic-forms-array-field.component-DK7dAQv7.mjs} +6 -10
  2. package/fesm2022/ng-forge-dynamic-forms-array-field.component-DK7dAQv7.mjs.map +1 -0
  3. package/fesm2022/{ng-forge-dynamic-forms-bootstrap-derivation-orchestrator-OBDy6qd9.mjs → ng-forge-dynamic-forms-bootstrap-derivation-orchestrator-BfxYqAQA.mjs} +29 -7
  4. package/fesm2022/ng-forge-dynamic-forms-bootstrap-derivation-orchestrator-BfxYqAQA.mjs.map +1 -0
  5. package/fesm2022/{ng-forge-dynamic-forms-container-field.component-BpeFyhAt.mjs → ng-forge-dynamic-forms-container-field.component-Cj2msZp_.mjs} +9 -12
  6. package/fesm2022/ng-forge-dynamic-forms-container-field.component-Cj2msZp_.mjs.map +1 -0
  7. package/fesm2022/ng-forge-dynamic-forms-debounce-C9F4v1Ke.mjs +17 -0
  8. package/fesm2022/ng-forge-dynamic-forms-debounce-C9F4v1Ke.mjs.map +1 -0
  9. package/fesm2022/ng-forge-dynamic-forms-field-errors-wrapper.component-ZdaC4Bit.mjs +25 -0
  10. package/fesm2022/ng-forge-dynamic-forms-field-errors-wrapper.component-ZdaC4Bit.mjs.map +1 -0
  11. package/fesm2022/ng-forge-dynamic-forms-form-schema.service-C3cVSmft.mjs +24 -0
  12. package/fesm2022/ng-forge-dynamic-forms-form-schema.service-C3cVSmft.mjs.map +1 -0
  13. package/fesm2022/{ng-forge-dynamic-forms-group-field.component-BNjYMTqT.mjs → ng-forge-dynamic-forms-group-field.component-DN6X506r.mjs} +6 -10
  14. package/fesm2022/ng-forge-dynamic-forms-group-field.component-DN6X506r.mjs.map +1 -0
  15. package/fesm2022/ng-forge-dynamic-forms-integration.mjs +10 -72
  16. package/fesm2022/ng-forge-dynamic-forms-integration.mjs.map +1 -1
  17. package/fesm2022/ng-forge-dynamic-forms-internal.mjs +252 -95
  18. package/fesm2022/ng-forge-dynamic-forms-internal.mjs.map +1 -1
  19. package/fesm2022/{ng-forge-dynamic-forms-ng-forge-dynamic-forms-DSXZJHcu.mjs → ng-forge-dynamic-forms-ng-forge-dynamic-forms-DCX7tvaB.mjs} +1089 -1288
  20. package/fesm2022/ng-forge-dynamic-forms-ng-forge-dynamic-forms-DCX7tvaB.mjs.map +1 -0
  21. package/fesm2022/{ng-forge-dynamic-forms-page-field.component-B92kLZkH.mjs → ng-forge-dynamic-forms-page-field.component-D16ey8r-.mjs} +54 -13
  22. package/fesm2022/ng-forge-dynamic-forms-page-field.component-D16ey8r-.mjs.map +1 -0
  23. package/fesm2022/ng-forge-dynamic-forms-schema-builder-DO-su9sF.mjs +570 -0
  24. package/fesm2022/ng-forge-dynamic-forms-schema-builder-DO-su9sF.mjs.map +1 -0
  25. package/fesm2022/ng-forge-dynamic-forms.mjs +2 -2
  26. package/package.json +2 -2
  27. package/types/ng-forge-dynamic-forms-integration.d.ts +7 -31
  28. package/types/ng-forge-dynamic-forms-internal.d.ts +429 -222
  29. package/types/ng-forge-dynamic-forms.d.ts +33 -17
  30. package/fesm2022/ng-forge-dynamic-forms-array-field.component-D-VWBM-t.mjs.map +0 -1
  31. package/fesm2022/ng-forge-dynamic-forms-bootstrap-derivation-orchestrator-OBDy6qd9.mjs.map +0 -1
  32. package/fesm2022/ng-forge-dynamic-forms-container-field.component-BpeFyhAt.mjs.map +0 -1
  33. package/fesm2022/ng-forge-dynamic-forms-container-utils-BZFz6ztF.mjs +0 -24
  34. package/fesm2022/ng-forge-dynamic-forms-container-utils-BZFz6ztF.mjs.map +0 -1
  35. package/fesm2022/ng-forge-dynamic-forms-emit-initialization-DhHwU6FJ.mjs +0 -17
  36. package/fesm2022/ng-forge-dynamic-forms-emit-initialization-DhHwU6FJ.mjs.map +0 -1
  37. package/fesm2022/ng-forge-dynamic-forms-group-field.component-BNjYMTqT.mjs.map +0 -1
  38. package/fesm2022/ng-forge-dynamic-forms-ng-forge-dynamic-forms-DSXZJHcu.mjs.map +0 -1
  39. package/fesm2022/ng-forge-dynamic-forms-page-field.component-B92kLZkH.mjs.map +0 -1
@@ -1,12 +1,12 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, computed, isSignal, inject, Injector, input, signal, ChangeDetectionStrategy, Component, untracked, Injectable, linkedSignal, resourceFromSnapshots, Pipe } from '@angular/core';
2
+ import { InjectionToken, computed, isSignal, inject, Injector, input, signal, ChangeDetectionStrategy, Component, untracked, Injectable, linkedSignal, resourceFromSnapshots, Pipe, viewChild, ViewContainerRef, Directive, forwardRef } from '@angular/core';
3
3
  import { NgComponentOutlet } from '@angular/common';
4
4
  import { explicitEffect } from 'ngxtension/explicit-effect';
5
5
  import { toSignal, toObservable, rxResource } from '@angular/core/rxjs-interop';
6
6
  import { isObservable, defer, combineLatest, pipe, debounceTime, distinctUntilChanged, map, tap, catchError, of, from, startWith, Subject, filter, TimeoutError, throwError } from 'rxjs';
7
7
  import { HttpClient } from '@angular/common/http';
8
- import { email, min, max, minLength, maxLength, pattern, required, validate, validateAsync, validateHttp } from '@angular/forms/signals';
9
- import { scan, map as map$1, filter as filter$1, take, switchMap, timeout, catchError as catchError$1, shareReplay } from 'rxjs/operators';
8
+ import { switchMap, map as map$1, scan, filter as filter$1, take, timeout, catchError as catchError$1, shareReplay } from 'rxjs/operators';
9
+ import { email, min, max, minLength, maxLength, pattern, required, validateTree, validate, validateAsync, validateHttp } from '@angular/forms/signals';
10
10
 
11
11
  const ADDON_TYPE_DEFINITIONS = new InjectionToken('ADDON_TYPE_DEFINITIONS');
12
12
 
@@ -1576,10 +1576,14 @@ function safeReadPathKeys(fieldContext) {
1576
1576
  }
1577
1577
 
1578
1578
  function createFieldValueProxy(getRootForm, getRootFormValue) {
1579
- const readField = (key) => {
1579
+ const resolveAccessor = (key) => {
1580
1580
  const root = getRootForm();
1581
1581
  const accessor = root?.[key];
1582
- if (typeof accessor === 'function') {
1582
+ return typeof accessor === 'function' ? accessor : undefined;
1583
+ };
1584
+ const readField = (key) => {
1585
+ const accessor = resolveAccessor(key);
1586
+ if (accessor) {
1583
1587
  const state = untracked(() => accessor());
1584
1588
  const valueSig = state && state.value;
1585
1589
  if (typeof valueSig === 'function') {
@@ -1598,8 +1602,7 @@ function createFieldValueProxy(getRootForm, getRootFormValue) {
1598
1602
  has(_target, prop) {
1599
1603
  if (typeof prop === 'symbol')
1600
1604
  return false;
1601
- const root = getRootForm();
1602
- if (root && prop in root)
1605
+ if (resolveAccessor(prop))
1603
1606
  return true;
1604
1607
  return prop in getRootFormValue();
1605
1608
  },
@@ -2662,6 +2665,187 @@ function injectNonFieldEvaluationContext(fieldDef, options = {}) {
2662
2665
  };
2663
2666
  }
2664
2667
 
2668
+ function dynamicTextToObservable(value, injector) {
2669
+ if (value === undefined) {
2670
+ return of('');
2671
+ }
2672
+ if (isObservable(value)) {
2673
+ return value;
2674
+ }
2675
+ if (isSignal(value)) {
2676
+ return untracked(() => toObservable(value, { injector }));
2677
+ }
2678
+ return of(String(value));
2679
+ }
2680
+
2681
+ const PLACEHOLDER_PATTERN = /\{\{([^{}]*)\}\}/g;
2682
+ function interpolateParams(message, error) {
2683
+ const params = extractErrorParams(error);
2684
+ return message.replace(PLACEHOLDER_PATTERN, (placeholder, rawKey) => {
2685
+ const key = rawKey.trim();
2686
+ return Object.hasOwn(params, key) ? safeToString(params[key]) : placeholder;
2687
+ });
2688
+ }
2689
+ function safeToString(value) {
2690
+ if (value === null || value === undefined) {
2691
+ return '';
2692
+ }
2693
+ if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
2694
+ return String(value);
2695
+ }
2696
+ if (value instanceof RegExp) {
2697
+ return value.toString();
2698
+ }
2699
+ if (value instanceof Date) {
2700
+ return value.toISOString();
2701
+ }
2702
+ if (Array.isArray(value)) {
2703
+ return value.join(', ');
2704
+ }
2705
+ try {
2706
+ if (typeof value === 'object' && value.toString !== Object.prototype.toString) {
2707
+ return value.toString();
2708
+ }
2709
+ return JSON.stringify(value);
2710
+ }
2711
+ catch {
2712
+ return '[object]';
2713
+ }
2714
+ }
2715
+ function extractErrorParams(error) {
2716
+ const params = {};
2717
+ if ('min' in error)
2718
+ params.min = error.min;
2719
+ if ('max' in error)
2720
+ params.max = error.max;
2721
+ if ('pattern' in error)
2722
+ params.pattern = error.pattern;
2723
+ if ('actual' in error)
2724
+ params.actual = error.actual;
2725
+ if ('expected' in error)
2726
+ params.expected = error.expected;
2727
+ if ('requiredLength' in error) {
2728
+ params.requiredLength = error.requiredLength;
2729
+ }
2730
+ else if ('minLength' in error) {
2731
+ params.requiredLength = error.minLength;
2732
+ params.minLength = error.minLength;
2733
+ }
2734
+ else if ('maxLength' in error) {
2735
+ params.requiredLength = error.maxLength;
2736
+ params.maxLength = error.maxLength;
2737
+ }
2738
+ if ('actualLength' in error)
2739
+ params.actualLength = error.actualLength;
2740
+ Object.keys(error).forEach((key) => {
2741
+ if (key !== 'kind' && !(key in params)) {
2742
+ params[key] = error[key];
2743
+ }
2744
+ });
2745
+ return params;
2746
+ }
2747
+
2748
+ function createResolvedErrorsSignal(field, validationMessages, defaultValidationMessages = signal(undefined), injector = inject(Injector)) {
2749
+ const logger = injector.get(DynamicFormLogger);
2750
+ const messages = computed(() => validationMessages() ?? {}, /* @ts-ignore */
2751
+ ...(ngDevMode ? [{ debugName: "messages" }] : /* istanbul ignore next */ []));
2752
+ const defaultMessages = computed(() => defaultValidationMessages() ?? {}, /* @ts-ignore */
2753
+ ...(ngDevMode ? [{ debugName: "defaultMessages" }] : /* istanbul ignore next */ []));
2754
+ const errors = computed(() => field()?.().errors() ?? [], /* @ts-ignore */
2755
+ ...(ngDevMode ? [{ debugName: "errors" }] : /* istanbul ignore next */ []));
2756
+ const errors$ = toObservable(errors, { injector });
2757
+ const messages$ = toObservable(messages, { injector });
2758
+ const defaultMessages$ = toObservable(defaultMessages, { injector });
2759
+ const resolvedErrors$ = combineLatest([errors$, messages$, defaultMessages$]).pipe(switchMap(([currentErrors, msgs, defaultMsgs]) => {
2760
+ if (!currentErrors || currentErrors.length === 0) {
2761
+ return of([]);
2762
+ }
2763
+ const errorResolvers = currentErrors.map((error) => resolveErrorMessage(error, msgs, defaultMsgs, injector, logger));
2764
+ return errorResolvers.length > 0
2765
+ ? combineLatest(errorResolvers).pipe(map$1((errors) => errors.filter((e) => e !== null)))
2766
+ : of([]);
2767
+ }));
2768
+ return toSignal(resolvedErrors$, { initialValue: [], injector });
2769
+ }
2770
+ function isMessageResolver(message) {
2771
+ return typeof message === 'function' && !isSignal(message);
2772
+ }
2773
+ function resolveMessageFunction(resolver, error, logger) {
2774
+ try {
2775
+ return resolver(error) ?? error.message ?? '';
2776
+ }
2777
+ catch (err) {
2778
+ logger.error(`Validation message resolver for error kind "${error.kind}" threw; falling back to error.message.`, err);
2779
+ return error.message ?? '';
2780
+ }
2781
+ }
2782
+ function resolveErrorMessage(error, fieldMessages, defaultMessages, injector, logger) {
2783
+ const fieldMessage = fieldMessages[error.kind];
2784
+ const defaultMessage = defaultMessages[error.kind];
2785
+ const messageToUse = fieldMessage ?? defaultMessage ?? error.message;
2786
+ if (!messageToUse) {
2787
+ logger.warn(`No validation message found for error kind "${error.kind}". ` +
2788
+ `Please provide a message via field-level validationMessages or form-level defaultValidationMessages.`);
2789
+ return of(null);
2790
+ }
2791
+ const isSchemaMessage = fieldMessage === undefined && defaultMessage === undefined;
2792
+ const messageText = isMessageResolver(messageToUse) ? resolveMessageFunction(messageToUse, error, logger) : messageToUse;
2793
+ const messageObservable = isSchemaMessage
2794
+ ? of(messageToUse) : dynamicTextToObservable(messageText, injector);
2795
+ return messageObservable.pipe(map$1((msg) => ({
2796
+ kind: error.kind,
2797
+ message: interpolateParams(msg, error),
2798
+ })));
2799
+ }
2800
+
2801
+ function shouldShowErrors(field) {
2802
+ return computed(() => {
2803
+ const control = field()?.();
2804
+ if (!control)
2805
+ return false;
2806
+ return control.invalid() && control.touched() && control.errors().length > 0;
2807
+ });
2808
+ }
2809
+
2810
+ const FIELD_ERROR_DISPLAY = new InjectionToken('FIELD_ERROR_DISPLAY');
2811
+ function injectFieldErrors(options) {
2812
+ const injector = options.injector ?? inject(Injector);
2813
+ const defaultValidationMessages = inject(DEFAULT_VALIDATION_MESSAGES, { optional: true });
2814
+ const fieldSignalContext = inject(FIELD_SIGNAL_CONTEXT, { optional: true });
2815
+ const fieldState = computed(() => {
2816
+ const inputs = options.fieldInputs();
2817
+ if (!inputs)
2818
+ return undefined;
2819
+ if (inputs.field)
2820
+ return inputs.field;
2821
+ const parentTree = fieldSignalContext?.form;
2822
+ const node = inputs.key ? parentTree?.[inputs.key] : undefined;
2823
+ return node ? node() : undefined;
2824
+ }, /* @ts-ignore */
2825
+ ...(ngDevMode ? [{ debugName: "fieldState" }] : /* istanbul ignore next */ []));
2826
+ const fieldTree = computed(() => {
2827
+ const state = fieldState();
2828
+ return state ? (() => state) : undefined;
2829
+ }, /* @ts-ignore */
2830
+ ...(ngDevMode ? [{ debugName: "fieldTree" }] : /* istanbul ignore next */ []));
2831
+ const messages = computed(() => options.validationMessages?.() ?? options.fieldInputs()?.validationMessages, /* @ts-ignore */
2832
+ ...(ngDevMode ? [{ debugName: "messages" }] : /* istanbul ignore next */ []));
2833
+ const errors = createResolvedErrorsSignal(fieldTree, messages, computed(() => defaultValidationMessages?.()), injector);
2834
+ const showErrors = shouldShowErrors(fieldTree);
2835
+ return {
2836
+ errors,
2837
+ showErrors,
2838
+ errorsToDisplay: computed(() => (showErrors() ? errors() : [])),
2839
+ errorId: computed(() => `${options.fieldInputs()?.key ?? ''}-error`),
2840
+ };
2841
+ }
2842
+
2843
+ function rowError(ctx, index, key, error) {
2844
+ const rows = ctx.fieldTree;
2845
+ const fieldTree = rows?.[index]?.[key];
2846
+ return fieldTree ? { ...error, fieldTree } : error;
2847
+ }
2848
+
2665
2849
  function isFunctionHttpValidator(config) {
2666
2850
  const c = config;
2667
2851
  return typeof c.functionName === 'string' || (c.fn !== null && typeof c.fn === 'object');
@@ -2773,7 +2957,8 @@ function applyPatternValidator(path, value, expression, when) {
2773
2957
  function createConditionalLogic(when) {
2774
2958
  return when ? createLogicFunction(when) : undefined;
2775
2959
  }
2776
- function applyValidator(config, fieldPath) {
2960
+ function applyValidator(config,
2961
+ fieldPath, attachment = 'field') {
2777
2962
  const path = fieldPath;
2778
2963
  switch (config.type) {
2779
2964
  case 'required':
@@ -2820,7 +3005,7 @@ function applyValidator(config, fieldPath) {
2820
3005
  }
2821
3006
  break;
2822
3007
  case 'custom':
2823
- applyCustomValidator(config, path);
3008
+ applyCustomValidator(config, path, attachment);
2824
3009
  break;
2825
3010
  case 'async':
2826
3011
  applyAsyncValidator(config, path);
@@ -2830,7 +3015,7 @@ function applyValidator(config, fieldPath) {
2830
3015
  break;
2831
3016
  }
2832
3017
  }
2833
- function applyCustomValidator(config, fieldPath) {
3018
+ function applyCustomValidator(config, fieldPath, attachment = 'field') {
2834
3019
  let validatorFn;
2835
3020
  if (config.expression) {
2836
3021
  validatorFn = createExpressionValidator(config);
@@ -2842,11 +3027,16 @@ function applyCustomValidator(config, fieldPath) {
2842
3027
  throw new DynamicFormError('Custom validator requires one of "expression", "functionName", or "fn".');
2843
3028
  }
2844
3029
  const whenLogic = createConditionalLogic(config.when);
2845
- validate(fieldPath, (ctx) => {
3030
+ const run = (ctx) => {
2846
3031
  if (whenLogic && !whenLogic(ctx))
2847
3032
  return null;
2848
3033
  return validatorFn(ctx);
2849
- });
3034
+ };
3035
+ if (attachment === 'tree') {
3036
+ validateTree(fieldPath, run);
3037
+ return;
3038
+ }
3039
+ validate(fieldPath, run);
2850
3040
  }
2851
3041
  function createFunctionValidator(config) {
2852
3042
  const logger = inject(DynamicFormLogger);
@@ -2998,8 +3188,9 @@ function applyDeclarativeHttpValidator(config, fieldPath) {
2998
3188
  },
2999
3189
  });
3000
3190
  }
3001
- function applyValidators(configs, fieldPath) {
3002
- configs.forEach((config) => applyValidator(config, fieldPath));
3191
+ function applyValidators(configs,
3192
+ fieldPath, attachment = 'field') {
3193
+ configs.forEach((config) => applyValidator(config, fieldPath, attachment));
3003
3194
  }
3004
3195
 
3005
3196
  function isCheckedField(field) {
@@ -3485,19 +3676,6 @@ function isDisplayOnlyField(field) {
3485
3676
  }
3486
3677
 
3487
3678
 
3488
- function dynamicTextToObservable(value, injector) {
3489
- if (value === undefined) {
3490
- return of('');
3491
- }
3492
- if (isObservable(value)) {
3493
- return value;
3494
- }
3495
- if (isSignal(value)) {
3496
- return untracked(() => toObservable(value, { injector }));
3497
- }
3498
- return of(String(value));
3499
- }
3500
-
3501
3679
  class DynamicTextPipe {
3502
3680
  injector = inject(Injector);
3503
3681
  transform(value) {
@@ -3559,74 +3737,15 @@ function setupInitializationTracking(options) {
3559
3737
  }), shareReplay({ bufferSize: 1, refCount: false }));
3560
3738
  }
3561
3739
 
3562
- const PLACEHOLDER_PATTERN = /\{\{([^{}]*)\}\}/g;
3563
- function interpolateParams(message, error) {
3564
- const params = extractErrorParams(error);
3565
- return message.replace(PLACEHOLDER_PATTERN, (placeholder, rawKey) => {
3566
- const key = rawKey.trim();
3567
- return Object.hasOwn(params, key) ? safeToString(params[key]) : placeholder;
3568
- });
3569
- }
3570
- function safeToString(value) {
3571
- if (value === null || value === undefined) {
3572
- return '';
3573
- }
3574
- if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
3575
- return String(value);
3576
- }
3577
- if (value instanceof RegExp) {
3578
- return value.toString();
3579
- }
3580
- if (value instanceof Date) {
3581
- return value.toISOString();
3582
- }
3583
- if (Array.isArray(value)) {
3584
- return value.join(', ');
3585
- }
3586
- try {
3587
- if (typeof value === 'object' && value.toString !== Object.prototype.toString) {
3588
- return value.toString();
3589
- }
3590
- return JSON.stringify(value);
3591
- }
3592
- catch {
3593
- return '[object]';
3594
- }
3595
- }
3596
- function extractErrorParams(error) {
3597
- const params = {};
3598
- if ('min' in error)
3599
- params.min = error.min;
3600
- if ('max' in error)
3601
- params.max = error.max;
3602
- if ('pattern' in error)
3603
- params.pattern = error.pattern;
3604
- if ('actual' in error)
3605
- params.actual = error.actual;
3606
- if ('expected' in error)
3607
- params.expected = error.expected;
3608
- if ('requiredLength' in error) {
3609
- params.requiredLength = error.requiredLength;
3610
- }
3611
- else if ('minLength' in error) {
3612
- params.requiredLength = error.minLength;
3613
- params.minLength = error.minLength;
3614
- }
3615
- else if ('maxLength' in error) {
3616
- params.requiredLength = error.maxLength;
3617
- params.maxLength = error.maxLength;
3618
- }
3619
- if ('actualLength' in error)
3620
- params.actualLength = error.actualLength;
3621
- Object.keys(error).forEach((key) => {
3622
- if (key !== 'kind' && !(key in params)) {
3623
- params[key] = error[key];
3624
- }
3625
- });
3626
- return params;
3627
- }
3628
-
3629
3740
  function isEqual(a, b) {
3741
+ if (a === b)
3742
+ return true;
3743
+ if (typeof a === 'number' && typeof b === 'number')
3744
+ return Object.is(a, b);
3745
+ if (a == null || b == null)
3746
+ return false;
3747
+ if (typeof a !== 'object' || typeof b !== 'object')
3748
+ return Object.is(a, b);
3630
3749
  return isEqualInternal(a, b, new WeakMap(), new WeakMap());
3631
3750
  }
3632
3751
  function isEqualInternal(a, b, seenA, seenB) {
@@ -3788,6 +3907,22 @@ function memoize(fn, resolverOrOptions) {
3788
3907
  function normalizeFieldsArray(fields) {
3789
3908
  return Array.isArray(fields) ? [...fields] : Object.values(fields);
3790
3909
  }
3910
+ function getChangedKeysWithin(previous, current, keys) {
3911
+ const changed = new Set();
3912
+ if (keys.size === 0)
3913
+ return changed;
3914
+ const before = previous ?? {};
3915
+ const after = current ?? {};
3916
+ for (const key of keys) {
3917
+ const inBefore = key in before;
3918
+ const inAfter = key in after;
3919
+ if (!inBefore && !inAfter)
3920
+ continue;
3921
+ if (inBefore !== inAfter || !isEqual(before[key], after[key]))
3922
+ changed.add(key);
3923
+ }
3924
+ return changed;
3925
+ }
3791
3926
  function getChangedKeys(previous, current) {
3792
3927
  const changedKeys = new Set();
3793
3928
  if (!previous && !current)
@@ -3820,7 +3955,29 @@ function createWarningTracker() {
3820
3955
  return { warnedKeys: new Set() };
3821
3956
  }
3822
3957
 
3958
+ class FieldErrorsWrapperBase {
3959
+ fieldComponent = viewChild.required('fieldComponent', { read: ViewContainerRef });
3960
+ validationMessages = input(/* @ts-ignore */
3961
+ ...(ngDevMode ? [undefined, { debugName: "validationMessages" }] : /* istanbul ignore next */ []));
3962
+ fieldInputs = input(/* @ts-ignore */
3963
+ ...(ngDevMode ? [undefined, { debugName: "fieldInputs" }] : /* istanbul ignore next */ []));
3964
+ claimedKey = computed(() => this.fieldInputs()?.key, /* @ts-ignore */
3965
+ ...(ngDevMode ? [{ debugName: "claimedKey" }] : /* istanbul ignore next */ []));
3966
+ ngf = injectFieldErrors({
3967
+ fieldInputs: this.fieldInputs,
3968
+ validationMessages: this.validationMessages,
3969
+ });
3970
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: FieldErrorsWrapperBase, deps: [], target: i0.ɵɵFactoryTarget.Directive });
3971
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "22.0.1", type: FieldErrorsWrapperBase, isStandalone: true, inputs: { validationMessages: { classPropertyName: "validationMessages", publicName: "validationMessages", isSignal: true, isRequired: false, transformFunction: null }, fieldInputs: { classPropertyName: "fieldInputs", publicName: "fieldInputs", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "fieldComponent", first: true, predicate: ["fieldComponent"], descendants: true, read: ViewContainerRef, isSignal: true }], ngImport: i0 });
3972
+ }
3973
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: FieldErrorsWrapperBase, decorators: [{
3974
+ type: Directive
3975
+ }], propDecorators: { fieldComponent: [{ type: i0.ViewChild, args: ['fieldComponent', { ...{ read: ViewContainerRef }, isSignal: true }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], fieldInputs: [{ type: i0.Input, args: [{ isSignal: true, alias: "fieldInputs", required: false }] }] } });
3976
+ function provideFieldErrorDisplay(wrapper) {
3977
+ return { provide: FIELD_ERROR_DISPLAY, useExisting: forwardRef(wrapper) };
3978
+ }
3979
+
3823
3980
 
3824
3981
 
3825
- export { ADDON_ACTION_HANDLERS, ADDON_ACTION_REGISTRY, ADDON_TYPE_COMPONENT_CACHE, ADDON_TYPE_DEFINITIONS, ADDON_TYPE_REGISTRY, ARRAY_CONTEXT, AsyncConditionFunctionCacheService, ComponentInitializedEvent, DEFAULT_PROPS, DEFAULT_VALIDATION_MESSAGES, DEFAULT_WRAPPERS, DEPRECATION_WARNING_TRACKER, DF_FIELD_TEMPLATES, DfAddonSlot, DynamicFormError, DynamicFormLogger, DynamicTextPipe, DynamicValueFunctionCacheService, EMIT_FORM_VALUE_ON_EVENTS, EXTERNAL_DATA, EventBus, ExpressionParser, ExpressionParserError, FIELD_REGISTRY, FIELD_SIGNAL_CONTEXT, FORM_ID_PREFIX, FORM_OPTIONS, FieldContextRegistryService, FunctionRegistryService, GROUP_CONTEXT, HTTP_CONDITION_CACHE, HttpConditionCache, HttpConditionFunctionCacheService, INITIALIZATION_TIMEOUT_MS, LogicFunctionCacheService, NoopLogger, READONLY_FIELD_TREE_CACHE, RootFormRegistryService, TokenType, WRAPPER_AUTO_ASSOCIATIONS, WRAPPER_COMPONENT_CACHE, WRAPPER_REGISTRY, applyMetaToElement, applyValidator, applyValidators, arrayFieldMapper, assertNever, baseFieldMapper, buildBaseInputs, buildClassName, compareValues, containerFieldMapper, createAddonActionRegistry, createDebouncedLogicFunction, createDefaultDerivationLogConfig, createDynamicValueFunction, createFieldValueProxy, createFormFieldStateMap, createFormStateLogicFunction, createInitializationTracker, createLogicFunction, createWarningTracker, deepMergeDefaults, derivedFromDeferred, detectFormMode, dynamicTextToObservable, evaluateCondition, evaluateNonFieldDisabled, evaluateNonFieldHidden, extractExpressionDependencies, extractStringDependencies, getArrayLength, getChangedKeys, getFieldValueHandling, getGridClassString, getNestedValue, groupFieldMapper, hasChildFields, hasCrossFieldWhenCondition, hasFormValue, hasNestedProperty, hasTargetProperty, injectAddonTypeRegistry, injectFieldSignalContext, injectFieldsSupportingAddons, injectNonFieldEvaluationContext, interpolateParams, isArrayField, isCheckedField, isContainerField, isCrossFieldBuiltInValidator, isCrossFieldExpression, isCrossFieldSchema, isCrossFieldStateLogic, isCrossFieldValidator, isDerivationLogicConfig, isDisplayOnlyField, isEqual, isFieldBoundContext, isFormStateCondition, isFunctionHttpValidator, isGenericContainerField, isGroupField, isHiddenField, isLeafField, isNonPagedForm, isPageField, isPagedForm, isResourceBasedValidator, isRowField, isSimplifiedArrayField, isStateLogicConfig, isValidNonPagedForm, isValidPagedForm, isValueBearingField, isValueField, isWrapperTypeDefinition, keyBy, mapValues, memoize, normalizeFieldsArray, omit, pageFieldMapper, readFieldStateInfo, resolveDynamicValue, resolveHttpRequest, resolveNextButtonDisabled, resolveNonFieldDisabled, resolveNonFieldHidden, resolveSubmitButtonDisabled, resolveTokens, rowFieldMapper, runPresetAction, setupInitializationTracking, shouldLog, textFieldMapper, toReadonlyFieldTree, toReadonlyFieldTreeCached, validatePageNesting, withPreviousValue, writeToFieldValue };
3982
+ export { ADDON_ACTION_HANDLERS, ADDON_ACTION_REGISTRY, ADDON_TYPE_COMPONENT_CACHE, ADDON_TYPE_DEFINITIONS, ADDON_TYPE_REGISTRY, ARRAY_CONTEXT, AsyncConditionFunctionCacheService, ComponentInitializedEvent, DEFAULT_PROPS, DEFAULT_VALIDATION_MESSAGES, DEFAULT_WRAPPERS, DEPRECATION_WARNING_TRACKER, DF_FIELD_TEMPLATES, DfAddonSlot, DynamicFormError, DynamicFormLogger, DynamicTextPipe, DynamicValueFunctionCacheService, EMIT_FORM_VALUE_ON_EVENTS, EXTERNAL_DATA, EventBus, ExpressionParser, ExpressionParserError, FIELD_ERROR_DISPLAY, FIELD_REGISTRY, FIELD_SIGNAL_CONTEXT, FORM_ID_PREFIX, FORM_OPTIONS, FieldContextRegistryService, FieldErrorsWrapperBase, FunctionRegistryService, GROUP_CONTEXT, HTTP_CONDITION_CACHE, HttpConditionCache, HttpConditionFunctionCacheService, INITIALIZATION_TIMEOUT_MS, LogicFunctionCacheService, NoopLogger, READONLY_FIELD_TREE_CACHE, RootFormRegistryService, TokenType, WRAPPER_AUTO_ASSOCIATIONS, WRAPPER_COMPONENT_CACHE, WRAPPER_REGISTRY, applyMetaToElement, applyValidator, applyValidators, arrayFieldMapper, assertNever, baseFieldMapper, buildBaseInputs, buildClassName, compareValues, containerFieldMapper, createAddonActionRegistry, createDebouncedLogicFunction, createDefaultDerivationLogConfig, createDynamicValueFunction, createFieldValueProxy, createFormFieldStateMap, createFormStateLogicFunction, createInitializationTracker, createLogicFunction, createResolvedErrorsSignal, createWarningTracker, deepMergeDefaults, derivedFromDeferred, detectFormMode, dynamicTextToObservable, evaluateCondition, evaluateNonFieldDisabled, evaluateNonFieldHidden, extractExpressionDependencies, extractStringDependencies, getArrayLength, getChangedKeys, getChangedKeysWithin, getFieldValueHandling, getGridClassString, getNestedValue, groupFieldMapper, hasChildFields, hasCrossFieldWhenCondition, hasFormValue, hasNestedProperty, hasTargetProperty, injectAddonTypeRegistry, injectFieldErrors, injectFieldSignalContext, injectFieldsSupportingAddons, injectNonFieldEvaluationContext, interpolateParams, isArrayField, isCheckedField, isContainerField, isCrossFieldBuiltInValidator, isCrossFieldExpression, isCrossFieldSchema, isCrossFieldStateLogic, isCrossFieldValidator, isDerivationLogicConfig, isDisplayOnlyField, isEqual, isFieldBoundContext, isFormStateCondition, isFunctionHttpValidator, isGenericContainerField, isGroupField, isHiddenField, isLeafField, isNonPagedForm, isPageField, isPagedForm, isResourceBasedValidator, isRowField, isSimplifiedArrayField, isStateLogicConfig, isValidNonPagedForm, isValidPagedForm, isValueBearingField, isValueField, isWrapperTypeDefinition, keyBy, mapValues, memoize, normalizeFieldsArray, omit, pageFieldMapper, provideFieldErrorDisplay, readFieldStateInfo, resolveDynamicValue, resolveHttpRequest, resolveNextButtonDisabled, resolveNonFieldDisabled, resolveNonFieldHidden, resolveSubmitButtonDisabled, resolveTokens, rowError, rowFieldMapper, runPresetAction, setupInitializationTracking, shouldLog, shouldShowErrors, textFieldMapper, toReadonlyFieldTree, toReadonlyFieldTreeCached, validatePageNesting, withPreviousValue, writeToFieldValue };
3826
3983
  //# sourceMappingURL=ng-forge-dynamic-forms-internal.mjs.map