@stemy/ngx-dynamic-form 19.2.13 → 19.3.0
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 +382 -257
- package/fesm2022/stemy-ngx-dynamic-form.mjs.map +1 -1
- package/ngx-dynamic-form/common-types.d.ts +36 -14
- package/ngx-dynamic-form/components/dynamic-form/dynamic-form.component.d.ts +4 -2
- package/ngx-dynamic-form/services/dynamic-form-builder.service.d.ts +3 -2
- package/ngx-dynamic-form/services/dynamic-form-schema.service.d.ts +36 -0
- package/ngx-dynamic-form/services/dynamic-form.service.d.ts +10 -29
- package/ngx-dynamic-form/utils/customizer.d.ts +2 -2
- package/ngx-dynamic-form/utils/internal.d.ts +21 -0
- package/ngx-dynamic-form/utils/misc.d.ts +1 -4
- package/package.json +2 -2
- package/public_api.d.ts +3 -2
- package/ngx-dynamic-form/utils/validation-errors.d.ts +0 -11
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as i2 from '@stemy/ngx-utils';
|
|
2
|
-
import { cachedFactory, ReflectUtils, ObjectUtils, LANGUAGE_SERVICE, API_SERVICE, StringUtils, TOASTER_SERVICE, EventsService, NgxUtilsModule } from '@stemy/ngx-utils';
|
|
3
|
-
import { Subject, BehaviorSubject,
|
|
2
|
+
import { cachedFactory, ReflectUtils, ObjectUtils, LANGUAGE_SERVICE, ForbiddenZone, API_SERVICE, StringUtils, TOASTER_SERVICE, EventsService, NgxUtilsModule } from '@stemy/ngx-utils';
|
|
3
|
+
import { Subject, BehaviorSubject, startWith, distinctUntilChanged, switchMap, from, isObservable, firstValueFrom, first } from 'rxjs';
|
|
4
4
|
import * as i0 from '@angular/core';
|
|
5
5
|
import { Inject, Injectable, input, output, inject, Renderer2, ElementRef, computed, signal, effect, HostListener, HostBinding, Directive, Injector, ChangeDetectionStrategy, ViewEncapsulation, Component, makeEnvironmentProviders, NgModule } from '@angular/core';
|
|
6
6
|
import * as i1 from '@angular/forms';
|
|
@@ -17,18 +17,18 @@ const FORM_ROOT_KEY = "__root";
|
|
|
17
17
|
|
|
18
18
|
function customizeFormField(...providers) {
|
|
19
19
|
const factory = cachedFactory(providers);
|
|
20
|
-
return async (
|
|
20
|
+
return async (field, options, injector, property, schema) => {
|
|
21
21
|
const customizers = factory(injector);
|
|
22
|
-
const
|
|
22
|
+
const fields = [field];
|
|
23
23
|
for (const customizer of customizers) {
|
|
24
|
-
const index =
|
|
24
|
+
const index = fields.findIndex(m => customizer.acceptField(m, property, schema));
|
|
25
25
|
if (index >= 0) {
|
|
26
|
-
const custom = await customizer.customizeField(
|
|
26
|
+
const custom = await customizer.customizeField(fields[index], options, property, schema);
|
|
27
27
|
const result = Array.isArray(custom) ? custom : [custom];
|
|
28
|
-
|
|
28
|
+
fields.splice(index, 1, ...result);
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
|
-
return
|
|
31
|
+
return fields;
|
|
32
32
|
};
|
|
33
33
|
}
|
|
34
34
|
|
|
@@ -176,32 +176,9 @@ function maxValueValidation(max, each) {
|
|
|
176
176
|
return validateEach(each, v => typeof v == "number" && v <= max, "maxValue");
|
|
177
177
|
}
|
|
178
178
|
|
|
179
|
-
function isStringWithVal(val) {
|
|
180
|
-
return typeof val == "string" && val.length > 0;
|
|
181
|
-
}
|
|
182
|
-
function findRefs(property) {
|
|
183
|
-
const refs = Array.isArray(property.allOf)
|
|
184
|
-
? property.allOf.map(o => o.$ref).filter(isStringWithVal)
|
|
185
|
-
: [property.items?.$ref, property.$ref].filter(isStringWithVal);
|
|
186
|
-
return refs.map(t => t.split("/").pop());
|
|
187
|
-
}
|
|
188
179
|
function replaceSpecialChars(str, to = "-") {
|
|
189
180
|
return `${str}`.replace(/[&\/\\#, +()$~%.@'":*?<>{}]/g, to);
|
|
190
181
|
}
|
|
191
|
-
function mergeFormFields(formFields) {
|
|
192
|
-
const res = [];
|
|
193
|
-
for (const formModel of formFields) {
|
|
194
|
-
for (const subModel of formModel) {
|
|
195
|
-
const index = res.findIndex(t => t.key == subModel.key);
|
|
196
|
-
if (index >= 0) {
|
|
197
|
-
res[index] = subModel;
|
|
198
|
-
continue;
|
|
199
|
-
}
|
|
200
|
-
res.push(subModel);
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
return res;
|
|
204
|
-
}
|
|
205
182
|
function getFieldByPath(field, path) {
|
|
206
183
|
if (field.path === path) {
|
|
207
184
|
return field;
|
|
@@ -215,6 +192,18 @@ function getFieldByPath(field, path) {
|
|
|
215
192
|
}
|
|
216
193
|
return null;
|
|
217
194
|
}
|
|
195
|
+
function getFieldsByKey(field, key) {
|
|
196
|
+
if (field.key === key) {
|
|
197
|
+
return [field];
|
|
198
|
+
}
|
|
199
|
+
if (!field.fieldGroup)
|
|
200
|
+
return [];
|
|
201
|
+
const results = [];
|
|
202
|
+
for (const sf of field.fieldGroup) {
|
|
203
|
+
results.push(...getFieldsByKey(sf, key));
|
|
204
|
+
}
|
|
205
|
+
return results;
|
|
206
|
+
}
|
|
218
207
|
function setFieldHidden(field, hidden = true) {
|
|
219
208
|
const hide = field.expressions?.hide;
|
|
220
209
|
if (hide) {
|
|
@@ -245,6 +234,113 @@ const MIN_INPUT_NUM = -999999999;
|
|
|
245
234
|
const MAX_INPUT_NUM = 999999999;
|
|
246
235
|
const EDITOR_FORMATS = ["php", "json", "html", "css", "scss"];
|
|
247
236
|
|
|
237
|
+
class ConfigForSchemaWrap {
|
|
238
|
+
opts;
|
|
239
|
+
mode;
|
|
240
|
+
injector;
|
|
241
|
+
schema;
|
|
242
|
+
get labelPrefix() {
|
|
243
|
+
return this.opts.labelPrefix;
|
|
244
|
+
}
|
|
245
|
+
get labelCustomizer() {
|
|
246
|
+
return this.opts.labelCustomizer;
|
|
247
|
+
}
|
|
248
|
+
get testId() {
|
|
249
|
+
return this.opts.testId;
|
|
250
|
+
}
|
|
251
|
+
fieldCustomizer;
|
|
252
|
+
constructor(opts, mode, injector, schema) {
|
|
253
|
+
this.opts = opts;
|
|
254
|
+
this.mode = mode;
|
|
255
|
+
this.injector = injector;
|
|
256
|
+
this.schema = schema;
|
|
257
|
+
this.fieldCustomizer = this.mode !== "wrap" || !ObjectUtils.isFunction(this.opts.fieldCustomizer)
|
|
258
|
+
? field => field
|
|
259
|
+
: this.opts.fieldCustomizer;
|
|
260
|
+
}
|
|
261
|
+
async customize(field, property, schema) {
|
|
262
|
+
field.defaultValue = `${field.props?.type}`.startsWith("date")
|
|
263
|
+
? convertToDate(property.default) : property.default;
|
|
264
|
+
const res = await ForbiddenZone.run("customizer", () => this.fieldCustomizer(field, this.forCustomizer(), this.injector, property, schema));
|
|
265
|
+
return !res ? [field] : handleConfigs(res);
|
|
266
|
+
}
|
|
267
|
+
forCustomizer() {
|
|
268
|
+
return new ConfigForSchemaWrap(this.opts, "customizer", this.injector, this.schema);
|
|
269
|
+
}
|
|
270
|
+
forSchema(schema) {
|
|
271
|
+
return new ConfigForSchemaWrap(this.opts, this.mode, this.injector, schema);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
async function toWrapOptions(customizeOrOptions, injector, schema, errorMsg) {
|
|
275
|
+
if (errorMsg && ForbiddenZone.isForbidden("customizer")) {
|
|
276
|
+
throw new Error(errorMsg);
|
|
277
|
+
}
|
|
278
|
+
if (customizeOrOptions instanceof ConfigForSchemaWrap) {
|
|
279
|
+
return customizeOrOptions;
|
|
280
|
+
}
|
|
281
|
+
let schemaOptions = customizeOrOptions;
|
|
282
|
+
if (!ObjectUtils.isObject(schemaOptions)) {
|
|
283
|
+
schemaOptions = {
|
|
284
|
+
fieldCustomizer: customizeOrOptions
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
return new ConfigForSchemaWrap(schemaOptions, "wrap", injector, schema);
|
|
288
|
+
}
|
|
289
|
+
function convertToDate(value) {
|
|
290
|
+
if (ObjectUtils.isNullOrUndefined(value))
|
|
291
|
+
return null;
|
|
292
|
+
const date = ObjectUtils.isDate(value)
|
|
293
|
+
? value
|
|
294
|
+
: new Date(value);
|
|
295
|
+
return isNaN(date) ? new Date() : date;
|
|
296
|
+
}
|
|
297
|
+
function handleConfigs(configs) {
|
|
298
|
+
return Array.isArray(configs) ? configs : [configs];
|
|
299
|
+
}
|
|
300
|
+
function isStringWithVal(val) {
|
|
301
|
+
return typeof val == "string" && val.length > 0;
|
|
302
|
+
}
|
|
303
|
+
function findRefs(property) {
|
|
304
|
+
const refs = Array.isArray(property.allOf)
|
|
305
|
+
? property.allOf.map(o => o.$ref).filter(isStringWithVal)
|
|
306
|
+
: [property.items?.$ref, property.$ref].filter(isStringWithVal);
|
|
307
|
+
return refs.map(t => t.split("/").pop());
|
|
308
|
+
}
|
|
309
|
+
function mergeFormFields(formFields) {
|
|
310
|
+
const res = [];
|
|
311
|
+
for (const formModel of formFields) {
|
|
312
|
+
for (const subModel of formModel) {
|
|
313
|
+
const index = res.findIndex(t => t.key == subModel.key);
|
|
314
|
+
if (index >= 0) {
|
|
315
|
+
res[index] = subModel;
|
|
316
|
+
continue;
|
|
317
|
+
}
|
|
318
|
+
res.push(subModel);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
return res;
|
|
322
|
+
}
|
|
323
|
+
function getFormValidationErrors(controls, parentPath = "") {
|
|
324
|
+
const errors = [];
|
|
325
|
+
Object.entries(controls).forEach(([name, control], ix) => {
|
|
326
|
+
const path = !parentPath ? name : `${parentPath}.${name}`;
|
|
327
|
+
if (control instanceof FormGroup$1) {
|
|
328
|
+
getFormValidationErrors(control.controls, path).forEach(error => errors.push(error));
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
if (control instanceof FormArray$1) {
|
|
332
|
+
control.controls.forEach((control, ix) => {
|
|
333
|
+
getFormValidationErrors(control.controls, `${path}.${ix}`).forEach(error => errors.push(error));
|
|
334
|
+
});
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
Object.entries(control.errors || {}).forEach(([errorKey, errorValue]) => {
|
|
338
|
+
errors.push({ control, path, errorKey, errorValue });
|
|
339
|
+
});
|
|
340
|
+
});
|
|
341
|
+
return errors;
|
|
342
|
+
}
|
|
343
|
+
|
|
248
344
|
class DynamicFormBuilderService {
|
|
249
345
|
injector;
|
|
250
346
|
api;
|
|
@@ -254,60 +350,6 @@ class DynamicFormBuilderService {
|
|
|
254
350
|
this.api = api;
|
|
255
351
|
this.language = language;
|
|
256
352
|
}
|
|
257
|
-
getLabel(key, label, parent, options) {
|
|
258
|
-
const labelPrefix = !ObjectUtils.isString(options.labelPrefix) ? `` : options.labelPrefix;
|
|
259
|
-
const pathPrefix = `${parent?.props?.label || labelPrefix}`;
|
|
260
|
-
const labelItems = ObjectUtils.isString(label)
|
|
261
|
-
? (!label ? [] : [labelPrefix, label])
|
|
262
|
-
: [pathPrefix, `${key || ""}`];
|
|
263
|
-
return labelItems.filter(l => l.length > 0).join(".");
|
|
264
|
-
}
|
|
265
|
-
createFormField(key, type, data, props, parent, options) {
|
|
266
|
-
const validators = Array.isArray(data.validators)
|
|
267
|
-
? data.validators.reduce((res, validator, ix) => {
|
|
268
|
-
res[validator.validatorName || `validator_${ix}`] = validator;
|
|
269
|
-
return res;
|
|
270
|
-
}, {})
|
|
271
|
-
: data.validators || {};
|
|
272
|
-
const hide = new BehaviorSubject(data.hidden === true);
|
|
273
|
-
const additional = new BehaviorSubject({});
|
|
274
|
-
const field = {
|
|
275
|
-
key,
|
|
276
|
-
type,
|
|
277
|
-
validators,
|
|
278
|
-
parent,
|
|
279
|
-
path: !parent?.path ? key : `${parent.path}.${key}`,
|
|
280
|
-
fieldSet: String(data.fieldSet || ""),
|
|
281
|
-
resetOnHide: false,
|
|
282
|
-
validation: {
|
|
283
|
-
messages: Object.keys(validators).reduce((res, key) => {
|
|
284
|
-
res[key] = validationMessage(this.injector, key, options.labelPrefix);
|
|
285
|
-
return res;
|
|
286
|
-
}, {})
|
|
287
|
-
},
|
|
288
|
-
props: {
|
|
289
|
-
...props,
|
|
290
|
-
disabled: data.disabled === true,
|
|
291
|
-
formCheck: "nolabel",
|
|
292
|
-
required: !!validators.required,
|
|
293
|
-
label: this.getLabel(key, data.label, parent, options),
|
|
294
|
-
},
|
|
295
|
-
modelOptions: {
|
|
296
|
-
updateOn: "change"
|
|
297
|
-
},
|
|
298
|
-
fieldGroupClassName: "field-container",
|
|
299
|
-
expressions: {
|
|
300
|
-
hide,
|
|
301
|
-
additional
|
|
302
|
-
}
|
|
303
|
-
};
|
|
304
|
-
field.expressions.className = hide.pipe(map(hidden => {
|
|
305
|
-
const classes = [`dynamic-form-field`, `dynamic-form-field-${field.key}`, `dynamic-form-${field.type || "group"}`].concat(Array.isArray(data.classes) ? data.classes : [data.classes || ""]);
|
|
306
|
-
return hidden ? `` : classes.filter(c => c?.length > 0).join(" ");
|
|
307
|
-
}));
|
|
308
|
-
field.expressions.path = () => field.path;
|
|
309
|
-
return field;
|
|
310
|
-
}
|
|
311
353
|
resolveFormFields(target, parent, options) {
|
|
312
354
|
const prototype = target?.prototype || {};
|
|
313
355
|
const fields = ReflectUtils.getMetadata("dynamicFormFields", target?.prototype || {}) || new Set();
|
|
@@ -347,7 +389,7 @@ class DynamicFormBuilderService {
|
|
|
347
389
|
}
|
|
348
390
|
// Create a field-set wrapper for each group and concat the other fields to the end
|
|
349
391
|
return Object.keys(groups).map(group => {
|
|
350
|
-
|
|
392
|
+
const fieldSet = {
|
|
351
393
|
fieldGroup: groups[group],
|
|
352
394
|
wrappers: ["form-fieldset"],
|
|
353
395
|
className: `dynamic-form-fieldset dynamic-form-fieldset-${group}`,
|
|
@@ -357,6 +399,8 @@ class DynamicFormBuilderService {
|
|
|
357
399
|
hidden: false
|
|
358
400
|
}
|
|
359
401
|
};
|
|
402
|
+
this.setExpressions(fieldSet, options);
|
|
403
|
+
return fieldSet;
|
|
360
404
|
}).concat(others);
|
|
361
405
|
}
|
|
362
406
|
createFormInput(key, data, parent, options) {
|
|
@@ -375,6 +419,8 @@ class DynamicFormBuilderService {
|
|
|
375
419
|
minLength: isNaN(data.minLength) ? 0 : data.minLength,
|
|
376
420
|
maxLength: isNaN(data.maxLength) ? MAX_INPUT_NUM : data.maxLength,
|
|
377
421
|
placeholder: data.placeholder || "",
|
|
422
|
+
indeterminate: data.indeterminate || false,
|
|
423
|
+
suffix: data.suffix || "",
|
|
378
424
|
attributes: {
|
|
379
425
|
autocomplete
|
|
380
426
|
},
|
|
@@ -497,6 +543,81 @@ class DynamicFormBuilderService {
|
|
|
497
543
|
control.setValue(options[0].value);
|
|
498
544
|
return options;
|
|
499
545
|
}
|
|
546
|
+
getLabel(key, label, parent, options) {
|
|
547
|
+
const labelPrefix = !ObjectUtils.isString(options.labelPrefix) ? `` : options.labelPrefix;
|
|
548
|
+
const pathPrefix = `${parent?.props?.label || labelPrefix}`;
|
|
549
|
+
const labelItems = ObjectUtils.isString(label)
|
|
550
|
+
? (!label ? [] : [labelPrefix, label])
|
|
551
|
+
: [pathPrefix, `${key || ""}`];
|
|
552
|
+
return options.labelCustomizer?.(key, label, parent, options.labelPrefix)
|
|
553
|
+
?? labelItems.filter(l => l.length > 0).join(".");
|
|
554
|
+
}
|
|
555
|
+
createFormField(key, type, data, props, parent, options) {
|
|
556
|
+
const validators = Array.isArray(data.validators)
|
|
557
|
+
? data.validators.reduce((res, validator, ix) => {
|
|
558
|
+
res[validator.validatorName || `validator_${ix}`] = validator;
|
|
559
|
+
return res;
|
|
560
|
+
}, {})
|
|
561
|
+
: data.validators || {};
|
|
562
|
+
const hide = new BehaviorSubject(data.hidden === true);
|
|
563
|
+
const additional = new BehaviorSubject({});
|
|
564
|
+
const field = {
|
|
565
|
+
key,
|
|
566
|
+
type,
|
|
567
|
+
validators,
|
|
568
|
+
parent,
|
|
569
|
+
fieldSet: String(data.fieldSet || ""),
|
|
570
|
+
resetOnHide: false,
|
|
571
|
+
validation: {
|
|
572
|
+
messages: Object.keys(validators).reduce((res, key) => {
|
|
573
|
+
res[key] = validationMessage(this.injector, key, options.labelPrefix);
|
|
574
|
+
return res;
|
|
575
|
+
}, {})
|
|
576
|
+
},
|
|
577
|
+
props: {
|
|
578
|
+
...props,
|
|
579
|
+
disabled: data.disabled === true,
|
|
580
|
+
formCheck: "nolabel",
|
|
581
|
+
required: !!validators.required,
|
|
582
|
+
label: this.getLabel(key, data.label, parent, options),
|
|
583
|
+
},
|
|
584
|
+
modelOptions: {
|
|
585
|
+
updateOn: "change"
|
|
586
|
+
},
|
|
587
|
+
fieldGroupClassName: "field-container",
|
|
588
|
+
expressions: {
|
|
589
|
+
hide,
|
|
590
|
+
additional,
|
|
591
|
+
className: (target) => {
|
|
592
|
+
return target.hide ? `` : [`dynamic-form-field`, `dynamic-form-field-${target.key}`, `dynamic-form-${target.type || "group"}`].concat(Array.isArray(data.classes) ? data.classes : [data.classes || ""]).filter(c => c?.length > 0).join(" ");
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
};
|
|
596
|
+
this.setExpressions(field, options);
|
|
597
|
+
return field;
|
|
598
|
+
}
|
|
599
|
+
setExpressions(field, options) {
|
|
600
|
+
const expressions = {
|
|
601
|
+
path: target => {
|
|
602
|
+
const tp = target.parent;
|
|
603
|
+
const key = !target.key ? `` : `.${target.key}`;
|
|
604
|
+
return !tp?.path ? `${target.key || ""}` : `${tp.path}.${key}`;
|
|
605
|
+
},
|
|
606
|
+
testId: target => {
|
|
607
|
+
const tp = target.parent;
|
|
608
|
+
const prefix = !options.testId ? `` : `${options.testId}-`;
|
|
609
|
+
const key = !target.key ? `` : `-${target.key}`;
|
|
610
|
+
return !tp?.testId ? `${prefix}${target.key || key}` : `${tp.testId}${key}`;
|
|
611
|
+
}
|
|
612
|
+
};
|
|
613
|
+
Object.entries(expressions).forEach(([key, expression]) => {
|
|
614
|
+
field.expressions = field.expressions ?? {};
|
|
615
|
+
field.expressions[key] = expression;
|
|
616
|
+
if (ObjectUtils.isFunction(expression)) {
|
|
617
|
+
field[key] = expression(field);
|
|
618
|
+
}
|
|
619
|
+
});
|
|
620
|
+
}
|
|
500
621
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DynamicFormBuilderService, deps: [{ token: i0.Injector }, { token: API_SERVICE }, { token: LANGUAGE_SERVICE }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
501
622
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DynamicFormBuilderService });
|
|
502
623
|
}
|
|
@@ -510,28 +631,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
|
|
|
510
631
|
args: [LANGUAGE_SERVICE]
|
|
511
632
|
}] }] });
|
|
512
633
|
|
|
513
|
-
|
|
514
|
-
const errors = [];
|
|
515
|
-
Object.entries(controls).forEach(([name, control], ix) => {
|
|
516
|
-
const path = !parentPath ? name : `${parentPath}.${name}`;
|
|
517
|
-
if (control instanceof FormGroup$1) {
|
|
518
|
-
getFormValidationErrors(control.controls, path).forEach(error => errors.push(error));
|
|
519
|
-
return;
|
|
520
|
-
}
|
|
521
|
-
if (control instanceof FormArray$1) {
|
|
522
|
-
control.controls.forEach((control, ix) => {
|
|
523
|
-
getFormValidationErrors(control.controls, `${path}.${ix}`).forEach(error => errors.push(error));
|
|
524
|
-
});
|
|
525
|
-
return;
|
|
526
|
-
}
|
|
527
|
-
Object.entries(control.errors || {}).forEach(([errorKey, errorValue]) => {
|
|
528
|
-
errors.push({ control, path, errorKey, errorValue });
|
|
529
|
-
});
|
|
530
|
-
});
|
|
531
|
-
return errors;
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
class DynamicFormService {
|
|
634
|
+
class DynamicFormSchemaService {
|
|
535
635
|
openApi;
|
|
536
636
|
injector;
|
|
537
637
|
builder;
|
|
@@ -541,149 +641,32 @@ class DynamicFormService {
|
|
|
541
641
|
get language() {
|
|
542
642
|
return this.api.language;
|
|
543
643
|
}
|
|
544
|
-
schemas;
|
|
545
644
|
constructor(openApi, injector, builder) {
|
|
546
645
|
this.openApi = openApi;
|
|
547
646
|
this.injector = injector;
|
|
548
647
|
this.builder = builder;
|
|
549
648
|
}
|
|
550
|
-
async
|
|
551
|
-
|
|
552
|
-
if (!group)
|
|
553
|
-
return Promise.resolve();
|
|
554
|
-
return new Promise((resolve, reject) => {
|
|
555
|
-
group.statusChanges
|
|
556
|
-
.pipe(first(status => status == "VALID" || status == "INVALID"))
|
|
557
|
-
.subscribe(status => {
|
|
558
|
-
if (showErrors) {
|
|
559
|
-
this.showErrorsForGroup(group);
|
|
560
|
-
}
|
|
561
|
-
if (status == "VALID") {
|
|
562
|
-
resolve(null);
|
|
563
|
-
return;
|
|
564
|
-
}
|
|
565
|
-
reject(getFormValidationErrors(group.controls));
|
|
566
|
-
});
|
|
567
|
-
group.updateValueAndValidity();
|
|
568
|
-
});
|
|
569
|
-
}
|
|
570
|
-
async serializeForm(form, validate = true) {
|
|
571
|
-
const fields = form.config();
|
|
572
|
-
if (!fields)
|
|
573
|
-
return null;
|
|
574
|
-
if (validate) {
|
|
575
|
-
await this.validateForm(form);
|
|
576
|
-
}
|
|
577
|
-
return this.serialize(fields);
|
|
649
|
+
async getSchema(name) {
|
|
650
|
+
return this.openApi.getSchema(name);
|
|
578
651
|
}
|
|
579
|
-
async
|
|
580
|
-
const
|
|
581
|
-
if (!fields)
|
|
582
|
-
return result;
|
|
583
|
-
for (const field of fields) {
|
|
584
|
-
const serializer = field.serializer;
|
|
585
|
-
const key = `${field.key}`;
|
|
586
|
-
if (ObjectUtils.isFunction(serializer)) {
|
|
587
|
-
result[key] = await serializer(field, this.injector);
|
|
588
|
-
continue;
|
|
589
|
-
}
|
|
590
|
-
if (field.hide && !field.serialize) {
|
|
591
|
-
continue;
|
|
592
|
-
}
|
|
593
|
-
const control = field.formControl;
|
|
594
|
-
if (field.fieldGroup) {
|
|
595
|
-
const group = await this.serialize(field.fieldGroup);
|
|
596
|
-
if (field.key) {
|
|
597
|
-
result[key] = !field.fieldArray ? group : Object.values(group);
|
|
598
|
-
continue;
|
|
599
|
-
}
|
|
600
|
-
Object.assign(result, group);
|
|
601
|
-
continue;
|
|
602
|
-
}
|
|
603
|
-
result[key] = control.value;
|
|
604
|
-
}
|
|
605
|
-
return result;
|
|
606
|
-
}
|
|
607
|
-
async getFormFieldsForSchema(name, customizeOrOptions) {
|
|
608
|
-
const group = await this.getFormFieldGroupForSchema(name, customizeOrOptions);
|
|
609
|
-
return group.fieldGroup;
|
|
610
|
-
}
|
|
611
|
-
async getFormFieldGroupForSchema(name, customizeOrOptions) {
|
|
612
|
-
this.schemas = await this.openApi.getSchemas();
|
|
613
|
-
const schemaOptions = ObjectUtils.isObject(customizeOrOptions) ? customizeOrOptions : {};
|
|
614
|
-
const customizeConfig = ObjectUtils.isFunction(customizeOrOptions) ? customizeOrOptions : schemaOptions.customizer;
|
|
615
|
-
const schema = this.schemas[name];
|
|
616
|
-
const wrapOptions = {
|
|
617
|
-
...schemaOptions,
|
|
618
|
-
schema,
|
|
619
|
-
injector: this.injector,
|
|
620
|
-
customizer: async (property, options, config) => {
|
|
621
|
-
config.defaultValue = `${config.type}`.startsWith("date")
|
|
622
|
-
? this.convertToDate(property.default) : property.default;
|
|
623
|
-
if (!ObjectUtils.isFunction(customizeConfig))
|
|
624
|
-
return [config];
|
|
625
|
-
let res = customizeConfig(property, schema, config, options, this.injector);
|
|
626
|
-
if (!res)
|
|
627
|
-
return [config];
|
|
628
|
-
if (res instanceof Promise) {
|
|
629
|
-
res = await res;
|
|
630
|
-
}
|
|
631
|
-
return Array.isArray(res) ? res : [res];
|
|
632
|
-
}
|
|
633
|
-
};
|
|
634
|
-
const config = {
|
|
635
|
-
key: FORM_ROOT_KEY,
|
|
636
|
-
path: "",
|
|
637
|
-
wrappers: ["form-group"]
|
|
638
|
-
};
|
|
639
|
-
const fields = await this.getFormFieldsForSchemaDef(schema, config, wrapOptions);
|
|
640
|
-
const fieldGroup = [...fields];
|
|
641
|
-
// Add id fields if necessary
|
|
642
|
-
if (fields.length > 0) {
|
|
643
|
-
const idFields = [
|
|
644
|
-
{ key: "id", props: { hidden: true } },
|
|
645
|
-
{ key: "_id", props: { hidden: true } },
|
|
646
|
-
];
|
|
647
|
-
fieldGroup.unshift(...idFields
|
|
648
|
-
.filter(t => !fields.some(c => c.key == t.key)));
|
|
649
|
-
}
|
|
650
|
-
config.fieldGroup = fieldGroup;
|
|
651
|
-
const root = await wrapOptions.customizer({
|
|
652
|
-
id: FORM_ROOT_KEY,
|
|
653
|
-
type: "object",
|
|
654
|
-
properties: schema?.properties || {}
|
|
655
|
-
}, wrapOptions, config);
|
|
656
|
-
// Check if the customized root wrapper returned an array
|
|
657
|
-
fields.length = 0;
|
|
658
|
-
for (const model of root) {
|
|
659
|
-
if (model.key === FORM_ROOT_KEY) {
|
|
660
|
-
return model;
|
|
661
|
-
}
|
|
662
|
-
else {
|
|
663
|
-
fields.push(model);
|
|
664
|
-
}
|
|
665
|
-
}
|
|
666
|
-
return {
|
|
667
|
-
...config,
|
|
668
|
-
fieldGroup: fields
|
|
669
|
-
};
|
|
670
|
-
}
|
|
671
|
-
async getFormFieldsForSchemaDef(schema, parent, options) {
|
|
652
|
+
async getFormFieldsForSchema(name, parent, customizeOrOptions) {
|
|
653
|
+
const schema = await this.getSchema(name);
|
|
672
654
|
if (!schema)
|
|
673
655
|
return [];
|
|
656
|
+
const options = await toWrapOptions(customizeOrOptions, this.injector, schema);
|
|
674
657
|
const keys = Object.keys(schema.properties || {});
|
|
675
658
|
const fields = [];
|
|
676
659
|
// Collect all properties of this schema def
|
|
677
660
|
for (const key of keys) {
|
|
678
661
|
const property = schema.properties[key];
|
|
679
|
-
const propFields = await this.getFormFieldsForProp(property, options, parent);
|
|
662
|
+
const propFields = await this.getFormFieldsForProp(property, schema, options, parent);
|
|
680
663
|
fields.push(...propFields);
|
|
681
664
|
}
|
|
682
665
|
return this.builder.createFieldSets(fields.filter(f => null !== f), parent, options);
|
|
683
666
|
}
|
|
684
|
-
async getFormFieldsForProp(property, options, parent) {
|
|
667
|
+
async getFormFieldsForProp(property, schema, options, parent) {
|
|
685
668
|
const field = await this.getFormFieldForProp(property, options, parent);
|
|
686
|
-
return !field ? [] : options.
|
|
669
|
+
return !field ? [] : options.customize(field, property, schema);
|
|
687
670
|
}
|
|
688
671
|
async getFormFieldForProp(property, options, parent) {
|
|
689
672
|
const $enum = property.items?.enum || property.enum;
|
|
@@ -737,9 +720,9 @@ class DynamicFormService {
|
|
|
737
720
|
}
|
|
738
721
|
async getFormArrayConfig(property, options, parent) {
|
|
739
722
|
return this.builder.createFormArray(property.id, async (sp) => {
|
|
740
|
-
const subSchemas = findRefs(property)
|
|
723
|
+
const subSchemas = findRefs(property);
|
|
741
724
|
if (subSchemas.length > 0) {
|
|
742
|
-
const subModels = await Promise.all(subSchemas.map(s => this.
|
|
725
|
+
const subModels = await Promise.all(subSchemas.map(s => this.getFormFieldsForSchema(s, sp, options)));
|
|
743
726
|
return mergeFormFields(ObjectUtils.copy(subModels));
|
|
744
727
|
}
|
|
745
728
|
return this.getFormFieldForProp(property.items, options, null);
|
|
@@ -758,9 +741,9 @@ class DynamicFormService {
|
|
|
758
741
|
}, parent, options);
|
|
759
742
|
}
|
|
760
743
|
async getFormGroupConfig(property, options, parent) {
|
|
761
|
-
const subSchemas = findRefs(property).map(ref => this.schemas[ref]);
|
|
762
744
|
return this.builder.createFormGroup(property.id, async (sp) => {
|
|
763
|
-
const
|
|
745
|
+
const subSchemas = findRefs(property);
|
|
746
|
+
const subModels = await Promise.all(subSchemas.map(s => this.getFormFieldsForSchema(s, sp, options)));
|
|
764
747
|
return mergeFormFields(subModels);
|
|
765
748
|
}, {
|
|
766
749
|
...this.getFormFieldData(property, options),
|
|
@@ -793,7 +776,9 @@ class DynamicFormService {
|
|
|
793
776
|
max: sub.maximum,
|
|
794
777
|
minLength: sub.minLength,
|
|
795
778
|
maxLength: sub.maxLength,
|
|
796
|
-
placeholder: property.placeholder
|
|
779
|
+
placeholder: property.placeholder,
|
|
780
|
+
indeterminate: property.indeterminate,
|
|
781
|
+
suffix: property.suffix
|
|
797
782
|
}, parent, options);
|
|
798
783
|
}
|
|
799
784
|
getFormTextareaConfig(property, options, parent) {
|
|
@@ -808,7 +793,7 @@ class DynamicFormService {
|
|
|
808
793
|
placeholder: property.placeholder || ""
|
|
809
794
|
}, parent, options);
|
|
810
795
|
}
|
|
811
|
-
// getFormEditorConfig(property: IOpenApiSchemaProperty, options:
|
|
796
|
+
// getFormEditorConfig(property: IOpenApiSchemaProperty, options: ConfigForSchemaWrap): DynamicEditorModelConfig {
|
|
812
797
|
// const sub = property.type == "array" ? property.items || property : property;
|
|
813
798
|
// return Object.assign(
|
|
814
799
|
// this.getFormControlConfig(property, options),
|
|
@@ -832,8 +817,8 @@ class DynamicFormService {
|
|
|
832
817
|
...this.getFormFieldData(property, options),
|
|
833
818
|
type: property.format == "date-time" ? "datetime-local" : "date",
|
|
834
819
|
// format: property.dateFormat || "dd.MM.yyyy",
|
|
835
|
-
min:
|
|
836
|
-
max:
|
|
820
|
+
min: convertToDate(property.min),
|
|
821
|
+
max: convertToDate(property.max),
|
|
837
822
|
}, parent, options);
|
|
838
823
|
}
|
|
839
824
|
getFormSelectConfig(property, options, parent) {
|
|
@@ -956,14 +941,6 @@ class DynamicFormService {
|
|
|
956
941
|
}
|
|
957
942
|
});
|
|
958
943
|
}
|
|
959
|
-
convertToDate(value) {
|
|
960
|
-
if (ObjectUtils.isNullOrUndefined(value))
|
|
961
|
-
return null;
|
|
962
|
-
const date = ObjectUtils.isDate(value)
|
|
963
|
-
? value
|
|
964
|
-
: new Date(value);
|
|
965
|
-
return isNaN(date) ? new Date() : date;
|
|
966
|
-
}
|
|
967
944
|
addPropertyValidators(validators, property) {
|
|
968
945
|
if (!property)
|
|
969
946
|
return;
|
|
@@ -1004,12 +981,155 @@ class DynamicFormService {
|
|
|
1004
981
|
validators.itemsMaxValue = maxValueValidation(items.maximum, true);
|
|
1005
982
|
}
|
|
1006
983
|
}
|
|
1007
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type:
|
|
984
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DynamicFormSchemaService, deps: [{ token: i2.OpenApiService }, { token: i0.Injector }, { token: DynamicFormBuilderService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
985
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DynamicFormSchemaService });
|
|
986
|
+
}
|
|
987
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DynamicFormSchemaService, decorators: [{
|
|
988
|
+
type: Injectable
|
|
989
|
+
}], ctorParameters: () => [{ type: i2.OpenApiService }, { type: i0.Injector }, { type: DynamicFormBuilderService }] });
|
|
990
|
+
|
|
991
|
+
class DynamicFormService {
|
|
992
|
+
fs;
|
|
993
|
+
injector;
|
|
994
|
+
api;
|
|
995
|
+
constructor(fs, injector, api) {
|
|
996
|
+
this.fs = fs;
|
|
997
|
+
this.injector = injector;
|
|
998
|
+
this.api = api;
|
|
999
|
+
}
|
|
1000
|
+
async getFormFieldsForSchema(name, customizeOrOptions) {
|
|
1001
|
+
const group = await this.getFormFieldGroupBySchemaName(name, customizeOrOptions, "getFormFieldsForSchema");
|
|
1002
|
+
return group.fieldGroup;
|
|
1003
|
+
}
|
|
1004
|
+
async getFormFieldGroupForSchema(name, customizeOrOptions) {
|
|
1005
|
+
return this.getFormFieldGroupBySchemaName(name, customizeOrOptions, "getFormFieldsForSchema");
|
|
1006
|
+
}
|
|
1007
|
+
async getFormFieldGroupBySchemaName(name, customizeOrOptions, restrictedMethod) {
|
|
1008
|
+
const config = {
|
|
1009
|
+
key: FORM_ROOT_KEY,
|
|
1010
|
+
path: "",
|
|
1011
|
+
wrappers: ["form-group"]
|
|
1012
|
+
};
|
|
1013
|
+
const schema = await this.fs.getSchema(name);
|
|
1014
|
+
const wrapOptions = await toWrapOptions(customizeOrOptions, this.injector, schema, `"DynamicFormService.${restrictedMethod}" is called from a customizer, which is not allowed. Please use DynamicFormSchemaService instead!`);
|
|
1015
|
+
const fields = await this.fs.getFormFieldsForSchema(name, config, wrapOptions);
|
|
1016
|
+
const fieldGroup = [...fields];
|
|
1017
|
+
config.fieldGroup = fieldGroup;
|
|
1018
|
+
// There are no actual fields in the schema, or no schema exists
|
|
1019
|
+
if (fields.length === 0)
|
|
1020
|
+
return config;
|
|
1021
|
+
// Add id fields if necessary
|
|
1022
|
+
const idFields = [
|
|
1023
|
+
{ key: "id", props: { hidden: true } },
|
|
1024
|
+
{ key: "_id", props: { hidden: true } },
|
|
1025
|
+
];
|
|
1026
|
+
fieldGroup.unshift(...idFields
|
|
1027
|
+
.filter(t => !fields.some(c => c.key == t.key)));
|
|
1028
|
+
const root = await wrapOptions.customize(config, {
|
|
1029
|
+
id: FORM_ROOT_KEY,
|
|
1030
|
+
type: "object",
|
|
1031
|
+
properties: schema?.properties || {}
|
|
1032
|
+
}, schema);
|
|
1033
|
+
// Check if the customized root wrapper returned an array
|
|
1034
|
+
fields.length = 0;
|
|
1035
|
+
for (const model of root) {
|
|
1036
|
+
if (model.key === FORM_ROOT_KEY) {
|
|
1037
|
+
return model;
|
|
1038
|
+
}
|
|
1039
|
+
else {
|
|
1040
|
+
fields.push(model);
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
return {
|
|
1044
|
+
...config,
|
|
1045
|
+
fieldGroup: fields
|
|
1046
|
+
};
|
|
1047
|
+
}
|
|
1048
|
+
async validateForm(form, showErrors = true) {
|
|
1049
|
+
const group = form.group();
|
|
1050
|
+
if (!group)
|
|
1051
|
+
return Promise.resolve();
|
|
1052
|
+
return new Promise((resolve, reject) => {
|
|
1053
|
+
group.statusChanges
|
|
1054
|
+
.pipe(first(status => status == "VALID" || status == "INVALID"))
|
|
1055
|
+
.subscribe(status => {
|
|
1056
|
+
if (showErrors) {
|
|
1057
|
+
this.showErrorsForGroup(group);
|
|
1058
|
+
}
|
|
1059
|
+
if (status == "VALID") {
|
|
1060
|
+
resolve(null);
|
|
1061
|
+
return;
|
|
1062
|
+
}
|
|
1063
|
+
reject(getFormValidationErrors(group.controls));
|
|
1064
|
+
});
|
|
1065
|
+
group.updateValueAndValidity();
|
|
1066
|
+
});
|
|
1067
|
+
}
|
|
1068
|
+
async serializeForm(form, validate = true) {
|
|
1069
|
+
const fields = form.config();
|
|
1070
|
+
if (!fields)
|
|
1071
|
+
return null;
|
|
1072
|
+
if (validate) {
|
|
1073
|
+
await this.validateForm(form);
|
|
1074
|
+
}
|
|
1075
|
+
return this.serialize(fields);
|
|
1076
|
+
}
|
|
1077
|
+
async serialize(fields) {
|
|
1078
|
+
const result = {};
|
|
1079
|
+
if (!fields)
|
|
1080
|
+
return result;
|
|
1081
|
+
for (const field of fields) {
|
|
1082
|
+
const serializer = field.serializer;
|
|
1083
|
+
const key = `${field.key}`;
|
|
1084
|
+
if (ObjectUtils.isFunction(serializer)) {
|
|
1085
|
+
result[key] = await serializer(field, this.injector);
|
|
1086
|
+
continue;
|
|
1087
|
+
}
|
|
1088
|
+
if (field.hide && !field.serialize) {
|
|
1089
|
+
continue;
|
|
1090
|
+
}
|
|
1091
|
+
const control = field.formControl;
|
|
1092
|
+
if (field.fieldGroup) {
|
|
1093
|
+
const group = await this.serialize(field.fieldGroup);
|
|
1094
|
+
if (field.key) {
|
|
1095
|
+
result[key] = !field.fieldArray ? group : Object.values(group);
|
|
1096
|
+
continue;
|
|
1097
|
+
}
|
|
1098
|
+
Object.assign(result, group);
|
|
1099
|
+
continue;
|
|
1100
|
+
}
|
|
1101
|
+
result[key] = control.value;
|
|
1102
|
+
}
|
|
1103
|
+
return result;
|
|
1104
|
+
}
|
|
1105
|
+
showErrorsForGroup(formGroup) {
|
|
1106
|
+
if (!formGroup)
|
|
1107
|
+
return;
|
|
1108
|
+
formGroup.markAsTouched({ onlySelf: true });
|
|
1109
|
+
const controls = Object.keys(formGroup.controls).map(id => formGroup.controls[id]);
|
|
1110
|
+
this.showErrorsForControls(controls);
|
|
1111
|
+
}
|
|
1112
|
+
showErrorsForControls(controls) {
|
|
1113
|
+
controls.forEach(control => {
|
|
1114
|
+
if (control instanceof FormGroup$1) {
|
|
1115
|
+
this.showErrorsForGroup(control);
|
|
1116
|
+
return;
|
|
1117
|
+
}
|
|
1118
|
+
control.markAsTouched({ onlySelf: true });
|
|
1119
|
+
if (control instanceof FormArray$1) {
|
|
1120
|
+
this.showErrorsForControls(control.controls);
|
|
1121
|
+
}
|
|
1122
|
+
});
|
|
1123
|
+
}
|
|
1124
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DynamicFormService, deps: [{ token: DynamicFormSchemaService }, { token: i0.Injector }, { token: API_SERVICE }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1008
1125
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DynamicFormService });
|
|
1009
1126
|
}
|
|
1010
1127
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DynamicFormService, decorators: [{
|
|
1011
1128
|
type: Injectable
|
|
1012
|
-
}], ctorParameters: () => [{ type:
|
|
1129
|
+
}], ctorParameters: () => [{ type: DynamicFormSchemaService }, { type: i0.Injector }, { type: undefined, decorators: [{
|
|
1130
|
+
type: Inject,
|
|
1131
|
+
args: [API_SERVICE]
|
|
1132
|
+
}] }] });
|
|
1013
1133
|
|
|
1014
1134
|
class AsyncSubmitDirective {
|
|
1015
1135
|
method = input(null, { alias: "async-submit" });
|
|
@@ -1113,6 +1233,8 @@ class DynamicFormComponent {
|
|
|
1113
1233
|
events = inject(EventsService);
|
|
1114
1234
|
languages = inject(LANGUAGE_SERVICE);
|
|
1115
1235
|
labelPrefix = input("label");
|
|
1236
|
+
labelCustomizer = input(null);
|
|
1237
|
+
testId = input("");
|
|
1116
1238
|
data = input({});
|
|
1117
1239
|
fields = input(null);
|
|
1118
1240
|
fieldChanges = new Subject();
|
|
@@ -1121,7 +1243,9 @@ class DynamicFormComponent {
|
|
|
1121
1243
|
});
|
|
1122
1244
|
config = computed(() => {
|
|
1123
1245
|
return this.fields() || this.builder.resolveFormFields(this.data()?.constructor, null, {
|
|
1124
|
-
labelPrefix: this.labelPrefix()
|
|
1246
|
+
labelPrefix: this.labelPrefix(),
|
|
1247
|
+
labelCustomizer: this.labelCustomizer(),
|
|
1248
|
+
testId: this.testId(),
|
|
1125
1249
|
});
|
|
1126
1250
|
});
|
|
1127
1251
|
group = computed(() => {
|
|
@@ -1159,7 +1283,7 @@ class DynamicFormComponent {
|
|
|
1159
1283
|
this.options?.resetModel?.();
|
|
1160
1284
|
}
|
|
1161
1285
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DynamicFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1162
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: DynamicFormComponent, isStandalone: false, selector: "dynamic-form", inputs: { labelPrefix: { classPropertyName: "labelPrefix", publicName: "labelPrefix", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, fields: { classPropertyName: "fields", publicName: "fields", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onSubmit: "onSubmit" }, ngImport: i0, template: "@if (config() && group()) {\n <form [formGroup]=\"group()\" (ngSubmit)=\"submit()\" autocomplete=\"off\" role=\"presentation\">\n <input type=\"submit\" [hidden]=\"true\" />\n <formly-form [model]=\"data()\"\n [fields]=\"config()\"\n [form]=\"group()\"\n [options]=\"options\"></formly-form>\n <ng-content></ng-content>\n </form>\n}\n", dependencies: [{ kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: i3.FormlyForm, selector: "formly-form", inputs: ["form", "model", "fields", "options"], outputs: ["modelChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
1286
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: DynamicFormComponent, isStandalone: false, selector: "dynamic-form", inputs: { labelPrefix: { classPropertyName: "labelPrefix", publicName: "labelPrefix", isSignal: true, isRequired: false, transformFunction: null }, labelCustomizer: { classPropertyName: "labelCustomizer", publicName: "labelCustomizer", isSignal: true, isRequired: false, transformFunction: null }, testId: { classPropertyName: "testId", publicName: "testId", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, fields: { classPropertyName: "fields", publicName: "fields", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onSubmit: "onSubmit" }, ngImport: i0, template: "@if (config() && group()) {\n <form [formGroup]=\"group()\" (ngSubmit)=\"submit()\" autocomplete=\"off\" role=\"presentation\">\n <input type=\"submit\" [hidden]=\"true\" />\n <formly-form [model]=\"data()\"\n [fields]=\"config()\"\n [form]=\"group()\"\n [options]=\"options\"></formly-form>\n <ng-content></ng-content>\n </form>\n}\n", dependencies: [{ kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: i3.FormlyForm, selector: "formly-form", inputs: ["form", "model", "fields", "options"], outputs: ["modelChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
1163
1287
|
}
|
|
1164
1288
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DynamicFormComponent, decorators: [{
|
|
1165
1289
|
type: Component,
|
|
@@ -1193,11 +1317,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
|
|
|
1193
1317
|
|
|
1194
1318
|
class DynamicFormFieldComponent extends FieldWrapper {
|
|
1195
1319
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DynamicFormFieldComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
1196
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: DynamicFormFieldComponent, isStandalone: false, selector: "dynamic-form-field", usesInheritance: true, ngImport: i0, template: "<label class=\"field-label\" *ngIf=\"props.label\">\n {{ props.label | translate }}\n <p class=\"field-description\" *ngIf=\"props.description\">{{ props.description | translate }}</p>\n <span class=\"field-required\" *ngIf=\"props.required && props.hideRequiredMarker !== true\" aria-hidden=\"true\">*</span>\n</label>\n<div class=\"field-container\">\n <ng-container #fieldComponent></ng-container>\n <div *ngIf=\"showError\" class=\"field-errors invalid-feedback\">\n <formly-validation-message\n id=\"{{ id }}-formly-validation-error\"\n [field]=\"field\"\n role=\"alert\"\n ></formly-validation-message>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i3.ɵFormlyValidationMessage, selector: "formly-validation-message", inputs: ["field"] }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None });
|
|
1320
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: DynamicFormFieldComponent, isStandalone: false, selector: "dynamic-form-field", usesInheritance: true, ngImport: i0, template: "<label class=\"field-label\" [for]=\"id\" *ngIf=\"props.label\">\n {{ props.label | translate }}\n <p class=\"field-description\" *ngIf=\"props.description\">{{ props.description | translate }}</p>\n <span class=\"field-required\" *ngIf=\"props.required && props.hideRequiredMarker !== true\" aria-hidden=\"true\">*</span>\n</label>\n<div class=\"field-container\">\n <ng-container #fieldComponent></ng-container>\n <div *ngIf=\"showError\" class=\"field-errors invalid-feedback\">\n <formly-validation-message\n id=\"{{ id }}-formly-validation-error\"\n [field]=\"field\"\n role=\"alert\"\n ></formly-validation-message>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i3.ɵFormlyValidationMessage, selector: "formly-validation-message", inputs: ["field"] }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None });
|
|
1197
1321
|
}
|
|
1198
1322
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DynamicFormFieldComponent, decorators: [{
|
|
1199
1323
|
type: Component,
|
|
1200
|
-
args: [{ standalone: false, selector: "dynamic-form-field", encapsulation: ViewEncapsulation.None, template: "<label class=\"field-label\" *ngIf=\"props.label\">\n {{ props.label | translate }}\n <p class=\"field-description\" *ngIf=\"props.description\">{{ props.description | translate }}</p>\n <span class=\"field-required\" *ngIf=\"props.required && props.hideRequiredMarker !== true\" aria-hidden=\"true\">*</span>\n</label>\n<div class=\"field-container\">\n <ng-container #fieldComponent></ng-container>\n <div *ngIf=\"showError\" class=\"field-errors invalid-feedback\">\n <formly-validation-message\n id=\"{{ id }}-formly-validation-error\"\n [field]=\"field\"\n role=\"alert\"\n ></formly-validation-message>\n </div>\n</div>\n" }]
|
|
1324
|
+
args: [{ standalone: false, selector: "dynamic-form-field", encapsulation: ViewEncapsulation.None, template: "<label class=\"field-label\" [for]=\"id\" *ngIf=\"props.label\">\n {{ props.label | translate }}\n <p class=\"field-description\" *ngIf=\"props.description\">{{ props.description | translate }}</p>\n <span class=\"field-required\" *ngIf=\"props.required && props.hideRequiredMarker !== true\" aria-hidden=\"true\">*</span>\n</label>\n<div class=\"field-container\">\n <ng-container #fieldComponent></ng-container>\n <div *ngIf=\"showError\" class=\"field-errors invalid-feedback\">\n <formly-validation-message\n id=\"{{ id }}-formly-validation-error\"\n [field]=\"field\"\n role=\"alert\"\n ></formly-validation-message>\n </div>\n</div>\n" }]
|
|
1201
1325
|
}] });
|
|
1202
1326
|
|
|
1203
1327
|
class DynamicFormFieldsetComponent extends FieldWrapper {
|
|
@@ -1273,7 +1397,8 @@ class NgxDynamicFormModule {
|
|
|
1273
1397
|
return [
|
|
1274
1398
|
...providers,
|
|
1275
1399
|
DynamicFormService,
|
|
1276
|
-
DynamicFormBuilderService
|
|
1400
|
+
DynamicFormBuilderService,
|
|
1401
|
+
DynamicFormSchemaService
|
|
1277
1402
|
];
|
|
1278
1403
|
}
|
|
1279
1404
|
static forRoot(config) {
|
|
@@ -1339,5 +1464,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
|
|
|
1339
1464
|
* Generated bundle index. Do not edit.
|
|
1340
1465
|
*/
|
|
1341
1466
|
|
|
1342
|
-
export { AsyncSubmitDirective, DynamicFormArrayComponent, DynamicFormBuilderService, DynamicFormChipsComponent, DynamicFormComponent, DynamicFormFieldComponent, DynamicFormFieldsetComponent, DynamicFormGroupComponent, DynamicFormService, DynamicFormUploadComponent, EDITOR_FORMATS, FORM_ROOT_KEY, FormFile, FormGroup, FormInput, FormModel, FormSelect, FormSerializable, FormUpload, MAX_INPUT_NUM, MIN_INPUT_NUM, NgxDynamicFormModule, additionalFieldValues, customizeFormField, emailValidation, getFieldByPath, jsonValidation, maxLengthValidation, maxValueValidation,
|
|
1467
|
+
export { AsyncSubmitDirective, DynamicFormArrayComponent, DynamicFormBuilderService, DynamicFormChipsComponent, DynamicFormComponent, DynamicFormFieldComponent, DynamicFormFieldsetComponent, DynamicFormGroupComponent, DynamicFormSchemaService, DynamicFormService, DynamicFormUploadComponent, EDITOR_FORMATS, FORM_ROOT_KEY, FormFile, FormGroup, FormInput, FormModel, FormSelect, FormSerializable, FormUpload, MAX_INPUT_NUM, MIN_INPUT_NUM, NgxDynamicFormModule, additionalFieldValues, customizeFormField, emailValidation, getFieldByPath, getFieldsByKey, jsonValidation, maxLengthValidation, maxValueValidation, minLengthValidation, minValueValidation, phoneValidation, replaceSpecialChars, requiredValidation, setFieldDisabled, setFieldHidden, translationValidation, validationMessage };
|
|
1343
1468
|
//# sourceMappingURL=stemy-ngx-dynamic-form.mjs.map
|