@stemy/ngx-dynamic-form 19.9.21 → 19.9.23
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/stemy-ngx-dynamic-form.mjs +54 -31
- package/fesm2022/stemy-ngx-dynamic-form.mjs.map +1 -1
- package/ngx-dynamic-form/common-types.d.ts +28 -0
- package/ngx-dynamic-form/components/dynamic-form-group/dynamic-form-group.component.d.ts +1 -0
- package/ngx-dynamic-form/services/dynamic-form-schema.service.d.ts +1 -0
- package/ngx-dynamic-form/utils/internal.d.ts +0 -1
- package/package.json +2 -2
|
@@ -592,20 +592,6 @@ function arrayItemActionToExpression(actionName) {
|
|
|
592
592
|
: true;
|
|
593
593
|
};
|
|
594
594
|
}
|
|
595
|
-
function mergeFormFields(formFields) {
|
|
596
|
-
const res = [];
|
|
597
|
-
for (const formModel of formFields) {
|
|
598
|
-
for (const subModel of formModel) {
|
|
599
|
-
const index = res.findIndex(t => t.key == subModel.key);
|
|
600
|
-
if (index >= 0) {
|
|
601
|
-
res[index] = subModel;
|
|
602
|
-
continue;
|
|
603
|
-
}
|
|
604
|
-
res.push(subModel);
|
|
605
|
-
}
|
|
606
|
-
}
|
|
607
|
-
return res;
|
|
608
|
-
}
|
|
609
595
|
function getFormValidationErrors(controls, parentPath = "") {
|
|
610
596
|
const errors = [];
|
|
611
597
|
Object.entries(controls).forEach(([name, control], ix) => {
|
|
@@ -671,6 +657,7 @@ class DynamicFormBuilderService {
|
|
|
671
657
|
return this.setExpressions({
|
|
672
658
|
id,
|
|
673
659
|
parent,
|
|
660
|
+
schemas: [],
|
|
674
661
|
fieldGroup: fields,
|
|
675
662
|
wrappers: ["form-fieldset"],
|
|
676
663
|
props: {
|
|
@@ -791,7 +778,7 @@ class DynamicFormBuilderService {
|
|
|
791
778
|
const root = target.formControl.root;
|
|
792
779
|
setFieldProp(target, "options", options instanceof Observable
|
|
793
780
|
? options
|
|
794
|
-
: controlValues(root).pipe(combineLatestWith(this.language), switchMap(async () => {
|
|
781
|
+
: controlValues(root).pipe(combineLatestWith(this.language), switchMap(async (a, b) => {
|
|
795
782
|
const results = await factory(target, this.injector) || [];
|
|
796
783
|
return this.fixSelectOptions(target, results);
|
|
797
784
|
})));
|
|
@@ -948,7 +935,7 @@ class DynamicFormBuilderService {
|
|
|
948
935
|
}
|
|
949
936
|
if (options.length === 0 || options.findIndex(o => o.value === control.value) >= 0)
|
|
950
937
|
return options;
|
|
951
|
-
control.setValue(
|
|
938
|
+
control.setValue(options[0].value);
|
|
952
939
|
return options;
|
|
953
940
|
}
|
|
954
941
|
isFieldset(field) {
|
|
@@ -994,6 +981,8 @@ class DynamicFormBuilderService {
|
|
|
994
981
|
prefixTemplateKey: String(data.prefixTemplateKey || ""),
|
|
995
982
|
suffixTemplateKey: String(data.suffixTemplateKey || ""),
|
|
996
983
|
purposes: toStringArray(data.purposes),
|
|
984
|
+
schemas: toStringArray(data.schemas),
|
|
985
|
+
discriminator: data.discriminator,
|
|
997
986
|
priority: isNaN(data.priority) ? Number.MAX_SAFE_INTEGER : Number(data.priority),
|
|
998
987
|
wrappers: wrappers.filter(ObjectUtils.isDefined),
|
|
999
988
|
type: data.componentType || type,
|
|
@@ -1116,6 +1105,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.19", ngImpo
|
|
|
1116
1105
|
args: [DEFAULT_NUMERIC_STEP]
|
|
1117
1106
|
}] }] });
|
|
1118
1107
|
|
|
1108
|
+
const PRIORITY_DIFF = 20;
|
|
1119
1109
|
class DynamicFormSchemaService {
|
|
1120
1110
|
openApi;
|
|
1121
1111
|
injector;
|
|
@@ -1141,13 +1131,37 @@ class DynamicFormSchemaService {
|
|
|
1141
1131
|
const keys = Object.keys(schema.properties || {});
|
|
1142
1132
|
const fields = [];
|
|
1143
1133
|
// Collect all properties of this schema def
|
|
1134
|
+
let priority = Number.MAX_SAFE_INTEGER - (keys.length * PRIORITY_DIFF);
|
|
1144
1135
|
for (const key of keys) {
|
|
1145
1136
|
const property = schema.properties[key];
|
|
1137
|
+
// Property priority is necessary when merging different schemas
|
|
1138
|
+
property.priority = property.priority ?? (priority += PRIORITY_DIFF);
|
|
1139
|
+
// Generate sub-fields for property
|
|
1146
1140
|
const propFields = await this.getFormFieldsForProp(property, schema, options, parent);
|
|
1147
1141
|
fields.push(...propFields);
|
|
1148
1142
|
}
|
|
1149
1143
|
return this.builder.createFieldSets(fields.filter(f => null !== f), parent, options, schema.sets || []);
|
|
1150
1144
|
}
|
|
1145
|
+
async getFormFieldsForRefs(subSchemas, parent, options) {
|
|
1146
|
+
const subFields = await Promise.all(subSchemas.map(async (s) => this.getFormFieldsForSchema(s, parent, options)));
|
|
1147
|
+
const res = [];
|
|
1148
|
+
for (const ix in subSchemas) {
|
|
1149
|
+
const schema = subSchemas[ix];
|
|
1150
|
+
const fields = subFields[ix];
|
|
1151
|
+
for (const field of fields) {
|
|
1152
|
+
const index = field.key
|
|
1153
|
+
? res.findIndex(t => t.key === field.key)
|
|
1154
|
+
: res.findIndex(t => t.id === field.id);
|
|
1155
|
+
if (index >= 0) {
|
|
1156
|
+
res[index].schemas.push(schema.name);
|
|
1157
|
+
continue;
|
|
1158
|
+
}
|
|
1159
|
+
field.schemas.push(schema.name);
|
|
1160
|
+
res.push(field);
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1163
|
+
return this.builder.createFieldSets(res, parent, options);
|
|
1164
|
+
}
|
|
1151
1165
|
async getFormFieldsForProp(property, schema, options, parent) {
|
|
1152
1166
|
const field = await this.getFormFieldForProp(property, options, parent);
|
|
1153
1167
|
return !field ? [] : options.customize(field, property, schema);
|
|
@@ -1161,16 +1175,16 @@ class DynamicFormSchemaService {
|
|
|
1161
1175
|
return this.getFormUploadConfig(property, options, parent);
|
|
1162
1176
|
case "boolean":
|
|
1163
1177
|
return this.getFormCheckboxConfig(property, options, parent);
|
|
1164
|
-
case "array":
|
|
1165
|
-
return this.getFormArrayConfig(property, options, parent);
|
|
1166
1178
|
}
|
|
1167
1179
|
const $enum = property.items?.enum || property.enum;
|
|
1168
1180
|
if (Array.isArray($enum) || ObjectUtils.isStringWithValue(property.optionsPath) || ObjectUtils.isStringWithValue(property.endpoint)) {
|
|
1181
|
+
// Handle select after boolean, because there could be a boolean field, with a strict enum [true] for validation
|
|
1169
1182
|
return this.getFormSelectConfig($enum, property, options, parent);
|
|
1170
1183
|
}
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1184
|
+
if (property.type === "array") {
|
|
1185
|
+
// Handle array after select, because there are also multi select fields
|
|
1186
|
+
return this.getFormArrayConfig(property, options, parent);
|
|
1187
|
+
}
|
|
1174
1188
|
if (property.format == "file" || property.format == "upload") {
|
|
1175
1189
|
return this.getFormUploadConfig(property, options, parent);
|
|
1176
1190
|
}
|
|
@@ -1184,6 +1198,9 @@ class DynamicFormSchemaService {
|
|
|
1184
1198
|
if (refs.length > 0) {
|
|
1185
1199
|
return this.getFormGroupConfig(property, options, parent);
|
|
1186
1200
|
}
|
|
1201
|
+
// if (this.checkIsEditorProperty(property)) {
|
|
1202
|
+
// return this.getFormEditorConfig(property, options, parent);
|
|
1203
|
+
// }
|
|
1187
1204
|
return this.getFormInputConfig(property, options, parent);
|
|
1188
1205
|
}
|
|
1189
1206
|
getFormFieldData(property, options) {
|
|
@@ -1210,6 +1227,7 @@ class DynamicFormSchemaService {
|
|
|
1210
1227
|
fieldSet: property.fieldSet,
|
|
1211
1228
|
labelPrefix: property.labelPrefix,
|
|
1212
1229
|
purposes: property.purposes || property.purpose,
|
|
1230
|
+
discriminator: property.discriminator,
|
|
1213
1231
|
priority: property.priority,
|
|
1214
1232
|
componentType: property.componentType,
|
|
1215
1233
|
wrappers: wrappers.filter(ObjectUtils.isStringWithValue),
|
|
@@ -1224,8 +1242,7 @@ class DynamicFormSchemaService {
|
|
|
1224
1242
|
return this.builder.createFormArray(property.id, async (sp) => {
|
|
1225
1243
|
const subSchemas = await this.openApi.getReferences(property, options.schema);
|
|
1226
1244
|
if (subSchemas.length > 0) {
|
|
1227
|
-
|
|
1228
|
-
return mergeFormFields(ObjectUtils.copy(subModels));
|
|
1245
|
+
return this.getFormFieldsForRefs(subSchemas, sp, options);
|
|
1229
1246
|
}
|
|
1230
1247
|
return this.getFormFieldForProp(property.items, options, sp);
|
|
1231
1248
|
}, {
|
|
@@ -1245,10 +1262,10 @@ class DynamicFormSchemaService {
|
|
|
1245
1262
|
async getFormGroupConfig(property, options, parent) {
|
|
1246
1263
|
return this.builder.createFormGroup(property.id, async (sp) => {
|
|
1247
1264
|
const subSchemas = await this.openApi.getReferences(property, options.schema);
|
|
1248
|
-
|
|
1249
|
-
return mergeFormFields(subFields);
|
|
1265
|
+
return this.getFormFieldsForRefs(subSchemas, sp, options);
|
|
1250
1266
|
}, {
|
|
1251
1267
|
...this.getFormFieldData(property, options),
|
|
1268
|
+
useTabs: property.useTabs
|
|
1252
1269
|
}, parent, options);
|
|
1253
1270
|
}
|
|
1254
1271
|
getFormInputConfig(property, options, parent) {
|
|
@@ -2174,7 +2191,7 @@ class DynamicFormArrayComponent extends FieldArrayType {
|
|
|
2174
2191
|
this.currentTab.set(Math.min(this.currentTab(), length - 1));
|
|
2175
2192
|
}
|
|
2176
2193
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.19", ngImport: i0, type: DynamicFormArrayComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
2177
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.19", type: DynamicFormArrayComponent, isStandalone: false, selector: "dynamic-form-array", usesInheritance: true, ngImport: i0, template: "@let label = !props.label || props.hideLabel ? null : props.label | translate;\n@if (field.display) {\n @if (label) {\n <label class=\"field-label\">\n <span [innerHTML]=\"label | safe: 'html'\"></span>\n <p class=\"field-description\" *ngIf=\"props.description\">{{ props.description | translate }}</p>\n @if (props.markRequired) {\n <span class=\"field-required\" aria-hidden=\"true\">*</span>\n }\n </label>\n }\n <div class=\"field-container\">\n <tabs class=\"form-array-items\" [(value)]=\"currentTab\">\n @for (itemField of field.fieldGroup; track itemField.key; let ix = $index) {\n <ng-template #fieldContent>\n <div class=\"form-array-buttons\">\n @if (itemField.removeItem) {\n <btn icon=\"trash\" [attr.data-testid]=\"field.testId + '-remove-item-' + ix\" (click)=\"removeItem(ix)\"></btn>\n }\n @if (itemField.insertItem) {\n <btn icon=\"plus\" [attr.data-testid]=\"field.testId + '-insert-item-' + ix\" (click)=\"addItem(ix)\"></btn>\n }\n </div>\n <formly-field [field]=\"itemField\"></formly-field>\n </ng-template>\n @if (props.useTabs) {\n <div class=\"form-array-item\"\n [tabsItem]=\"ix\"\n [label]=\"(itemField.formControl.value | getValue : props.tabsLabel) || ix + 1\">\n <ng-container [ngTemplateOutlet]=\"fieldContent\"></ng-container>\n </div>\n } @else {\n <div class=\"form-array-item\">\n <ng-container [ngTemplateOutlet]=\"fieldContent\"></ng-container>\n </div>\n }\n }\n </tabs>\n\n <div class=\"form-array-buttons\">\n @if (props.clearItems) {\n <btn [attr.data-testid]=\"field.testId + '-clear-items'\" icon=\"trash\" label=\"button.clear-items\" (click)=\"clearItems()\"></btn>\n }\n @if (props.addItem) {\n <btn [attr.data-testid]=\"field.testId + '-add-item'\" icon=\"plus\" label=\"button.insert-item\" (click)=\"addItem()\"></btn>\n }\n </div>\n\n <div *ngIf=\"showError\" class=\"field-errors invalid-feedback\">\n <formly-validation-message\n [field]=\"field\"\n id=\"{{ id }}-formly-validation-error\"\n role=\"alert\"\n ></formly-validation-message>\n </div>\n </div>\n}\n", styles: [".form-array-item.hidden-tab{display:none}.form-array-buttons{display:flex;gap:5px;margin-bottom:5px}.field-errors.invalid-feedback{display:block}\n"], dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.TabsItemDirective, selector: "[tabsItem]", inputs: ["tabsItem", "label", "tooltip", "icon", "disabled", "classes"] }, { kind: "component", type: i2.BtnComponent, selector: "btn", inputs: ["label", "tooltip", "icon", "disabled", "type", "size"] }, { kind: "component", type: i2.TabsComponent, selector: "tabs", inputs: ["value", "options", "type", "size", "testId", "tabsClass"], outputs: ["valueChange", "selectedChange"] }, { kind: "component", type: i3.LegacyFormlyField, selector: "formly-field" }, { kind: "component", type: i3.LegacyFormlyValidationMessage, selector: "formly-validation-message" }, { kind: "pipe", type: i2.GetValuePipe, name: "getValue" }, { kind: "pipe", type: i2.SafeHtmlPipe, name: "safe" }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None });
|
|
2194
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.19", type: DynamicFormArrayComponent, isStandalone: false, selector: "dynamic-form-array", usesInheritance: true, ngImport: i0, template: "@let label = !props.label || props.hideLabel ? null : props.label | translate;\n@if (field.display) {\n @if (label) {\n <label class=\"field-label\">\n <span [innerHTML]=\"label | safe: 'html'\"></span>\n <p class=\"field-description\" *ngIf=\"props.description\">{{ props.description | translate }}</p>\n @if (props.markRequired) {\n <span class=\"field-required\" aria-hidden=\"true\">*</span>\n }\n </label>\n }\n <div class=\"field-container\">\n <tabs class=\"form-array-items\" [(value)]=\"currentTab\">\n @for (itemField of field.fieldGroup; track itemField.key; let ix = $index) {\n <ng-template #fieldContent>\n <div class=\"form-array-buttons\">\n @if (itemField.removeItem) {\n <btn icon=\"trash\" [attr.data-testid]=\"field.testId + '-remove-item-' + ix\" (click)=\"removeItem(ix)\"></btn>\n }\n @if (itemField.insertItem) {\n <btn icon=\"plus\" [attr.data-testid]=\"field.testId + '-insert-item-' + ix\" (click)=\"addItem(ix)\"></btn>\n }\n </div>\n <formly-field [field]=\"itemField\"></formly-field>\n </ng-template>\n @if (props.useTabs) {\n <div class=\"form-array-item\"\n [tabsItem]=\"ix\"\n [label]=\"(itemField.formControl.value | getValue : props.tabsLabel) || ix + 1\">\n <ng-container [ngTemplateOutlet]=\"fieldContent\"></ng-container>\n </div>\n } @else {\n <div class=\"form-array-item\">\n <ng-container [ngTemplateOutlet]=\"fieldContent\"></ng-container>\n </div>\n }\n }\n </tabs>\n\n <div class=\"form-array-buttons\">\n @if (props.clearItems) {\n <btn [attr.data-testid]=\"field.testId + '-clear-items'\" icon=\"trash\" label=\"button.clear-items\" (click)=\"clearItems()\"></btn>\n }\n @if (props.addItem) {\n <btn [attr.data-testid]=\"field.testId + '-add-item'\" icon=\"plus\" label=\"button.insert-item\" (click)=\"addItem()\"></btn>\n }\n </div>\n\n <div *ngIf=\"showError\" class=\"field-errors invalid-feedback\">\n <formly-validation-message\n [field]=\"field\"\n id=\"{{ id }}-formly-validation-error\"\n role=\"alert\"\n ></formly-validation-message>\n </div>\n </div>\n}\n", styles: [".form-array-item.hidden-tab{display:none}.form-array-buttons{display:flex;gap:5px;margin-bottom:5px}.field-errors.invalid-feedback{display:block}\n"], dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.TabsItemDirective, selector: "[tabsItem]", inputs: ["tabsItem", "label", "tooltip", "icon", "disabled", "path", "classes"] }, { kind: "component", type: i2.BtnComponent, selector: "btn", inputs: ["label", "tooltip", "icon", "disabled", "path", "type", "size"] }, { kind: "component", type: i2.TabsComponent, selector: "tabs", inputs: ["value", "options", "type", "size", "testId", "tabsClass"], outputs: ["valueChange", "selectedChange"] }, { kind: "component", type: i3.LegacyFormlyField, selector: "formly-field" }, { kind: "component", type: i3.LegacyFormlyValidationMessage, selector: "formly-validation-message" }, { kind: "pipe", type: i2.GetValuePipe, name: "getValue" }, { kind: "pipe", type: i2.SafeHtmlPipe, name: "safe" }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None });
|
|
2178
2195
|
}
|
|
2179
2196
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.19", ngImport: i0, type: DynamicFormArrayComponent, decorators: [{
|
|
2180
2197
|
type: Component,
|
|
@@ -2207,7 +2224,7 @@ class DynamicFormPasswordComponent extends DynamicFieldType {
|
|
|
2207
2224
|
});
|
|
2208
2225
|
}
|
|
2209
2226
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.19", ngImport: i0, type: DynamicFormPasswordComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
2210
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "19.2.19", type: DynamicFormPasswordComponent, isStandalone: false, selector: "dynamic-form-password", viewQueries: [{ propertyName: "input", first: true, predicate: ["input"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"form-password-group\">\n <input #input\n class=\"form-control\"\n [attr.type]=\"type()\"\n [attr.data-testid]=\"field.testId\"\n [formControl]=\"formControl\"\n [formlyAttributes]=\"field\" />\n <btn type=\"transparent\"\n [icon]=\"icon()\"\n [attr.data-testid]=\"field.testId + '-toggle'\"\n (mousedown)=\"switchType()\"></btn>\n</div>\n", styles: [".form-password-group{position:relative}.form-password-group btn{display:block;position:absolute;aspect-ratio:1;top:0;bottom:0;right:0}\n"], dependencies: [{ kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: i2.BtnComponent, selector: "btn", inputs: ["label", "tooltip", "icon", "disabled", "type", "size"] }, { kind: "directive", type: i3.LegacyFormlyAttributes, selector: "[formlyAttributes]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
2227
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "19.2.19", type: DynamicFormPasswordComponent, isStandalone: false, selector: "dynamic-form-password", viewQueries: [{ propertyName: "input", first: true, predicate: ["input"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"form-password-group\">\n <input #input\n class=\"form-control\"\n [attr.type]=\"type()\"\n [attr.data-testid]=\"field.testId\"\n [formControl]=\"formControl\"\n [formlyAttributes]=\"field\" />\n <btn type=\"transparent\"\n [icon]=\"icon()\"\n [attr.data-testid]=\"field.testId + '-toggle'\"\n (mousedown)=\"switchType()\"></btn>\n</div>\n", styles: [".form-password-group{position:relative}.form-password-group btn{display:block;position:absolute;aspect-ratio:1;top:0;bottom:0;right:0}\n"], dependencies: [{ kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: i2.BtnComponent, selector: "btn", inputs: ["label", "tooltip", "icon", "disabled", "path", "type", "size"] }, { kind: "directive", type: i3.LegacyFormlyAttributes, selector: "[formlyAttributes]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
2211
2228
|
}
|
|
2212
2229
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.19", ngImport: i0, type: DynamicFormPasswordComponent, decorators: [{
|
|
2213
2230
|
type: Component,
|
|
@@ -2304,20 +2321,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.19", ngImpo
|
|
|
2304
2321
|
|
|
2305
2322
|
class DynamicFormFieldsetComponent extends FieldWrapper {
|
|
2306
2323
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.19", ngImport: i0, type: DynamicFormFieldsetComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
2307
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.19", type: DynamicFormFieldsetComponent, isStandalone: false, selector: "dynamic-form-fieldset", usesInheritance: true, ngImport: i0, template: "@let label = !props.label || props.hideLabel || field.parent.props.useTabs ? null : props.label | translate;\n@if (field.display) {\n <ng-container [ngTemplateOutlet]=\"field | dynamicFormTemplate : 'prefix'\"\n [ngTemplateOutletContext]=\"field\"></ng-container>\n <legend class=\"field-legend\" *ngIf=\"label\">\n <span [innerHTML]=\"label | safe: 'html'\"></span>\n </legend>\n <div class=\"field-container\">\n @for (itemField of field.fieldGroup; track itemField) {\n @if (itemField.display) {\n <formly-field [field]=\"itemField\"></formly-field>\n }\n }\n </div>\n <ng-container [ngTemplateOutlet]=\"field | dynamicFormTemplate : 'suffix'\"\n [ngTemplateOutletContext]=\"field\"></ng-container>\n}\n", dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i3.LegacyFormlyField, selector: "formly-field" }, { kind: "pipe", type: i2.SafeHtmlPipe, name: "safe" }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }, { kind: "pipe", type: DynamicFormTemplatePipe, name: "dynamicFormTemplate" }], encapsulation: i0.ViewEncapsulation.None });
|
|
2324
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.19", type: DynamicFormFieldsetComponent, isStandalone: false, selector: "dynamic-form-fieldset", usesInheritance: true, ngImport: i0, template: "@let label = !props.label || props.hideLabel || field.parent.props.useTabs ? null : props.label | translate;\r\n@if (field.display) {\r\n <ng-container [ngTemplateOutlet]=\"field | dynamicFormTemplate : 'prefix'\"\r\n [ngTemplateOutletContext]=\"field\"></ng-container>\r\n <legend class=\"field-legend\" *ngIf=\"label\">\r\n <span [innerHTML]=\"label | safe: 'html'\"></span>\r\n </legend>\r\n <div class=\"field-container\">\r\n @for (itemField of field.fieldGroup; track itemField) {\r\n @if (itemField.display) {\r\n <formly-field [field]=\"itemField\"></formly-field>\r\n }\r\n }\r\n </div>\r\n <ng-container [ngTemplateOutlet]=\"field | dynamicFormTemplate : 'suffix'\"\r\n [ngTemplateOutletContext]=\"field\"></ng-container>\r\n}\r\n", dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i3.LegacyFormlyField, selector: "formly-field" }, { kind: "pipe", type: i2.SafeHtmlPipe, name: "safe" }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }, { kind: "pipe", type: DynamicFormTemplatePipe, name: "dynamicFormTemplate" }], encapsulation: i0.ViewEncapsulation.None });
|
|
2308
2325
|
}
|
|
2309
2326
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.19", ngImport: i0, type: DynamicFormFieldsetComponent, decorators: [{
|
|
2310
2327
|
type: Component,
|
|
2311
|
-
args: [{ standalone: false, selector: "dynamic-form-fieldset", encapsulation: ViewEncapsulation.None, template: "@let label = !props.label || props.hideLabel || field.parent.props.useTabs ? null : props.label | translate;\n@if (field.display) {\n <ng-container [ngTemplateOutlet]=\"field | dynamicFormTemplate : 'prefix'\"\n [ngTemplateOutletContext]=\"field\"></ng-container>\n <legend class=\"field-legend\" *ngIf=\"label\">\n <span [innerHTML]=\"label | safe: 'html'\"></span>\n </legend>\n <div class=\"field-container\">\n @for (itemField of field.fieldGroup; track itemField) {\n @if (itemField.display) {\n <formly-field [field]=\"itemField\"></formly-field>\n }\n }\n </div>\n <ng-container [ngTemplateOutlet]=\"field | dynamicFormTemplate : 'suffix'\"\n [ngTemplateOutletContext]=\"field\"></ng-container>\n}\n" }]
|
|
2328
|
+
args: [{ standalone: false, selector: "dynamic-form-fieldset", encapsulation: ViewEncapsulation.None, template: "@let label = !props.label || props.hideLabel || field.parent.props.useTabs ? null : props.label | translate;\r\n@if (field.display) {\r\n <ng-container [ngTemplateOutlet]=\"field | dynamicFormTemplate : 'prefix'\"\r\n [ngTemplateOutletContext]=\"field\"></ng-container>\r\n <legend class=\"field-legend\" *ngIf=\"label\">\r\n <span [innerHTML]=\"label | safe: 'html'\"></span>\r\n </legend>\r\n <div class=\"field-container\">\r\n @for (itemField of field.fieldGroup; track itemField) {\r\n @if (itemField.display) {\r\n <formly-field [field]=\"itemField\"></formly-field>\r\n }\r\n }\r\n </div>\r\n <ng-container [ngTemplateOutlet]=\"field | dynamicFormTemplate : 'suffix'\"\r\n [ngTemplateOutletContext]=\"field\"></ng-container>\r\n}\r\n" }]
|
|
2312
2329
|
}] });
|
|
2313
2330
|
|
|
2314
2331
|
class DynamicFormGroupComponent extends FieldWrapper {
|
|
2332
|
+
get parent() {
|
|
2333
|
+
return this.field?.parent;
|
|
2334
|
+
}
|
|
2315
2335
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.19", ngImport: i0, type: DynamicFormGroupComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
2316
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.19", type: DynamicFormGroupComponent, isStandalone: false, selector: "dynamic-form-group", usesInheritance: true, ngImport: i0, template: "<ng-template #innerLabelTemplate let-label=\"label\">\n <label class=\"field-label\" [for]=\"id\">\n <span [innerHTML]=\"label | safe: 'html'\"></span>\n @if (props.markRequired) {\n <span class=\"field-required\" aria-hidden=\"true\">*</span>\n }\n @if (props.description) {\n <p class=\"field-description\" [innerHTML]=\"props.description | translate | safe: 'html'\"></p>\n }\n </label>\n</ng-template>\n<ng-template #labelTemplate>\n @let label = !props.label || props.hideLabel ? null : props.label | translate;\n @if (label) {\n <ng-container [ngxTemplateOutlet]=\"(field | dynamicFormTemplate : 'label') || innerLabelTemplate\"\n [context]=\"field\"\n [additionalContext]=\"{label: label}\"></ng-container>\n }\n</ng-template>\n@if (field.display) {\n @if (props.labelAlign === \"before\") {\n <ng-container [ngTemplateOutlet]=\"labelTemplate\"></ng-container>\n }\n <tabs class=\"field-container\" [testId]=\"(field.testId || 'form') + '-tab'\">\n @for (itemField of field.fieldGroup; track itemField) {\n @if (itemField.display) {\n @if (props.useTabs && itemField.
|
|
2336
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.19", type: DynamicFormGroupComponent, isStandalone: false, selector: "dynamic-form-group", usesInheritance: true, ngImport: i0, template: "<ng-template #innerLabelTemplate let-label=\"label\">\r\n <label class=\"field-label\" [for]=\"id\">\r\n <span [innerHTML]=\"label | safe: 'html'\"></span>\r\n @if (props.markRequired) {\r\n <span class=\"field-required\" aria-hidden=\"true\">*</span>\r\n }\r\n @if (props.description) {\r\n <p class=\"field-description\" [innerHTML]=\"props.description | translate | safe: 'html'\"></p>\r\n }\r\n </label>\r\n</ng-template>\r\n<ng-template #labelTemplate>\r\n @let label = !props.label || props.hideLabel || parent?.props?.useTabs ? null : props.label | translate;\r\n @if (label) {\r\n <ng-container [ngxTemplateOutlet]=\"(field | dynamicFormTemplate : 'label') || innerLabelTemplate\"\r\n [context]=\"field\"\r\n [additionalContext]=\"{label: label}\"></ng-container>\r\n }\r\n</ng-template>\r\n@if (field.display) {\r\n @if (props.labelAlign === \"before\") {\r\n <ng-container [ngTemplateOutlet]=\"labelTemplate\"></ng-container>\r\n }\r\n <tabs class=\"field-container\" [testId]=\"(field.testId || 'form') + '-tab'\">\r\n @for (itemField of field.fieldGroup; track itemField) {\r\n @if (itemField.display) {\r\n @if (props.useTabs && itemField.fieldGroup) {\r\n <div class=\"form-fieldset-item\"\r\n [tabsItem]=\"itemField.id\"\r\n [classes]=\"['form-fieldset-tab', itemField.valid === false ? 'invalid' : 'valid']\"\r\n [label]=\"itemField.props.label\">\r\n <formly-field [field]=\"itemField\"></formly-field>\r\n </div>\r\n } @else {\r\n <formly-field [field]=\"itemField\"></formly-field>\r\n }\r\n }\r\n }\r\n @if (showError && field.key !== null) {\r\n <div *ngIf=\"showError\" class=\"field-errors invalid-feedback\">\r\n <formly-validation-message\r\n [field]=\"field\"\r\n id=\"{{ id }}-formly-validation-error\"\r\n role=\"alert\"\r\n ></formly-validation-message>\r\n </div>\r\n }\r\n </tabs>\r\n @if (props.labelAlign === \"after\") {\r\n <ng-container [ngTemplateOutlet]=\"labelTemplate\"></ng-container>\r\n }\r\n}\r\n", styles: [".dynamic-form-group>.field-container{overflow:hidden}.form-fieldset-item.hidden-tab{display:none}.form-fieldset-tab{position:relative;--invalid-bg: rgba(184, 38, 38, 1);--invalid-border: rgba(184, 38, 38, .6);--invalid-color: #ececec;--invalid-box-size: 15px;--invalid-box-pull: -3px}.form-fieldset-tab.invalid>btn .async-target{border:1px solid var(--invalid-border)}.form-fieldset-tab.invalid:after{background:var(--invalid-bg);color:var(--invalid-color);font-size:10px;line-height:var(--invalid-box-size);width:var(--invalid-box-size);height:var(--invalid-box-size);text-align:center;border-radius:5px;content:\"!\";display:block;position:absolute;top:var(--invalid-box-pull);right:var(--invalid-box-pull)}\n"], dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.NgxTemplateOutletDirective, selector: "[ngxTemplateOutlet]", inputs: ["context", "additionalContext", "ngxTemplateOutlet"] }, { kind: "directive", type: i2.TabsItemDirective, selector: "[tabsItem]", inputs: ["tabsItem", "label", "tooltip", "icon", "disabled", "path", "classes"] }, { kind: "component", type: i2.TabsComponent, selector: "tabs", inputs: ["value", "options", "type", "size", "testId", "tabsClass"], outputs: ["valueChange", "selectedChange"] }, { kind: "component", type: i3.LegacyFormlyField, selector: "formly-field" }, { kind: "component", type: i3.LegacyFormlyValidationMessage, selector: "formly-validation-message" }, { kind: "pipe", type: i2.SafeHtmlPipe, name: "safe" }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }, { kind: "pipe", type: DynamicFormTemplatePipe, name: "dynamicFormTemplate" }], encapsulation: i0.ViewEncapsulation.None });
|
|
2317
2337
|
}
|
|
2318
2338
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.19", ngImport: i0, type: DynamicFormGroupComponent, decorators: [{
|
|
2319
2339
|
type: Component,
|
|
2320
|
-
args: [{ standalone: false, selector: "dynamic-form-group", encapsulation: ViewEncapsulation.None, template: "<ng-template #innerLabelTemplate let-label=\"label\">\n <label class=\"field-label\" [for]=\"id\">\n <span [innerHTML]=\"label | safe: 'html'\"></span>\n @if (props.markRequired) {\n <span class=\"field-required\" aria-hidden=\"true\">*</span>\n }\n @if (props.description) {\n <p class=\"field-description\" [innerHTML]=\"props.description | translate | safe: 'html'\"></p>\n }\n </label>\n</ng-template>\n<ng-template #labelTemplate>\n @let label = !props.label || props.hideLabel ? null : props.label | translate;\n @if (label) {\n <ng-container [ngxTemplateOutlet]=\"(field | dynamicFormTemplate : 'label') || innerLabelTemplate\"\n [context]=\"field\"\n [additionalContext]=\"{label: label}\"></ng-container>\n }\n</ng-template>\n@if (field.display) {\n @if (props.labelAlign === \"before\") {\n <ng-container [ngTemplateOutlet]=\"labelTemplate\"></ng-container>\n }\n <tabs class=\"field-container\" [testId]=\"(field.testId || 'form') + '-tab'\">\n @for (itemField of field.fieldGroup; track itemField) {\n @if (itemField.display) {\n @if (props.useTabs && itemField.
|
|
2340
|
+
args: [{ standalone: false, selector: "dynamic-form-group", encapsulation: ViewEncapsulation.None, template: "<ng-template #innerLabelTemplate let-label=\"label\">\r\n <label class=\"field-label\" [for]=\"id\">\r\n <span [innerHTML]=\"label | safe: 'html'\"></span>\r\n @if (props.markRequired) {\r\n <span class=\"field-required\" aria-hidden=\"true\">*</span>\r\n }\r\n @if (props.description) {\r\n <p class=\"field-description\" [innerHTML]=\"props.description | translate | safe: 'html'\"></p>\r\n }\r\n </label>\r\n</ng-template>\r\n<ng-template #labelTemplate>\r\n @let label = !props.label || props.hideLabel || parent?.props?.useTabs ? null : props.label | translate;\r\n @if (label) {\r\n <ng-container [ngxTemplateOutlet]=\"(field | dynamicFormTemplate : 'label') || innerLabelTemplate\"\r\n [context]=\"field\"\r\n [additionalContext]=\"{label: label}\"></ng-container>\r\n }\r\n</ng-template>\r\n@if (field.display) {\r\n @if (props.labelAlign === \"before\") {\r\n <ng-container [ngTemplateOutlet]=\"labelTemplate\"></ng-container>\r\n }\r\n <tabs class=\"field-container\" [testId]=\"(field.testId || 'form') + '-tab'\">\r\n @for (itemField of field.fieldGroup; track itemField) {\r\n @if (itemField.display) {\r\n @if (props.useTabs && itemField.fieldGroup) {\r\n <div class=\"form-fieldset-item\"\r\n [tabsItem]=\"itemField.id\"\r\n [classes]=\"['form-fieldset-tab', itemField.valid === false ? 'invalid' : 'valid']\"\r\n [label]=\"itemField.props.label\">\r\n <formly-field [field]=\"itemField\"></formly-field>\r\n </div>\r\n } @else {\r\n <formly-field [field]=\"itemField\"></formly-field>\r\n }\r\n }\r\n }\r\n @if (showError && field.key !== null) {\r\n <div *ngIf=\"showError\" class=\"field-errors invalid-feedback\">\r\n <formly-validation-message\r\n [field]=\"field\"\r\n id=\"{{ id }}-formly-validation-error\"\r\n role=\"alert\"\r\n ></formly-validation-message>\r\n </div>\r\n }\r\n </tabs>\r\n @if (props.labelAlign === \"after\") {\r\n <ng-container [ngTemplateOutlet]=\"labelTemplate\"></ng-container>\r\n }\r\n}\r\n", styles: [".dynamic-form-group>.field-container{overflow:hidden}.form-fieldset-item.hidden-tab{display:none}.form-fieldset-tab{position:relative;--invalid-bg: rgba(184, 38, 38, 1);--invalid-border: rgba(184, 38, 38, .6);--invalid-color: #ececec;--invalid-box-size: 15px;--invalid-box-pull: -3px}.form-fieldset-tab.invalid>btn .async-target{border:1px solid var(--invalid-border)}.form-fieldset-tab.invalid:after{background:var(--invalid-bg);color:var(--invalid-color);font-size:10px;line-height:var(--invalid-box-size);width:var(--invalid-box-size);height:var(--invalid-box-size);text-align:center;border-radius:5px;content:\"!\";display:block;position:absolute;top:var(--invalid-box-pull);right:var(--invalid-box-pull)}\n"] }]
|
|
2321
2341
|
}] });
|
|
2322
2342
|
|
|
2323
2343
|
// --- Components ---
|
|
@@ -2365,6 +2385,9 @@ class NgxDynamicFormModule {
|
|
|
2365
2385
|
{ name: "form-field", component: DynamicFormFieldComponent },
|
|
2366
2386
|
{ name: "form-fieldset", component: DynamicFormFieldsetComponent },
|
|
2367
2387
|
{ name: "form-group", component: DynamicFormGroupComponent },
|
|
2388
|
+
// These are just placeholders, so the sample app does not break when it is in a more complex context
|
|
2389
|
+
{ name: "form-integration", component: DynamicFormFieldComponent },
|
|
2390
|
+
{ name: "form-address", component: DynamicFormGroupComponent },
|
|
2368
2391
|
],
|
|
2369
2392
|
extras: {
|
|
2370
2393
|
resetFieldOnHide: false,
|