@ng-forge/dynamic-forms 1.3.0-next.2 → 1.3.0-next.3
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/fesm2022/ng-forge-dynamic-forms-active-page-initialized.event-CiKN-mcc.mjs +12 -0
- package/fesm2022/ng-forge-dynamic-forms-active-page-initialized.event-CiKN-mcc.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-array-field.component-Dv9mPnJ3.mjs +770 -0
- package/fesm2022/ng-forge-dynamic-forms-array-field.component-Dv9mPnJ3.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-array-item-registry.service-D-AxVLdk.mjs +83 -0
- package/fesm2022/ng-forge-dynamic-forms-array-item-registry.service-D-AxVLdk.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-bootstrap-derivation-orchestrator-EuYCbquo.mjs +1887 -0
- package/fesm2022/ng-forge-dynamic-forms-bootstrap-derivation-orchestrator-EuYCbquo.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-bootstrap-web-mcp-2wQK_wPp.mjs +954 -0
- package/fesm2022/ng-forge-dynamic-forms-bootstrap-web-mcp-2wQK_wPp.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-container-field-processors-C_JRvaVt.mjs +117 -0
- package/fesm2022/ng-forge-dynamic-forms-container-field-processors-C_JRvaVt.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-container-field.component-Bg7Win9n.mjs +228 -0
- package/fesm2022/ng-forge-dynamic-forms-container-field.component-Bg7Win9n.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-css-wrapper.component-R2yc-H0T.mjs +102 -0
- package/fesm2022/ng-forge-dynamic-forms-css-wrapper.component-R2yc-H0T.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-debounce-CG3uP5B-.mjs +4 -0
- package/fesm2022/{ng-forge-dynamic-forms-debounce-C9F4v1Ke.mjs.map → ng-forge-dynamic-forms-debounce-CG3uP5B-.mjs.map} +1 -1
- package/fesm2022/ng-forge-dynamic-forms-default-value-D5M4MNE-.mjs +77 -0
- package/fesm2022/ng-forge-dynamic-forms-default-value-D5M4MNE-.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-dev-mode-4rbYBBo_.mjs +4 -0
- package/fesm2022/ng-forge-dynamic-forms-dev-mode-4rbYBBo_.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-df-field-outlet.directive-CQsDMV-s.mjs +644 -0
- package/fesm2022/ng-forge-dynamic-forms-df-field-outlet.directive-CQsDMV-s.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-field-errors-wrapper.component-DKgkpIpG.mjs +56 -0
- package/fesm2022/ng-forge-dynamic-forms-field-errors-wrapper.component-DKgkpIpG.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-form-schema.service-Dd-gHJ_7.mjs +38 -0
- package/fesm2022/{ng-forge-dynamic-forms-form-schema.service-Dx5Dlb15.mjs.map → ng-forge-dynamic-forms-form-schema.service-Dd-gHJ_7.mjs.map} +1 -1
- package/fesm2022/ng-forge-dynamic-forms-form-state-manager-DcOXRFRL.mjs +1522 -0
- package/fesm2022/ng-forge-dynamic-forms-form-state-manager-DcOXRFRL.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-group-field.component-BjZi0bhq.mjs +292 -0
- package/fesm2022/ng-forge-dynamic-forms-group-field.component-BjZi0bhq.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-integration.mjs +1318 -843
- package/fesm2022/ng-forge-dynamic-forms-integration.mjs.map +1 -1
- package/fesm2022/ng-forge-dynamic-forms-internal.mjs +3326 -3641
- package/fesm2022/ng-forge-dynamic-forms-internal.mjs.map +1 -1
- package/fesm2022/ng-forge-dynamic-forms-page-field.component-BRjQmWC9.mjs +295 -0
- package/fesm2022/ng-forge-dynamic-forms-page-field.component-BRjQmWC9.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-resolve-field-ByGa5cpo.mjs +329 -0
- package/fesm2022/ng-forge-dynamic-forms-resolve-field-ByGa5cpo.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-row-wrapper.component-CuFycQb-.mjs +81 -0
- package/fesm2022/ng-forge-dynamic-forms-row-wrapper.component-CuFycQb-.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-schema-builder-C62afItJ.mjs +400 -0
- package/fesm2022/ng-forge-dynamic-forms-schema-builder-C62afItJ.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-schema-registry.service-axBV9FBH.mjs +45 -0
- package/fesm2022/ng-forge-dynamic-forms-schema-registry.service-axBV9FBH.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-schema.mjs +8 -14
- package/fesm2022/ng-forge-dynamic-forms-schema.mjs.map +1 -1
- package/fesm2022/ng-forge-dynamic-forms-testing.mjs +68 -73
- package/fesm2022/ng-forge-dynamic-forms-testing.mjs.map +1 -1
- package/fesm2022/ng-forge-dynamic-forms-text-field.component--MAh_h4Q.mjs +257 -0
- package/fesm2022/ng-forge-dynamic-forms-text-field.component--MAh_h4Q.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-validation-execution.token-BFyySKtp.mjs +8 -0
- package/fesm2022/ng-forge-dynamic-forms-validation-execution.token-BFyySKtp.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-with-logger-config-BAATqYY0.mjs +94 -0
- package/fesm2022/ng-forge-dynamic-forms-with-logger-config-BAATqYY0.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-wrapper-chain-BnntfNU1.mjs +115 -0
- package/fesm2022/ng-forge-dynamic-forms-wrapper-chain-BnntfNU1.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms.mjs +2136 -3
- package/fesm2022/ng-forge-dynamic-forms.mjs.map +1 -1
- package/package.json +1 -1
- package/types/ng-forge-dynamic-forms-integration.d.ts +543 -415
- package/types/ng-forge-dynamic-forms-internal.d.ts +2319 -2436
- package/types/ng-forge-dynamic-forms-schema.d.ts +13 -16
- package/types/ng-forge-dynamic-forms-testing.d.ts +34 -37
- package/types/ng-forge-dynamic-forms.d.ts +735 -722
- package/fesm2022/ng-forge-dynamic-forms-array-field.component-CSCKq_1K.mjs +0 -750
- package/fesm2022/ng-forge-dynamic-forms-array-field.component-CSCKq_1K.mjs.map +0 -1
- package/fesm2022/ng-forge-dynamic-forms-bootstrap-derivation-orchestrator-CTOTwzzw.mjs +0 -2394
- package/fesm2022/ng-forge-dynamic-forms-bootstrap-derivation-orchestrator-CTOTwzzw.mjs.map +0 -1
- package/fesm2022/ng-forge-dynamic-forms-bootstrap-web-mcp-BtjqeJOj.mjs +0 -1054
- package/fesm2022/ng-forge-dynamic-forms-bootstrap-web-mcp-BtjqeJOj.mjs.map +0 -1
- package/fesm2022/ng-forge-dynamic-forms-container-field.component-Dc3ROhHL.mjs +0 -86
- package/fesm2022/ng-forge-dynamic-forms-container-field.component-Dc3ROhHL.mjs.map +0 -1
- package/fesm2022/ng-forge-dynamic-forms-css-wrapper.component-BzgX8lAD.mjs +0 -33
- package/fesm2022/ng-forge-dynamic-forms-css-wrapper.component-BzgX8lAD.mjs.map +0 -1
- package/fesm2022/ng-forge-dynamic-forms-debounce-C9F4v1Ke.mjs +0 -17
- package/fesm2022/ng-forge-dynamic-forms-field-errors-wrapper.component-CIKbWqYA.mjs +0 -25
- package/fesm2022/ng-forge-dynamic-forms-field-errors-wrapper.component-CIKbWqYA.mjs.map +0 -1
- package/fesm2022/ng-forge-dynamic-forms-form-schema.service-Dx5Dlb15.mjs +0 -24
- package/fesm2022/ng-forge-dynamic-forms-group-field.component-DAC3P9DC.mjs +0 -177
- package/fesm2022/ng-forge-dynamic-forms-group-field.component-DAC3P9DC.mjs.map +0 -1
- package/fesm2022/ng-forge-dynamic-forms-ng-forge-dynamic-forms-CXQe_5td.mjs +0 -5133
- package/fesm2022/ng-forge-dynamic-forms-ng-forge-dynamic-forms-CXQe_5td.mjs.map +0 -1
- package/fesm2022/ng-forge-dynamic-forms-page-field.component-DPKJcwUO.mjs +0 -176
- package/fesm2022/ng-forge-dynamic-forms-page-field.component-DPKJcwUO.mjs.map +0 -1
- package/fesm2022/ng-forge-dynamic-forms-row-wrapper.component-DMEeKZny.mjs +0 -19
- package/fesm2022/ng-forge-dynamic-forms-row-wrapper.component-DMEeKZny.mjs.map +0 -1
- package/fesm2022/ng-forge-dynamic-forms-schema-builder-BvDTzfdM.mjs +0 -570
- package/fesm2022/ng-forge-dynamic-forms-schema-builder-BvDTzfdM.mjs.map +0 -1
- package/fesm2022/ng-forge-dynamic-forms-text-field.component-BB-jutBq.mjs +0 -126
- package/fesm2022/ng-forge-dynamic-forms-text-field.component-BB-jutBq.mjs.map +0 -1
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, DestroyRef, Injector, EnvironmentInjector, input, computed, linkedSignal, runInInjectionContext, untracked, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
|
-
import { i as injectFieldRegistry, C as CONTAINER_FIELD_PROCESSORS, c as computeContainerHostClasses, a as createFieldResolutionPipe, s as setupContainerInitEffect, d as initializationComponentPath, D as DfFieldOutlet } from './ng-forge-dynamic-forms-ng-forge-dynamic-forms-CXQe_5td.mjs';
|
|
4
|
-
import { outputFromObservable, toObservable } from '@angular/core/rxjs-interop';
|
|
5
|
-
import { explicitEffect } from 'ngxtension/explicit-effect';
|
|
6
|
-
import { injectFieldSignalContext, GROUP_CONTEXT, EventBus, DynamicFormLogger, isEqual, FIELD_SIGNAL_CONTEXT, derivedFromDeferred } from '@ng-forge/dynamic-forms/internal';
|
|
7
|
-
import { form } from '@angular/forms/signals';
|
|
8
|
-
import { c as createSchemaFromFields } from './ng-forge-dynamic-forms-schema-builder-BvDTzfdM.mjs';
|
|
9
|
-
|
|
10
|
-
class GroupFieldComponent {
|
|
11
|
-
destroyRef = inject(DestroyRef);
|
|
12
|
-
fieldRegistry = injectFieldRegistry();
|
|
13
|
-
parentFieldSignalContext = injectFieldSignalContext();
|
|
14
|
-
parentGroupContext = inject(GROUP_CONTEXT, { optional: true });
|
|
15
|
-
injector = inject(Injector);
|
|
16
|
-
environmentInjector = inject(EnvironmentInjector);
|
|
17
|
-
eventBus = inject(EventBus);
|
|
18
|
-
logger = inject(DynamicFormLogger);
|
|
19
|
-
fieldProcessors = inject(CONTAINER_FIELD_PROCESSORS);
|
|
20
|
-
field = input.required(/* @ts-ignore */
|
|
21
|
-
...(ngDevMode ? [{ debugName: "field" }] : /* istanbul ignore next */ []));
|
|
22
|
-
key = input.required(/* @ts-ignore */
|
|
23
|
-
...(ngDevMode ? [{ debugName: "key" }] : /* istanbul ignore next */ []));
|
|
24
|
-
className = input(/* @ts-ignore */
|
|
25
|
-
...(ngDevMode ? [undefined, { debugName: "className" }] : /* istanbul ignore next */ []));
|
|
26
|
-
hidden = input(false, /* @ts-ignore */
|
|
27
|
-
...(ngDevMode ? [{ debugName: "hidden" }] : /* istanbul ignore next */ []));
|
|
28
|
-
hostClasses = computed(() => computeContainerHostClasses('group', this.className()), /* @ts-ignore */
|
|
29
|
-
...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
30
|
-
rawFieldRegistry = computed(() => this.fieldRegistry.raw, /* @ts-ignore */
|
|
31
|
-
...(ngDevMode ? [{ debugName: "rawFieldRegistry" }] : /* istanbul ignore next */ []));
|
|
32
|
-
formSetup = computed(() => {
|
|
33
|
-
const groupField = this.field();
|
|
34
|
-
const registry = this.rawFieldRegistry();
|
|
35
|
-
if (groupField.fields && groupField.fields.length > 0) {
|
|
36
|
-
const flattenedFields = this.fieldProcessors.memoizedFlattenFields(groupField.fields, registry);
|
|
37
|
-
const flattenedFieldsForRendering = this.fieldProcessors.memoizedFlattenFieldsForRendering(groupField.fields, registry);
|
|
38
|
-
const fieldsById = this.fieldProcessors.memoizedKeyBy(flattenedFields);
|
|
39
|
-
const defaultValues = this.fieldProcessors.memoizedDefaultValues(fieldsById, registry);
|
|
40
|
-
return {
|
|
41
|
-
fields: flattenedFieldsForRendering,
|
|
42
|
-
schemaFields: flattenedFields,
|
|
43
|
-
originalFields: groupField.fields,
|
|
44
|
-
defaultValues,
|
|
45
|
-
registry,
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
return {
|
|
49
|
-
fields: [],
|
|
50
|
-
schemaFields: [],
|
|
51
|
-
originalFields: [],
|
|
52
|
-
defaultValues: {},
|
|
53
|
-
registry,
|
|
54
|
-
};
|
|
55
|
-
}, /* @ts-ignore */
|
|
56
|
-
...(ngDevMode ? [{ debugName: "formSetup" }] : /* istanbul ignore next */ []));
|
|
57
|
-
defaultValues = linkedSignal(() => this.formSetup().defaultValues, /* @ts-ignore */
|
|
58
|
-
...(ngDevMode ? [{ debugName: "defaultValues" }] : /* istanbul ignore next */ []));
|
|
59
|
-
entity = linkedSignal(() => {
|
|
60
|
-
const parentValue = this.parentFieldSignalContext.value();
|
|
61
|
-
const groupKey = this.field().key;
|
|
62
|
-
const defaults = this.defaultValues();
|
|
63
|
-
const groupValue = parentValue?.[groupKey] || {};
|
|
64
|
-
return { ...defaults, ...groupValue };
|
|
65
|
-
}, {
|
|
66
|
-
debugName: 'GroupFieldComponent.entity',
|
|
67
|
-
equal: isEqual,
|
|
68
|
-
});
|
|
69
|
-
form = computed(() => {
|
|
70
|
-
return runInInjectionContext(this.injector, () => {
|
|
71
|
-
const setup = this.formSetup();
|
|
72
|
-
if (setup.schemaFields.length > 0) {
|
|
73
|
-
const schema = createSchemaFromFields(setup.schemaFields, setup.registry);
|
|
74
|
-
return untracked(() => form(this.entity, schema));
|
|
75
|
-
}
|
|
76
|
-
return untracked(() => form(this.entity));
|
|
77
|
-
});
|
|
78
|
-
}, /* @ts-ignore */
|
|
79
|
-
...(ngDevMode ? [{ debugName: "form" }] : /* istanbul ignore next */ []));
|
|
80
|
-
formValue = computed(() => this.entity(), /* @ts-ignore */
|
|
81
|
-
...(ngDevMode ? [{ debugName: "formValue" }] : /* istanbul ignore next */ []));
|
|
82
|
-
valid = computed(() => this.form()().valid(), /* @ts-ignore */
|
|
83
|
-
...(ngDevMode ? [{ debugName: "valid" }] : /* istanbul ignore next */ []));
|
|
84
|
-
invalid = computed(() => this.form()().invalid(), /* @ts-ignore */
|
|
85
|
-
...(ngDevMode ? [{ debugName: "invalid" }] : /* istanbul ignore next */ []));
|
|
86
|
-
dirty = computed(() => this.form()().dirty(), /* @ts-ignore */
|
|
87
|
-
...(ngDevMode ? [{ debugName: "dirty" }] : /* istanbul ignore next */ []));
|
|
88
|
-
touched = computed(() => this.form()().touched(), /* @ts-ignore */
|
|
89
|
-
...(ngDevMode ? [{ debugName: "touched" }] : /* istanbul ignore next */ []));
|
|
90
|
-
errors = computed(() => this.form()().errors(), /* @ts-ignore */
|
|
91
|
-
...(ngDevMode ? [{ debugName: "errors" }] : /* istanbul ignore next */ []));
|
|
92
|
-
disabled = computed(() => this.form()().disabled(), /* @ts-ignore */
|
|
93
|
-
...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
94
|
-
nestedFieldTree = computed(() => {
|
|
95
|
-
const parentForm = this.parentFieldSignalContext.form;
|
|
96
|
-
const groupKey = this.field().key;
|
|
97
|
-
return parentForm[groupKey];
|
|
98
|
-
}, /* @ts-ignore */
|
|
99
|
-
...(ngDevMode ? [{ debugName: "nestedFieldTree" }] : /* istanbul ignore next */ []));
|
|
100
|
-
groupFieldSignalContext = (() => {
|
|
101
|
-
const nestedFieldTree = this.nestedFieldTree;
|
|
102
|
-
return {
|
|
103
|
-
injector: this.injector,
|
|
104
|
-
value: this.parentFieldSignalContext.value,
|
|
105
|
-
defaultValues: this.defaultValues,
|
|
106
|
-
get form() {
|
|
107
|
-
return nestedFieldTree() ?? {};
|
|
108
|
-
},
|
|
109
|
-
};
|
|
110
|
-
})();
|
|
111
|
-
groupContext = {
|
|
112
|
-
groupPath: computed(() => {
|
|
113
|
-
const ownKey = this.field().key;
|
|
114
|
-
const parentPath = this.parentGroupContext?.groupPath();
|
|
115
|
-
return parentPath ? `${parentPath}.${ownKey}` : ownKey;
|
|
116
|
-
}),
|
|
117
|
-
};
|
|
118
|
-
groupInjector = Injector.create({
|
|
119
|
-
parent: this.injector,
|
|
120
|
-
providers: [
|
|
121
|
-
{ provide: FIELD_SIGNAL_CONTEXT, useValue: this.groupFieldSignalContext },
|
|
122
|
-
{ provide: GROUP_CONTEXT, useValue: this.groupContext },
|
|
123
|
-
],
|
|
124
|
-
});
|
|
125
|
-
validityChange = outputFromObservable(toObservable(this.valid));
|
|
126
|
-
dirtyChange = outputFromObservable(toObservable(this.dirty));
|
|
127
|
-
submitted = outputFromObservable(this.eventBus.on('submit'));
|
|
128
|
-
fieldsSource = computed(() => this.formSetup().fields, /* @ts-ignore */
|
|
129
|
-
...(ngDevMode ? [{ debugName: "fieldsSource" }] : /* istanbul ignore next */ []));
|
|
130
|
-
resolvedFields = derivedFromDeferred(this.fieldsSource, createFieldResolutionPipe(() => ({
|
|
131
|
-
loadTypeComponent: (type) => this.fieldRegistry.loadTypeComponent(type),
|
|
132
|
-
registry: this.rawFieldRegistry(),
|
|
133
|
-
injector: this.groupInjector,
|
|
134
|
-
destroyRef: this.destroyRef,
|
|
135
|
-
onError: (fieldDef, error) => {
|
|
136
|
-
const fieldKey = fieldDef.key || '<no key>';
|
|
137
|
-
this.logger.error(`Failed to load component for field type '${fieldDef.type}' (key: ${fieldKey}) ` +
|
|
138
|
-
`within group '${this.field().key}'. Ensure the field type is registered in your field registry.`, error);
|
|
139
|
-
},
|
|
140
|
-
})), { initialValue: [], injector: this.injector });
|
|
141
|
-
constructor() {
|
|
142
|
-
this.setupEffects();
|
|
143
|
-
}
|
|
144
|
-
setupEffects() {
|
|
145
|
-
setupContainerInitEffect(this.resolvedFields, this.eventBus, 'group', () => initializationComponentPath(this.field().key, this.parentGroupContext?.groupPath()), this.injector);
|
|
146
|
-
explicitEffect([this.nestedFieldTree, this.field], ([tree, field]) => {
|
|
147
|
-
if (!tree) {
|
|
148
|
-
this.logger.warn(`Group field "${field.key}" not found in parent form. ` + `Ensure the parent form schema includes this group field.`);
|
|
149
|
-
}
|
|
150
|
-
}, { defer: true });
|
|
151
|
-
}
|
|
152
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: GroupFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
153
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: GroupFieldComponent, isStandalone: true, selector: "fieldset[group-field]", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: true, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, hidden: { classPropertyName: "hidden", publicName: "hidden", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { validityChange: "validityChange", dirtyChange: "dirtyChange", submitted: "submitted" }, host: { attributes: { "role": "group" }, properties: { "class": "hostClasses()", "class.disabled": "disabled()", "class.df-container-hidden": "hidden()", "attr.aria-hidden": "hidden() || null", "id": "`${key()}`", "attr.data-testid": "key()" } }, ngImport: i0, template: `
|
|
154
|
-
@for (field of resolvedFields(); track field.key) {
|
|
155
|
-
<ng-container *dfFieldOutlet="field; environmentInjector: environmentInjector" />
|
|
156
|
-
}
|
|
157
|
-
`, isInline: true, styles: [".df-form{display:grid;grid-template-columns:1fr;gap:var(--df-grid-row-gap, .5rem);width:100%}.df-form>*{grid-column:1/-1}.df-row{display:grid;grid-template-columns:repeat(var(--df-grid-columns, 12),1fr);gap:var(--df-grid-gap, .5rem);align-items:start;width:100%}.df-row>*:not([class*=df-col-]){grid-column:1/-1}.df-col-1{grid-column:span 1}.df-col-2{grid-column:span 2}.df-col-3{grid-column:span 3}.df-col-4{grid-column:span 4}.df-col-5{grid-column:span 5}.df-col-6{grid-column:span 6}.df-col-7{grid-column:span 7}.df-col-8{grid-column:span 8}.df-col-9{grid-column:span 9}.df-col-10{grid-column:span 10}.df-col-11{grid-column:span 11}.df-col-12{grid-column:span 12}.df-col-auto{grid-column:span auto;width:auto}.df-col-full{grid-column:1/-1}.df-col-start-1{grid-column-start:1}.df-col-start-2{grid-column-start:2}.df-col-start-3{grid-column-start:3}.df-col-start-4{grid-column-start:4}.df-col-start-5{grid-column-start:5}.df-col-start-6{grid-column-start:6}.df-col-start-7{grid-column-start:7}.df-col-start-8{grid-column-start:8}.df-col-start-9{grid-column-start:9}.df-col-start-10{grid-column-start:10}.df-col-start-11{grid-column-start:11}.df-col-start-12{grid-column-start:12}.df-col-end-1{grid-column-end:1}.df-col-end-2{grid-column-end:2}.df-col-end-3{grid-column-end:3}.df-col-end-4{grid-column-end:4}.df-col-end-5{grid-column-end:5}.df-col-end-6{grid-column-end:6}.df-col-end-7{grid-column-end:7}.df-col-end-8{grid-column-end:8}.df-col-end-9{grid-column-end:9}.df-col-end-10{grid-column-end:10}.df-col-end-11{grid-column-end:11}.df-col-end-12{grid-column-end:12}.df-col-end-13{grid-column-end:13}@media(max-width:576px){.df-form{--df-grid-gap: var(--df-grid-gap-sm, .5rem);--df-grid-row-gap: var(--df-grid-row-gap-sm, .5rem)}.df-row{grid-template-columns:1fr}.df-row>*{grid-column:1/-1!important}.df-row.df-row-mobile-keep-cols{grid-template-columns:repeat(var(--df-grid-columns, 12),1fr)}.df-row.df-row-mobile-keep-cols>*{grid-column:revert!important}}@media(min-width:577px)and (max-width:768px){.df-form{--df-grid-gap: var(--df-grid-gap-md, .5rem);--df-grid-row-gap: var(--df-grid-row-gap-md, .5rem)}.df-row{--df-grid-columns: 6}.df-col-sm-1{grid-column:span 1}.df-col-sm-2{grid-column:span 2}.df-col-sm-3{grid-column:span 3}.df-col-sm-4{grid-column:span 4}.df-col-sm-5{grid-column:span 5}.df-col-sm-6{grid-column:span 6}.df-col-sm-full{grid-column:1/-1}}@media(min-width:769px)and (max-width:992px){.df-form{--df-grid-gap: var(--df-grid-gap-lg, .5rem);--df-grid-row-gap: var(--df-grid-row-gap-lg, .5rem)}.df-col-md-1{grid-column:span 1}.df-col-md-2{grid-column:span 2}.df-col-md-3{grid-column:span 3}.df-col-md-4{grid-column:span 4}.df-col-md-5{grid-column:span 5}.df-col-md-6{grid-column:span 6}.df-col-md-7{grid-column:span 7}.df-col-md-8{grid-column:span 8}.df-col-md-9{grid-column:span 9}.df-col-md-10{grid-column:span 10}.df-col-md-11{grid-column:span 11}.df-col-md-12{grid-column:span 12}.df-col-md-full{grid-column:1/-1}}@media(min-width:993px){.df-form{--df-grid-gap: var(--df-grid-gap-xl, .5rem);--df-grid-row-gap: var(--df-grid-row-gap-xl, .5rem)}.df-col-lg-1{grid-column:span 1}.df-col-lg-2{grid-column:span 2}.df-col-lg-3{grid-column:span 3}.df-col-lg-4{grid-column:span 4}.df-col-lg-5{grid-column:span 5}.df-col-lg-6{grid-column:span 6}.df-col-lg-7{grid-column:span 7}.df-col-lg-8{grid-column:span 8}.df-col-lg-9{grid-column:span 9}.df-col-lg-10{grid-column:span 10}.df-col-lg-11{grid-column:span 11}.df-col-lg-12{grid-column:span 12}.df-col-lg-full{grid-column:1/-1}}.df-gap-none{--df-grid-gap: 0}.df-gap-xs{--df-grid-gap: .25rem}.df-gap-sm{--df-grid-gap: .5rem}.df-gap-md{--df-grid-gap: 1rem}.df-gap-lg{--df-grid-gap: 1.5rem}.df-gap-xl{--df-grid-gap: 2rem}.df-row-gap-none{--df-grid-row-gap: 0}.df-row-gap-xs{--df-grid-row-gap: .25rem}.df-row-gap-sm{--df-grid-row-gap: .5rem}.df-row-gap-md{--df-grid-row-gap: 1rem}.df-row-gap-lg{--df-grid-row-gap: 1.5rem}.df-row-gap-xl{--df-grid-row-gap: 2rem}.df-field{display:block;width:100%;min-width:0;overflow:hidden;margin:0}.df-group,.df-page{display:block;width:100%}.df-form.disabled,.df-row.disabled,.df-field.disabled{opacity:.6;pointer-events:none}.df-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.df-sr-only-focusable:focus,.df-sr-only-focusable:active{position:static;width:auto;height:auto;padding:inherit;margin:inherit;overflow:visible;clip:auto;white-space:normal}.df-live-region{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.df-form :focus-visible{outline:2px solid var(--df-focus-color, #005fcc);outline-offset:2px}.df-group:focus-within{outline:1px dashed var(--df-focus-color, #005fcc);outline-offset:4px}:host{border:none;margin:0;padding:0;min-width:0;display:grid;grid-template-columns:1fr;gap:var(--df-grid-row-gap, .5rem);width:100%}:host>*{grid-column:1/-1}:host.df-container-hidden{display:none}\n"], dependencies: [{ kind: "directive", type: DfFieldOutlet, selector: "[dfFieldOutlet]", inputs: ["dfFieldOutlet", "dfFieldOutletEnvironmentInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
158
|
-
}
|
|
159
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: GroupFieldComponent, decorators: [{
|
|
160
|
-
type: Component,
|
|
161
|
-
args: [{ selector: 'fieldset[group-field]', imports: [DfFieldOutlet], template: `
|
|
162
|
-
@for (field of resolvedFields(); track field.key) {
|
|
163
|
-
<ng-container *dfFieldOutlet="field; environmentInjector: environmentInjector" />
|
|
164
|
-
}
|
|
165
|
-
`, host: {
|
|
166
|
-
'[class]': 'hostClasses()',
|
|
167
|
-
role: 'group',
|
|
168
|
-
'[class.disabled]': 'disabled()',
|
|
169
|
-
'[class.df-container-hidden]': 'hidden()',
|
|
170
|
-
'[attr.aria-hidden]': 'hidden() || null',
|
|
171
|
-
'[id]': '`${key()}`',
|
|
172
|
-
'[attr.data-testid]': 'key()',
|
|
173
|
-
}, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".df-form{display:grid;grid-template-columns:1fr;gap:var(--df-grid-row-gap, .5rem);width:100%}.df-form>*{grid-column:1/-1}.df-row{display:grid;grid-template-columns:repeat(var(--df-grid-columns, 12),1fr);gap:var(--df-grid-gap, .5rem);align-items:start;width:100%}.df-row>*:not([class*=df-col-]){grid-column:1/-1}.df-col-1{grid-column:span 1}.df-col-2{grid-column:span 2}.df-col-3{grid-column:span 3}.df-col-4{grid-column:span 4}.df-col-5{grid-column:span 5}.df-col-6{grid-column:span 6}.df-col-7{grid-column:span 7}.df-col-8{grid-column:span 8}.df-col-9{grid-column:span 9}.df-col-10{grid-column:span 10}.df-col-11{grid-column:span 11}.df-col-12{grid-column:span 12}.df-col-auto{grid-column:span auto;width:auto}.df-col-full{grid-column:1/-1}.df-col-start-1{grid-column-start:1}.df-col-start-2{grid-column-start:2}.df-col-start-3{grid-column-start:3}.df-col-start-4{grid-column-start:4}.df-col-start-5{grid-column-start:5}.df-col-start-6{grid-column-start:6}.df-col-start-7{grid-column-start:7}.df-col-start-8{grid-column-start:8}.df-col-start-9{grid-column-start:9}.df-col-start-10{grid-column-start:10}.df-col-start-11{grid-column-start:11}.df-col-start-12{grid-column-start:12}.df-col-end-1{grid-column-end:1}.df-col-end-2{grid-column-end:2}.df-col-end-3{grid-column-end:3}.df-col-end-4{grid-column-end:4}.df-col-end-5{grid-column-end:5}.df-col-end-6{grid-column-end:6}.df-col-end-7{grid-column-end:7}.df-col-end-8{grid-column-end:8}.df-col-end-9{grid-column-end:9}.df-col-end-10{grid-column-end:10}.df-col-end-11{grid-column-end:11}.df-col-end-12{grid-column-end:12}.df-col-end-13{grid-column-end:13}@media(max-width:576px){.df-form{--df-grid-gap: var(--df-grid-gap-sm, .5rem);--df-grid-row-gap: var(--df-grid-row-gap-sm, .5rem)}.df-row{grid-template-columns:1fr}.df-row>*{grid-column:1/-1!important}.df-row.df-row-mobile-keep-cols{grid-template-columns:repeat(var(--df-grid-columns, 12),1fr)}.df-row.df-row-mobile-keep-cols>*{grid-column:revert!important}}@media(min-width:577px)and (max-width:768px){.df-form{--df-grid-gap: var(--df-grid-gap-md, .5rem);--df-grid-row-gap: var(--df-grid-row-gap-md, .5rem)}.df-row{--df-grid-columns: 6}.df-col-sm-1{grid-column:span 1}.df-col-sm-2{grid-column:span 2}.df-col-sm-3{grid-column:span 3}.df-col-sm-4{grid-column:span 4}.df-col-sm-5{grid-column:span 5}.df-col-sm-6{grid-column:span 6}.df-col-sm-full{grid-column:1/-1}}@media(min-width:769px)and (max-width:992px){.df-form{--df-grid-gap: var(--df-grid-gap-lg, .5rem);--df-grid-row-gap: var(--df-grid-row-gap-lg, .5rem)}.df-col-md-1{grid-column:span 1}.df-col-md-2{grid-column:span 2}.df-col-md-3{grid-column:span 3}.df-col-md-4{grid-column:span 4}.df-col-md-5{grid-column:span 5}.df-col-md-6{grid-column:span 6}.df-col-md-7{grid-column:span 7}.df-col-md-8{grid-column:span 8}.df-col-md-9{grid-column:span 9}.df-col-md-10{grid-column:span 10}.df-col-md-11{grid-column:span 11}.df-col-md-12{grid-column:span 12}.df-col-md-full{grid-column:1/-1}}@media(min-width:993px){.df-form{--df-grid-gap: var(--df-grid-gap-xl, .5rem);--df-grid-row-gap: var(--df-grid-row-gap-xl, .5rem)}.df-col-lg-1{grid-column:span 1}.df-col-lg-2{grid-column:span 2}.df-col-lg-3{grid-column:span 3}.df-col-lg-4{grid-column:span 4}.df-col-lg-5{grid-column:span 5}.df-col-lg-6{grid-column:span 6}.df-col-lg-7{grid-column:span 7}.df-col-lg-8{grid-column:span 8}.df-col-lg-9{grid-column:span 9}.df-col-lg-10{grid-column:span 10}.df-col-lg-11{grid-column:span 11}.df-col-lg-12{grid-column:span 12}.df-col-lg-full{grid-column:1/-1}}.df-gap-none{--df-grid-gap: 0}.df-gap-xs{--df-grid-gap: .25rem}.df-gap-sm{--df-grid-gap: .5rem}.df-gap-md{--df-grid-gap: 1rem}.df-gap-lg{--df-grid-gap: 1.5rem}.df-gap-xl{--df-grid-gap: 2rem}.df-row-gap-none{--df-grid-row-gap: 0}.df-row-gap-xs{--df-grid-row-gap: .25rem}.df-row-gap-sm{--df-grid-row-gap: .5rem}.df-row-gap-md{--df-grid-row-gap: 1rem}.df-row-gap-lg{--df-grid-row-gap: 1.5rem}.df-row-gap-xl{--df-grid-row-gap: 2rem}.df-field{display:block;width:100%;min-width:0;overflow:hidden;margin:0}.df-group,.df-page{display:block;width:100%}.df-form.disabled,.df-row.disabled,.df-field.disabled{opacity:.6;pointer-events:none}.df-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.df-sr-only-focusable:focus,.df-sr-only-focusable:active{position:static;width:auto;height:auto;padding:inherit;margin:inherit;overflow:visible;clip:auto;white-space:normal}.df-live-region{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.df-form :focus-visible{outline:2px solid var(--df-focus-color, #005fcc);outline-offset:2px}.df-group:focus-within{outline:1px dashed var(--df-focus-color, #005fcc);outline-offset:4px}:host{border:none;margin:0;padding:0;min-width:0;display:grid;grid-template-columns:1fr;gap:var(--df-grid-row-gap, .5rem);width:100%}:host>*{grid-column:1/-1}:host.df-container-hidden{display:none}\n"] }]
|
|
174
|
-
}], 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"] }] } });
|
|
175
|
-
|
|
176
|
-
export { GroupFieldComponent, GroupFieldComponent as default };
|
|
177
|
-
//# sourceMappingURL=ng-forge-dynamic-forms-group-field.component-DAC3P9DC.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ng-forge-dynamic-forms-group-field.component-DAC3P9DC.mjs","mappings":";;;;;;;;;AA4Dc;YAKK;;;;AAIA;AACE;AACF;AACA;YAMA;;;;;AAQjB;;;;YAOS;;;;AAIQ;AACf;AACA;AAEA;AACE;AACA;;AAEA;;AAGE;AACA;;;;;;;AAQF;AACA;AACA;AACA;;;;;;;AAOJ,IAKiB;;;AAIb;;AAEA;AACF;AAEE;AACA;AACD;AAGc;AACf;AACE;;AAGE;AACA;;AAGF;AACF;;;;;AAQO;;AACA;;AACA;;AACA;;AACA;;AACA;;AAEQ;AACf;;AAEA;;;;AAIA;;;AAGE;;AAEA;AACE;;;;AAKN,IAMiB;AACf;;;AAGE;AACF;;AAGe;;AAEf;;;AAGC;AACF;;;AAQQ;;;AAQU;AAGf;AACA;;;AAGA;AACE;;;;AAOH;YAQH;;;;AASE;AAQA;;AAIM;;AAIJ;;;AArNe;;;;AAhBlB;;;;AANS;;;;;AASR;AACA;AACA;AACA;AACA;wEAIA;AACA","names":[],"ignoreList":[],"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/df-field-outlet.directive';\nimport { outputFromObservable, toObservable } from '@angular/core/rxjs-interop';\nimport { explicitEffect } from 'ngxtension/explicit-effect';\nimport { derivedFromDeferred } from '@ng-forge/dynamic-forms/internal';\nimport { createFieldResolutionPipe, ResolvedField } from '../../utils/resolve-field/resolve-field';\nimport {\n computeContainerHostClasses,\n initializationComponentPath,\n setupContainerInitEffect,\n} from '../../utils/container-utils/container-utils';\nimport { CONTAINER_FIELD_PROCESSORS } from '../../utils/container-utils/container-field-processors';\nimport { isEqual } from '@ng-forge/dynamic-forms/internal';\nimport { DynamicFormLogger } from '@ng-forge/dynamic-forms/internal';\nimport { GroupField } from '@ng-forge/dynamic-forms/internal';\nimport { injectFieldRegistry } from '../../utils/inject-field-registry/inject-field-registry';\nimport { FieldTree, form } from '@angular/forms/signals';\nimport { FieldDef } from '@ng-forge/dynamic-forms/internal';\nimport { FieldSignalContext, GroupContext } from '@ng-forge/dynamic-forms/internal';\nimport { FIELD_SIGNAL_CONTEXT, GROUP_CONTEXT, injectFieldSignalContext } from '@ng-forge/dynamic-forms/internal';\nimport { createSchemaFromFields } from '../../core/schema-builder';\nimport { EventBus } from '@ng-forge/dynamic-forms/internal';\nimport { FormSubmitEvent } from '../../events/constants/submit.event';\n\n/** Container component for rendering nested form groups. */\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 // The group element's own id is the plain `key()` — only its DESCENDANTS\n // compose scoped ids via GROUP_CONTEXT (e.g. children of an `address`\n // group render as `address_street`). The group selector is `#address`.\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 = injectFieldSignalContext<TModel>();\n private readonly parentGroupContext = inject(GROUP_CONTEXT, { optional: true });\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 /**\n * Group context propagated to descendants — carries the dot-separated path of\n * group ancestors so child fields can scope their DOM IDs (issue #401).\n * Reactive via `computed()`: a nested group composes its path from the parent\n * context signal + its own key, so the chain stays consistent if either changes.\n */\n private readonly groupContext: GroupContext = {\n groupPath: computed(() => {\n const ownKey = this.field().key;\n const parentPath = this.parentGroupContext?.groupPath();\n return parentPath ? `${parentPath}.${ownKey}` : ownKey;\n }),\n };\n\n private readonly groupInjector = Injector.create({\n parent: this.injector,\n providers: [\n { provide: FIELD_SIGNAL_CONTEXT, useValue: this.groupFieldSignalContext },\n { provide: GROUP_CONTEXT, useValue: this.groupContext },\n ],\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<FormSubmitEvent>('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(\n this.resolvedFields,\n this.eventBus,\n 'group',\n () => initializationComponentPath(this.field().key, this.parentGroupContext?.groupPath()),\n this.injector,\n );\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"]}
|