@ng-forge/dynamic-forms 1.1.0 → 1.2.0-next.10
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.
- package/README.md +11 -11
- package/fesm2022/{ng-forge-dynamic-forms-array-field.component-CvjDqYyq.mjs → ng-forge-dynamic-forms-array-field.component-CSCKq_1K.mjs} +9 -13
- package/fesm2022/ng-forge-dynamic-forms-array-field.component-CSCKq_1K.mjs.map +1 -0
- package/fesm2022/{ng-forge-dynamic-forms-bootstrap-derivation-orchestrator-CcoUnroD.mjs → ng-forge-dynamic-forms-bootstrap-derivation-orchestrator-CTOTwzzw.mjs} +29 -7
- package/fesm2022/ng-forge-dynamic-forms-bootstrap-derivation-orchestrator-CTOTwzzw.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-bootstrap-web-mcp-BtjqeJOj.mjs +1054 -0
- package/fesm2022/ng-forge-dynamic-forms-bootstrap-web-mcp-BtjqeJOj.mjs.map +1 -0
- package/fesm2022/{ng-forge-dynamic-forms-container-field.component-DZfVWjiM.mjs → ng-forge-dynamic-forms-container-field.component-Dc3ROhHL.mjs} +14 -17
- package/fesm2022/ng-forge-dynamic-forms-container-field.component-Dc3ROhHL.mjs.map +1 -0
- package/fesm2022/{ng-forge-dynamic-forms-css-wrapper.component-D_yRuLpu.mjs → ng-forge-dynamic-forms-css-wrapper.component-BzgX8lAD.mjs} +5 -5
- package/fesm2022/ng-forge-dynamic-forms-css-wrapper.component-BzgX8lAD.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-debounce-C9F4v1Ke.mjs +17 -0
- package/fesm2022/ng-forge-dynamic-forms-debounce-C9F4v1Ke.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-field-errors-wrapper.component-CIKbWqYA.mjs +25 -0
- package/fesm2022/ng-forge-dynamic-forms-field-errors-wrapper.component-CIKbWqYA.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-form-schema.service-Dx5Dlb15.mjs +24 -0
- package/fesm2022/ng-forge-dynamic-forms-form-schema.service-Dx5Dlb15.mjs.map +1 -0
- package/fesm2022/{ng-forge-dynamic-forms-group-field.component-CPFgu3pM.mjs → ng-forge-dynamic-forms-group-field.component-DAC3P9DC.mjs} +9 -13
- package/fesm2022/ng-forge-dynamic-forms-group-field.component-DAC3P9DC.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-integration.mjs +49 -107
- package/fesm2022/ng-forge-dynamic-forms-integration.mjs.map +1 -1
- package/fesm2022/ng-forge-dynamic-forms-internal.mjs +434 -139
- package/fesm2022/ng-forge-dynamic-forms-internal.mjs.map +1 -1
- package/fesm2022/{ng-forge-dynamic-forms-ng-forge-dynamic-forms-Du3V5AOb.mjs → ng-forge-dynamic-forms-ng-forge-dynamic-forms-CXQe_5td.mjs} +1930 -1847
- package/fesm2022/ng-forge-dynamic-forms-ng-forge-dynamic-forms-CXQe_5td.mjs.map +1 -0
- package/fesm2022/{ng-forge-dynamic-forms-page-field.component-amWhCdHL.mjs → ng-forge-dynamic-forms-page-field.component-DPKJcwUO.mjs} +94 -15
- package/fesm2022/ng-forge-dynamic-forms-page-field.component-DPKJcwUO.mjs.map +1 -0
- package/fesm2022/{ng-forge-dynamic-forms-row-wrapper.component-BBWmqQA_.mjs → ng-forge-dynamic-forms-row-wrapper.component-DMEeKZny.mjs} +5 -5
- package/fesm2022/ng-forge-dynamic-forms-row-wrapper.component-DMEeKZny.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-schema-builder-BvDTzfdM.mjs +570 -0
- package/fesm2022/ng-forge-dynamic-forms-schema-builder-BvDTzfdM.mjs.map +1 -0
- package/fesm2022/{ng-forge-dynamic-forms-text-field.component-C-f80sbk.mjs → ng-forge-dynamic-forms-text-field.component-BB-jutBq.mjs} +4 -4
- package/fesm2022/{ng-forge-dynamic-forms-text-field.component-C-f80sbk.mjs.map → ng-forge-dynamic-forms-text-field.component-BB-jutBq.mjs.map} +1 -1
- package/fesm2022/ng-forge-dynamic-forms.mjs +2 -2
- package/package.json +2 -2
- package/types/ng-forge-dynamic-forms-integration.d.ts +15 -33
- package/types/ng-forge-dynamic-forms-internal.d.ts +705 -292
- package/types/ng-forge-dynamic-forms.d.ts +400 -46
- package/fesm2022/ng-forge-dynamic-forms-array-field.component-CvjDqYyq.mjs.map +0 -1
- package/fesm2022/ng-forge-dynamic-forms-bootstrap-derivation-orchestrator-CcoUnroD.mjs.map +0 -1
- package/fesm2022/ng-forge-dynamic-forms-container-field.component-DZfVWjiM.mjs.map +0 -1
- package/fesm2022/ng-forge-dynamic-forms-container-utils-BZFz6ztF.mjs +0 -24
- package/fesm2022/ng-forge-dynamic-forms-container-utils-BZFz6ztF.mjs.map +0 -1
- package/fesm2022/ng-forge-dynamic-forms-css-wrapper.component-D_yRuLpu.mjs.map +0 -1
- package/fesm2022/ng-forge-dynamic-forms-emit-initialization-DhHwU6FJ.mjs +0 -17
- package/fesm2022/ng-forge-dynamic-forms-emit-initialization-DhHwU6FJ.mjs.map +0 -1
- package/fesm2022/ng-forge-dynamic-forms-group-field.component-CPFgu3pM.mjs.map +0 -1
- package/fesm2022/ng-forge-dynamic-forms-ng-forge-dynamic-forms-Du3V5AOb.mjs.map +0 -1
- package/fesm2022/ng-forge-dynamic-forms-page-field.component-amWhCdHL.mjs.map +0 -1
- package/fesm2022/ng-forge-dynamic-forms-row-wrapper.component-BBWmqQA_.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 {
|
|
9
|
-
import {
|
|
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
|
|
|
@@ -155,14 +155,14 @@ class DfAddonSlot {
|
|
|
155
155
|
});
|
|
156
156
|
});
|
|
157
157
|
}
|
|
158
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.
|
|
159
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.
|
|
158
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: DfAddonSlot, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
159
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: DfAddonSlot, isStandalone: true, selector: "df-addon-slot", inputs: { addon: { classPropertyName: "addon", publicName: "addon", isSignal: true, isRequired: true, transformFunction: null }, fieldInputs: { classPropertyName: "fieldInputs", publicName: "fieldInputs", isSignal: true, isRequired: false, transformFunction: null }, hidden: { classPropertyName: "hidden", publicName: "hidden", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.slot": "slotAttr()", "class": "className()", "style.display": "isHidden() ? \"none\" : null" } }, ngImport: i0, template: `
|
|
160
160
|
@if (resolvedComponent(); as cmp) {
|
|
161
161
|
<ng-container *ngComponentOutlet="cmp; inputs: typeInputs()" />
|
|
162
162
|
}
|
|
163
163
|
`, isInline: true, dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
164
164
|
}
|
|
165
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.
|
|
165
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: DfAddonSlot, decorators: [{
|
|
166
166
|
type: Component,
|
|
167
167
|
args: [{
|
|
168
168
|
selector: 'df-addon-slot',
|
|
@@ -295,7 +295,11 @@ function hasTargetProperty(config) {
|
|
|
295
295
|
}
|
|
296
296
|
|
|
297
297
|
const FORM_VALUE_ACCESS_PATTERN = /\bformValue\s*(?:\.|\[)/;
|
|
298
|
-
const
|
|
298
|
+
const ID_START = String.raw `[\p{ID_Start}$_]`;
|
|
299
|
+
const ID_PART = String.raw `[\p{ID_Continue}$]`;
|
|
300
|
+
const DOTTED_PATH = String.raw `${ID_START}${ID_PART}*(?:\.${ID_START}${ID_PART}*)*`;
|
|
301
|
+
const BRACKET_KEY = String.raw `[\p{ID_Continue}$.\-]+`;
|
|
302
|
+
const FORM_VALUE_PATTERN = new RegExp(String.raw `\bformValue\s*(?:\.(${DOTTED_PATH})|\[\s*'(${BRACKET_KEY})'\s*\]|\[\s*"(${BRACKET_KEY})"\s*\])`, 'gu');
|
|
299
303
|
function isCrossFieldExpression(expr, context) {
|
|
300
304
|
if (expr === undefined || typeof expr === 'boolean' || isFormStateCondition(expr)) {
|
|
301
305
|
return false;
|
|
@@ -392,15 +396,6 @@ function hasCrossFieldWhenCondition(config, context) {
|
|
|
392
396
|
}
|
|
393
397
|
return isCrossFieldExpression(config.when, context);
|
|
394
398
|
}
|
|
395
|
-
function requiresTreeValidation(config) {
|
|
396
|
-
if (isResourceBasedValidator(config)) {
|
|
397
|
-
return false;
|
|
398
|
-
}
|
|
399
|
-
if (config.type === 'custom') {
|
|
400
|
-
return isCrossFieldValidator(config);
|
|
401
|
-
}
|
|
402
|
-
return isCrossFieldBuiltInValidator(config);
|
|
403
|
-
}
|
|
404
399
|
function isCrossFieldStateLogic(config, context) {
|
|
405
400
|
return isCrossFieldExpression(config.condition, context);
|
|
406
401
|
}
|
|
@@ -585,6 +580,8 @@ class ExpressionParserError extends DynamicFormError {
|
|
|
585
580
|
}
|
|
586
581
|
}
|
|
587
582
|
|
|
583
|
+
const IDENTIFIER_START = /[\p{ID_Start}$_]/u;
|
|
584
|
+
const IDENTIFIER_PART = /[\p{ID_Continue}$]/u;
|
|
588
585
|
class Tokenizer {
|
|
589
586
|
position = 0;
|
|
590
587
|
expression;
|
|
@@ -617,7 +614,7 @@ class Tokenizer {
|
|
|
617
614
|
if (/[0-9]/.test(char)) {
|
|
618
615
|
return this.readNumber();
|
|
619
616
|
}
|
|
620
|
-
if (
|
|
617
|
+
if (IDENTIFIER_START.test(this.codePointAt(this.position))) {
|
|
621
618
|
return this.readIdentifierOrKeyword();
|
|
622
619
|
}
|
|
623
620
|
return this.readOperatorOrPunctuation();
|
|
@@ -676,12 +673,20 @@ class Tokenizer {
|
|
|
676
673
|
readIdentifierOrKeyword() {
|
|
677
674
|
const start = this.position;
|
|
678
675
|
let value = '';
|
|
679
|
-
while (this.position < this.expression.length
|
|
680
|
-
|
|
681
|
-
|
|
676
|
+
while (this.position < this.expression.length) {
|
|
677
|
+
const char = this.codePointAt(this.position);
|
|
678
|
+
if (!IDENTIFIER_PART.test(char)) {
|
|
679
|
+
break;
|
|
680
|
+
}
|
|
681
|
+
value += char;
|
|
682
|
+
this.position += char.length;
|
|
682
683
|
}
|
|
683
684
|
const type = this.getKeywordType(value);
|
|
684
685
|
return { type, value, position: start };
|
|
686
|
+
}
|
|
687
|
+
codePointAt(position) {
|
|
688
|
+
const codePoint = this.expression.codePointAt(position);
|
|
689
|
+
return codePoint === undefined ? '' : String.fromCodePoint(codePoint);
|
|
685
690
|
}
|
|
686
691
|
getKeywordType(value) {
|
|
687
692
|
switch (value) {
|
|
@@ -1570,6 +1575,54 @@ function safeReadPathKeys(fieldContext) {
|
|
|
1570
1575
|
return untracked(() => fieldContext.pathKeys());
|
|
1571
1576
|
}
|
|
1572
1577
|
|
|
1578
|
+
function createFieldValueProxy(getRootForm, getRootFormValue) {
|
|
1579
|
+
const resolveAccessor = (key) => {
|
|
1580
|
+
const root = getRootForm();
|
|
1581
|
+
const accessor = root?.[key];
|
|
1582
|
+
return typeof accessor === 'function' ? accessor : undefined;
|
|
1583
|
+
};
|
|
1584
|
+
const readField = (key) => {
|
|
1585
|
+
const accessor = resolveAccessor(key);
|
|
1586
|
+
if (accessor) {
|
|
1587
|
+
const state = untracked(() => accessor());
|
|
1588
|
+
const valueSig = state && state.value;
|
|
1589
|
+
if (typeof valueSig === 'function') {
|
|
1590
|
+
return { hit: true, value: valueSig() };
|
|
1591
|
+
}
|
|
1592
|
+
}
|
|
1593
|
+
return { hit: false, value: undefined };
|
|
1594
|
+
};
|
|
1595
|
+
return new Proxy({}, {
|
|
1596
|
+
get(_target, prop) {
|
|
1597
|
+
if (typeof prop === 'symbol')
|
|
1598
|
+
return undefined;
|
|
1599
|
+
const { hit, value } = readField(prop);
|
|
1600
|
+
return hit ? value : getRootFormValue()[prop];
|
|
1601
|
+
},
|
|
1602
|
+
has(_target, prop) {
|
|
1603
|
+
if (typeof prop === 'symbol')
|
|
1604
|
+
return false;
|
|
1605
|
+
if (resolveAccessor(prop))
|
|
1606
|
+
return true;
|
|
1607
|
+
return prop in getRootFormValue();
|
|
1608
|
+
},
|
|
1609
|
+
ownKeys() {
|
|
1610
|
+
return Reflect.ownKeys(getRootFormValue());
|
|
1611
|
+
},
|
|
1612
|
+
getOwnPropertyDescriptor(_target, prop) {
|
|
1613
|
+
if (typeof prop === 'symbol')
|
|
1614
|
+
return undefined;
|
|
1615
|
+
const whole = getRootFormValue();
|
|
1616
|
+
if (!(prop in whole))
|
|
1617
|
+
return undefined;
|
|
1618
|
+
const { hit, value } = readField(prop);
|
|
1619
|
+
return { value: hit ? value : whole[prop], enumerable: true, configurable: true, writable: false };
|
|
1620
|
+
},
|
|
1621
|
+
set() {
|
|
1622
|
+
return false; },
|
|
1623
|
+
});
|
|
1624
|
+
}
|
|
1625
|
+
|
|
1573
1626
|
function isChildFieldContext(context) {
|
|
1574
1627
|
return 'key' in context && isSignal(context.key);
|
|
1575
1628
|
}
|
|
@@ -1580,6 +1633,17 @@ function extractFieldState(fieldContext) {
|
|
|
1580
1633
|
return fieldContext.state;
|
|
1581
1634
|
});
|
|
1582
1635
|
}
|
|
1636
|
+
function navigateArrayItemTree(root, arrayKey, index) {
|
|
1637
|
+
let node = root;
|
|
1638
|
+
for (const segment of arrayKey.split('.')) {
|
|
1639
|
+
if (node == null)
|
|
1640
|
+
return undefined;
|
|
1641
|
+
node = node[segment];
|
|
1642
|
+
}
|
|
1643
|
+
if (node == null)
|
|
1644
|
+
return undefined;
|
|
1645
|
+
return node[index];
|
|
1646
|
+
}
|
|
1583
1647
|
function detectArrayScope(pathKeys) {
|
|
1584
1648
|
if (pathKeys.length < 3)
|
|
1585
1649
|
return undefined;
|
|
@@ -1693,6 +1757,65 @@ class FieldContextRegistryService {
|
|
|
1693
1757
|
return formFieldStateGetter();
|
|
1694
1758
|
},
|
|
1695
1759
|
};
|
|
1760
|
+
}
|
|
1761
|
+
buildReactiveArrayScopedContext(arrayScope, fieldValue, customFunctions, fieldContext) {
|
|
1762
|
+
const { arrayKey, index, localKey } = arrayScope;
|
|
1763
|
+
const rootFormSignal = this.rootFormRegistry.rootForm;
|
|
1764
|
+
const resolveExternalData = () => this.resolveExternalData();
|
|
1765
|
+
const fieldStateGetter = fieldContext ? () => readFieldStateInfo(extractFieldState(fieldContext), true) : () => undefined;
|
|
1766
|
+
const formFieldStateGetter = () => createFormFieldStateMap(rootFormSignal(), true);
|
|
1767
|
+
const hasValidItem = untracked(() => {
|
|
1768
|
+
const arrayData = getNestedValue(this.rootFormRegistry.formValue(), arrayKey);
|
|
1769
|
+
if (!Array.isArray(arrayData) || index < 0 || index >= arrayData.length)
|
|
1770
|
+
return false;
|
|
1771
|
+
const item = arrayData[index];
|
|
1772
|
+
return item != null && typeof item === 'object';
|
|
1773
|
+
});
|
|
1774
|
+
const rootFormValueProxy = createFieldValueProxy(() => rootFormSignal(), () => this.rootFormRegistry.formValue());
|
|
1775
|
+
if (!hasValidItem) {
|
|
1776
|
+
return {
|
|
1777
|
+
fieldValue,
|
|
1778
|
+
formValue: rootFormValueProxy,
|
|
1779
|
+
fieldPath: localKey,
|
|
1780
|
+
customFunctions: customFunctions || {},
|
|
1781
|
+
logger: this.logger,
|
|
1782
|
+
deprecationTracker: this.deprecationTracker ?? undefined,
|
|
1783
|
+
get externalData() {
|
|
1784
|
+
return resolveExternalData();
|
|
1785
|
+
},
|
|
1786
|
+
get fieldState() {
|
|
1787
|
+
return fieldStateGetter();
|
|
1788
|
+
},
|
|
1789
|
+
get formFieldState() {
|
|
1790
|
+
return formFieldStateGetter();
|
|
1791
|
+
},
|
|
1792
|
+
};
|
|
1793
|
+
}
|
|
1794
|
+
const itemFormValueProxy = createFieldValueProxy(() => navigateArrayItemTree(rootFormSignal(), arrayKey, index), () => {
|
|
1795
|
+
const arrayData = getNestedValue(this.rootFormRegistry.formValue(), arrayKey);
|
|
1796
|
+
const item = Array.isArray(arrayData) ? arrayData[index] : undefined;
|
|
1797
|
+
return item != null && typeof item === 'object' ? item : {};
|
|
1798
|
+
});
|
|
1799
|
+
return {
|
|
1800
|
+
fieldValue,
|
|
1801
|
+
formValue: itemFormValueProxy,
|
|
1802
|
+
rootFormValue: rootFormValueProxy,
|
|
1803
|
+
arrayIndex: index,
|
|
1804
|
+
arrayPath: arrayKey,
|
|
1805
|
+
fieldPath: `${arrayKey}.${index}.${localKey}`,
|
|
1806
|
+
customFunctions: customFunctions || {},
|
|
1807
|
+
logger: this.logger,
|
|
1808
|
+
deprecationTracker: this.deprecationTracker ?? undefined,
|
|
1809
|
+
get externalData() {
|
|
1810
|
+
return resolveExternalData();
|
|
1811
|
+
},
|
|
1812
|
+
get fieldState() {
|
|
1813
|
+
return fieldStateGetter();
|
|
1814
|
+
},
|
|
1815
|
+
get formFieldState() {
|
|
1816
|
+
return formFieldStateGetter();
|
|
1817
|
+
},
|
|
1818
|
+
};
|
|
1696
1819
|
}
|
|
1697
1820
|
resolveExternalData() {
|
|
1698
1821
|
const externalDataSignal = this.externalDataSignal;
|
|
@@ -1702,29 +1825,48 @@ class FieldContextRegistryService {
|
|
|
1702
1825
|
if (!externalDataRecord) {
|
|
1703
1826
|
return undefined;
|
|
1704
1827
|
}
|
|
1705
|
-
const
|
|
1706
|
-
|
|
1828
|
+
const readKey = (key) => {
|
|
1829
|
+
const value = externalDataRecord[key];
|
|
1707
1830
|
if (!isSignal(value)) {
|
|
1708
1831
|
throw new DynamicFormError(`externalData["${key}"] must be a Signal. Got: ${typeof value}. Wrap it with signal(yourValue).`);
|
|
1709
1832
|
}
|
|
1710
|
-
|
|
1711
|
-
}
|
|
1712
|
-
return
|
|
1833
|
+
return value();
|
|
1834
|
+
};
|
|
1835
|
+
return new Proxy({}, {
|
|
1836
|
+
get(_target, prop) {
|
|
1837
|
+
if (typeof prop === 'symbol' || !(prop in externalDataRecord))
|
|
1838
|
+
return undefined;
|
|
1839
|
+
return readKey(prop);
|
|
1840
|
+
},
|
|
1841
|
+
has(_target, prop) {
|
|
1842
|
+
return typeof prop === 'string' && prop in externalDataRecord;
|
|
1843
|
+
},
|
|
1844
|
+
ownKeys() {
|
|
1845
|
+
return Reflect.ownKeys(externalDataRecord);
|
|
1846
|
+
},
|
|
1847
|
+
getOwnPropertyDescriptor(_target, prop) {
|
|
1848
|
+
if (typeof prop !== 'string' || !(prop in externalDataRecord))
|
|
1849
|
+
return undefined;
|
|
1850
|
+
return { value: readKey(prop), enumerable: true, configurable: true, writable: false };
|
|
1851
|
+
},
|
|
1852
|
+
set() {
|
|
1853
|
+
return false; },
|
|
1854
|
+
});
|
|
1713
1855
|
}
|
|
1714
1856
|
createReactiveEvaluationContext(fieldContext, customFunctions) {
|
|
1715
1857
|
const fieldValue = fieldContext.value();
|
|
1716
|
-
const rootFormValue = this.rootFormRegistry.formValue();
|
|
1717
1858
|
const pathKeys = safeReadPathKeys(fieldContext);
|
|
1718
1859
|
const arrayScope = detectArrayScope(pathKeys);
|
|
1719
1860
|
if (arrayScope) {
|
|
1720
|
-
return this.
|
|
1861
|
+
return this.buildReactiveArrayScopedContext(arrayScope, fieldValue, customFunctions, fieldContext);
|
|
1721
1862
|
}
|
|
1722
1863
|
const localKey = this.extractFieldPath(fieldContext);
|
|
1723
1864
|
const rootFormSignal = this.rootFormRegistry.rootForm;
|
|
1724
1865
|
const resolveExternalData = () => this.resolveExternalData();
|
|
1866
|
+
const formValueProxy = createFieldValueProxy(() => rootFormSignal(), () => this.rootFormRegistry.formValue());
|
|
1725
1867
|
return {
|
|
1726
1868
|
fieldValue,
|
|
1727
|
-
formValue:
|
|
1869
|
+
formValue: formValueProxy,
|
|
1728
1870
|
fieldPath: localKey,
|
|
1729
1871
|
customFunctions: customFunctions || {},
|
|
1730
1872
|
logger: this.logger,
|
|
@@ -1741,15 +1883,15 @@ class FieldContextRegistryService {
|
|
|
1741
1883
|
};
|
|
1742
1884
|
}
|
|
1743
1885
|
createDisplayOnlyContext(fieldPath, customFunctions, arrayScope) {
|
|
1744
|
-
const rootFormValue = this.rootFormRegistry.formValue();
|
|
1745
1886
|
if (arrayScope) {
|
|
1746
|
-
return this.
|
|
1887
|
+
return this.buildReactiveArrayScopedContext(arrayScope, undefined, customFunctions);
|
|
1747
1888
|
}
|
|
1748
1889
|
const rootFormSignal = this.rootFormRegistry.rootForm;
|
|
1749
1890
|
const resolveExternalData = () => this.resolveExternalData();
|
|
1891
|
+
const formValueProxy = createFieldValueProxy(() => rootFormSignal(), () => this.rootFormRegistry.formValue());
|
|
1750
1892
|
return {
|
|
1751
1893
|
fieldValue: undefined,
|
|
1752
|
-
formValue:
|
|
1894
|
+
formValue: formValueProxy,
|
|
1753
1895
|
fieldPath,
|
|
1754
1896
|
customFunctions: customFunctions || {},
|
|
1755
1897
|
logger: this.logger,
|
|
@@ -1762,10 +1904,10 @@ class FieldContextRegistryService {
|
|
|
1762
1904
|
},
|
|
1763
1905
|
};
|
|
1764
1906
|
}
|
|
1765
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.
|
|
1766
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.
|
|
1907
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: FieldContextRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1908
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: FieldContextRegistryService });
|
|
1767
1909
|
}
|
|
1768
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.
|
|
1910
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: FieldContextRegistryService, decorators: [{
|
|
1769
1911
|
type: Injectable
|
|
1770
1912
|
}] });
|
|
1771
1913
|
|
|
@@ -1894,10 +2036,10 @@ class FunctionRegistryService {
|
|
|
1894
2036
|
this.clearAsyncValidators();
|
|
1895
2037
|
this.clearHttpValidators();
|
|
1896
2038
|
}
|
|
1897
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.
|
|
1898
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.
|
|
2039
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: FunctionRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2040
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: FunctionRegistryService });
|
|
1899
2041
|
}
|
|
1900
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.
|
|
2042
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: FunctionRegistryService, decorators: [{
|
|
1901
2043
|
type: Injectable
|
|
1902
2044
|
}] });
|
|
1903
2045
|
|
|
@@ -2523,6 +2665,187 @@ function injectNonFieldEvaluationContext(fieldDef, options = {}) {
|
|
|
2523
2665
|
};
|
|
2524
2666
|
}
|
|
2525
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
|
+
|
|
2526
2849
|
function isFunctionHttpValidator(config) {
|
|
2527
2850
|
const c = config;
|
|
2528
2851
|
return typeof c.functionName === 'string' || (c.fn !== null && typeof c.fn === 'object');
|
|
@@ -2570,9 +2893,9 @@ function createDynamicValueFunction(expression) {
|
|
|
2570
2893
|
return cached;
|
|
2571
2894
|
}
|
|
2572
2895
|
const fn = (ctx) => {
|
|
2573
|
-
|
|
2896
|
+
const evaluationContext = fieldContextRegistry.createReactiveEvaluationContext(ctx);
|
|
2574
2897
|
try {
|
|
2575
|
-
|
|
2898
|
+
return (ExpressionParser.evaluate(expression, evaluationContext) ?? undefined);
|
|
2576
2899
|
}
|
|
2577
2900
|
catch (error) {
|
|
2578
2901
|
logger.error('Error evaluating dynamic expression:', expression, error);
|
|
@@ -2634,11 +2957,9 @@ function applyPatternValidator(path, value, expression, when) {
|
|
|
2634
2957
|
function createConditionalLogic(when) {
|
|
2635
2958
|
return when ? createLogicFunction(when) : undefined;
|
|
2636
2959
|
}
|
|
2637
|
-
function applyValidator(config,
|
|
2960
|
+
function applyValidator(config,
|
|
2961
|
+
fieldPath, attachment = 'field') {
|
|
2638
2962
|
const path = fieldPath;
|
|
2639
|
-
if (requiresTreeValidation(config)) {
|
|
2640
|
-
return;
|
|
2641
|
-
}
|
|
2642
2963
|
switch (config.type) {
|
|
2643
2964
|
case 'required':
|
|
2644
2965
|
required(path, config.when ? { when: createConditionalLogic(config.when) } : undefined);
|
|
@@ -2684,7 +3005,7 @@ function applyValidator(config, fieldPath) {
|
|
|
2684
3005
|
}
|
|
2685
3006
|
break;
|
|
2686
3007
|
case 'custom':
|
|
2687
|
-
applyCustomValidator(config, path);
|
|
3008
|
+
applyCustomValidator(config, path, attachment);
|
|
2688
3009
|
break;
|
|
2689
3010
|
case 'async':
|
|
2690
3011
|
applyAsyncValidator(config, path);
|
|
@@ -2694,7 +3015,7 @@ function applyValidator(config, fieldPath) {
|
|
|
2694
3015
|
break;
|
|
2695
3016
|
}
|
|
2696
3017
|
}
|
|
2697
|
-
function applyCustomValidator(config, fieldPath) {
|
|
3018
|
+
function applyCustomValidator(config, fieldPath, attachment = 'field') {
|
|
2698
3019
|
let validatorFn;
|
|
2699
3020
|
if (config.expression) {
|
|
2700
3021
|
validatorFn = createExpressionValidator(config);
|
|
@@ -2706,11 +3027,16 @@ function applyCustomValidator(config, fieldPath) {
|
|
|
2706
3027
|
throw new DynamicFormError('Custom validator requires one of "expression", "functionName", or "fn".');
|
|
2707
3028
|
}
|
|
2708
3029
|
const whenLogic = createConditionalLogic(config.when);
|
|
2709
|
-
|
|
3030
|
+
const run = (ctx) => {
|
|
2710
3031
|
if (whenLogic && !whenLogic(ctx))
|
|
2711
3032
|
return null;
|
|
2712
3033
|
return validatorFn(ctx);
|
|
2713
|
-
}
|
|
3034
|
+
};
|
|
3035
|
+
if (attachment === 'tree') {
|
|
3036
|
+
validateTree(fieldPath, run);
|
|
3037
|
+
return;
|
|
3038
|
+
}
|
|
3039
|
+
validate(fieldPath, run);
|
|
2714
3040
|
}
|
|
2715
3041
|
function createFunctionValidator(config) {
|
|
2716
3042
|
const logger = inject(DynamicFormLogger);
|
|
@@ -2742,7 +3068,7 @@ function createExpressionValidator(config) {
|
|
|
2742
3068
|
const functionRegistry = inject(FunctionRegistryService);
|
|
2743
3069
|
return (ctx) => {
|
|
2744
3070
|
try {
|
|
2745
|
-
|
|
3071
|
+
const evaluationContext = fieldContextRegistry.createReactiveEvaluationContext(ctx, functionRegistry.getCustomFunctions());
|
|
2746
3072
|
const result = ExpressionParser.evaluate(expression, evaluationContext);
|
|
2747
3073
|
if (result) {
|
|
2748
3074
|
return null;
|
|
@@ -2862,8 +3188,9 @@ function applyDeclarativeHttpValidator(config, fieldPath) {
|
|
|
2862
3188
|
},
|
|
2863
3189
|
});
|
|
2864
3190
|
}
|
|
2865
|
-
function applyValidators(configs,
|
|
2866
|
-
|
|
3191
|
+
function applyValidators(configs,
|
|
3192
|
+
fieldPath, attachment = 'field') {
|
|
3193
|
+
configs.forEach((config) => applyValidator(config, fieldPath, attachment));
|
|
2867
3194
|
}
|
|
2868
3195
|
|
|
2869
3196
|
function isCheckedField(field) {
|
|
@@ -3019,10 +3346,10 @@ class EventBus {
|
|
|
3019
3346
|
}
|
|
3020
3347
|
return this.pipeline$.pipe(filter((event) => event.type === eventType));
|
|
3021
3348
|
}
|
|
3022
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.
|
|
3023
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.
|
|
3349
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: EventBus, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
3350
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: EventBus });
|
|
3024
3351
|
}
|
|
3025
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.
|
|
3352
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: EventBus, decorators: [{
|
|
3026
3353
|
type: Injectable
|
|
3027
3354
|
}] });
|
|
3028
3355
|
|
|
@@ -3079,7 +3406,6 @@ function applyHiddenLogic(inputs, fieldDef, rootFormRegistry, evaluationContext)
|
|
|
3079
3406
|
form: rootForm,
|
|
3080
3407
|
fieldLogic: fieldDef.logic,
|
|
3081
3408
|
explicitValue: fieldDef.hidden,
|
|
3082
|
-
formValue: rootFormRegistry.formValue(),
|
|
3083
3409
|
evaluationContext,
|
|
3084
3410
|
});
|
|
3085
3411
|
}
|
|
@@ -3237,6 +3563,10 @@ const WRAPPER_COMPONENT_CACHE = new InjectionToken('WRAPPER_COMPONENT_CACHE', {
|
|
|
3237
3563
|
providedIn: 'root',
|
|
3238
3564
|
factory: () => new Map(),
|
|
3239
3565
|
});
|
|
3566
|
+
const WRAPPER_COMPONENT_LOAD_CACHE = new InjectionToken('WRAPPER_COMPONENT_LOAD_CACHE', {
|
|
3567
|
+
providedIn: 'root',
|
|
3568
|
+
factory: () => new Map(),
|
|
3569
|
+
});
|
|
3240
3570
|
const WRAPPER_AUTO_ASSOCIATIONS = new InjectionToken('WRAPPER_AUTO_ASSOCIATIONS', {
|
|
3241
3571
|
providedIn: 'root',
|
|
3242
3572
|
factory: () => new Map(),
|
|
@@ -3350,28 +3680,15 @@ function isDisplayOnlyField(field) {
|
|
|
3350
3680
|
}
|
|
3351
3681
|
|
|
3352
3682
|
|
|
3353
|
-
function dynamicTextToObservable(value, injector) {
|
|
3354
|
-
if (value === undefined) {
|
|
3355
|
-
return of('');
|
|
3356
|
-
}
|
|
3357
|
-
if (isObservable(value)) {
|
|
3358
|
-
return value;
|
|
3359
|
-
}
|
|
3360
|
-
if (isSignal(value)) {
|
|
3361
|
-
return untracked(() => toObservable(value, { injector }));
|
|
3362
|
-
}
|
|
3363
|
-
return of(String(value));
|
|
3364
|
-
}
|
|
3365
|
-
|
|
3366
3683
|
class DynamicTextPipe {
|
|
3367
3684
|
injector = inject(Injector);
|
|
3368
3685
|
transform(value) {
|
|
3369
3686
|
return dynamicTextToObservable(value ?? undefined, this.injector);
|
|
3370
3687
|
}
|
|
3371
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.
|
|
3372
|
-
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.
|
|
3688
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: DynamicTextPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
3689
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.1.5", ngImport: i0, type: DynamicTextPipe, isStandalone: true, name: "dynamicText" });
|
|
3373
3690
|
}
|
|
3374
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.
|
|
3691
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: DynamicTextPipe, decorators: [{
|
|
3375
3692
|
type: Pipe,
|
|
3376
3693
|
args: [{
|
|
3377
3694
|
name: 'dynamicText',
|
|
@@ -3424,75 +3741,15 @@ function setupInitializationTracking(options) {
|
|
|
3424
3741
|
}), shareReplay({ bufferSize: 1, refCount: false }));
|
|
3425
3742
|
}
|
|
3426
3743
|
|
|
3427
|
-
function interpolateParams(message, error) {
|
|
3428
|
-
let result = message;
|
|
3429
|
-
const params = extractErrorParams(error);
|
|
3430
|
-
Object.entries(params).forEach(([key, value]) => {
|
|
3431
|
-
const placeholder = new RegExp(`{{\\s*${key}\\s*}}`, 'g');
|
|
3432
|
-
result = result.replace(placeholder, safeToString(value));
|
|
3433
|
-
});
|
|
3434
|
-
return result;
|
|
3435
|
-
}
|
|
3436
|
-
function safeToString(value) {
|
|
3437
|
-
if (value === null || value === undefined) {
|
|
3438
|
-
return '';
|
|
3439
|
-
}
|
|
3440
|
-
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
|
|
3441
|
-
return String(value);
|
|
3442
|
-
}
|
|
3443
|
-
if (value instanceof RegExp) {
|
|
3444
|
-
return value.toString();
|
|
3445
|
-
}
|
|
3446
|
-
if (value instanceof Date) {
|
|
3447
|
-
return value.toISOString();
|
|
3448
|
-
}
|
|
3449
|
-
if (Array.isArray(value)) {
|
|
3450
|
-
return value.join(', ');
|
|
3451
|
-
}
|
|
3452
|
-
try {
|
|
3453
|
-
if (typeof value === 'object' && value.toString !== Object.prototype.toString) {
|
|
3454
|
-
return value.toString();
|
|
3455
|
-
}
|
|
3456
|
-
return JSON.stringify(value);
|
|
3457
|
-
}
|
|
3458
|
-
catch {
|
|
3459
|
-
return '[object]';
|
|
3460
|
-
}
|
|
3461
|
-
}
|
|
3462
|
-
function extractErrorParams(error) {
|
|
3463
|
-
const params = {};
|
|
3464
|
-
if ('min' in error)
|
|
3465
|
-
params.min = error.min;
|
|
3466
|
-
if ('max' in error)
|
|
3467
|
-
params.max = error.max;
|
|
3468
|
-
if ('pattern' in error)
|
|
3469
|
-
params.pattern = error.pattern;
|
|
3470
|
-
if ('actual' in error)
|
|
3471
|
-
params.actual = error.actual;
|
|
3472
|
-
if ('expected' in error)
|
|
3473
|
-
params.expected = error.expected;
|
|
3474
|
-
if ('requiredLength' in error) {
|
|
3475
|
-
params.requiredLength = error.requiredLength;
|
|
3476
|
-
}
|
|
3477
|
-
else if ('minLength' in error) {
|
|
3478
|
-
params.requiredLength = error.minLength;
|
|
3479
|
-
params.minLength = error.minLength;
|
|
3480
|
-
}
|
|
3481
|
-
else if ('maxLength' in error) {
|
|
3482
|
-
params.requiredLength = error.maxLength;
|
|
3483
|
-
params.maxLength = error.maxLength;
|
|
3484
|
-
}
|
|
3485
|
-
if ('actualLength' in error)
|
|
3486
|
-
params.actualLength = error.actualLength;
|
|
3487
|
-
Object.keys(error).forEach((key) => {
|
|
3488
|
-
if (key !== 'kind' && !(key in params)) {
|
|
3489
|
-
params[key] = error[key];
|
|
3490
|
-
}
|
|
3491
|
-
});
|
|
3492
|
-
return params;
|
|
3493
|
-
}
|
|
3494
|
-
|
|
3495
3744
|
function isEqual(a, b) {
|
|
3745
|
+
if (a === b)
|
|
3746
|
+
return true;
|
|
3747
|
+
if (typeof a === 'number' && typeof b === 'number')
|
|
3748
|
+
return Object.is(a, b);
|
|
3749
|
+
if (a == null || b == null)
|
|
3750
|
+
return false;
|
|
3751
|
+
if (typeof a !== 'object' || typeof b !== 'object')
|
|
3752
|
+
return Object.is(a, b);
|
|
3496
3753
|
return isEqualInternal(a, b, new WeakMap(), new WeakMap());
|
|
3497
3754
|
}
|
|
3498
3755
|
function isEqualInternal(a, b, seenA, seenB) {
|
|
@@ -3654,6 +3911,22 @@ function memoize(fn, resolverOrOptions) {
|
|
|
3654
3911
|
function normalizeFieldsArray(fields) {
|
|
3655
3912
|
return Array.isArray(fields) ? [...fields] : Object.values(fields);
|
|
3656
3913
|
}
|
|
3914
|
+
function getChangedKeysWithin(previous, current, keys) {
|
|
3915
|
+
const changed = new Set();
|
|
3916
|
+
if (keys.size === 0)
|
|
3917
|
+
return changed;
|
|
3918
|
+
const before = previous ?? {};
|
|
3919
|
+
const after = current ?? {};
|
|
3920
|
+
for (const key of keys) {
|
|
3921
|
+
const inBefore = key in before;
|
|
3922
|
+
const inAfter = key in after;
|
|
3923
|
+
if (!inBefore && !inAfter)
|
|
3924
|
+
continue;
|
|
3925
|
+
if (inBefore !== inAfter || !isEqual(before[key], after[key]))
|
|
3926
|
+
changed.add(key);
|
|
3927
|
+
}
|
|
3928
|
+
return changed;
|
|
3929
|
+
}
|
|
3657
3930
|
function getChangedKeys(previous, current) {
|
|
3658
3931
|
const changedKeys = new Set();
|
|
3659
3932
|
if (!previous && !current)
|
|
@@ -3686,7 +3959,29 @@ function createWarningTracker() {
|
|
|
3686
3959
|
return { warnedKeys: new Set() };
|
|
3687
3960
|
}
|
|
3688
3961
|
|
|
3962
|
+
class FieldErrorsWrapperBase {
|
|
3963
|
+
fieldComponent = viewChild.required('fieldComponent', { ...(ngDevMode ? { debugName: "fieldComponent" } : /* istanbul ignore next */ {}), read: ViewContainerRef });
|
|
3964
|
+
validationMessages = input(/* @ts-ignore */
|
|
3965
|
+
...(ngDevMode ? [undefined, { debugName: "validationMessages" }] : /* istanbul ignore next */ []));
|
|
3966
|
+
fieldInputs = input(/* @ts-ignore */
|
|
3967
|
+
...(ngDevMode ? [undefined, { debugName: "fieldInputs" }] : /* istanbul ignore next */ []));
|
|
3968
|
+
claimedKey = computed(() => this.fieldInputs()?.key, /* @ts-ignore */
|
|
3969
|
+
...(ngDevMode ? [{ debugName: "claimedKey" }] : /* istanbul ignore next */ []));
|
|
3970
|
+
ngf = injectFieldErrors({
|
|
3971
|
+
fieldInputs: this.fieldInputs,
|
|
3972
|
+
validationMessages: this.validationMessages,
|
|
3973
|
+
});
|
|
3974
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: FieldErrorsWrapperBase, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
3975
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "22.1.5", 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 });
|
|
3976
|
+
}
|
|
3977
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: FieldErrorsWrapperBase, decorators: [{
|
|
3978
|
+
type: Directive
|
|
3979
|
+
}], 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 }] }] } });
|
|
3980
|
+
function provideFieldErrorDisplay(wrapper) {
|
|
3981
|
+
return { provide: FIELD_ERROR_DISPLAY, useExisting: forwardRef(wrapper) };
|
|
3982
|
+
}
|
|
3983
|
+
|
|
3689
3984
|
|
|
3690
3985
|
|
|
3691
|
-
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, 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,
|
|
3986
|
+
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_COMPONENT_LOAD_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 };
|
|
3692
3987
|
//# sourceMappingURL=ng-forge-dynamic-forms-internal.mjs.map
|