@stemy/ngx-dynamic-form 19.2.14 → 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 +359 -255
- package/fesm2022/stemy-ngx-dynamic-form.mjs.map +1 -1
- package/ngx-dynamic-form/common-types.d.ts +11 -7
- package/ngx-dynamic-form/components/dynamic-form/dynamic-form.component.d.ts +3 -2
- package/ngx-dynamic-form/services/dynamic-form-builder.service.d.ts +4 -4
- 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, startWith, distinctUntilChanged, switchMap,
|
|
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,57 +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
|
-
return {
|
|
275
|
-
key,
|
|
276
|
-
type,
|
|
277
|
-
validators,
|
|
278
|
-
parent,
|
|
279
|
-
fieldSet: String(data.fieldSet || ""),
|
|
280
|
-
resetOnHide: false,
|
|
281
|
-
validation: {
|
|
282
|
-
messages: Object.keys(validators).reduce((res, key) => {
|
|
283
|
-
res[key] = validationMessage(this.injector, key, options.labelPrefix);
|
|
284
|
-
return res;
|
|
285
|
-
}, {})
|
|
286
|
-
},
|
|
287
|
-
props: {
|
|
288
|
-
...props,
|
|
289
|
-
disabled: data.disabled === true,
|
|
290
|
-
formCheck: "nolabel",
|
|
291
|
-
required: !!validators.required,
|
|
292
|
-
label: this.getLabel(key, data.label, parent, options),
|
|
293
|
-
},
|
|
294
|
-
modelOptions: {
|
|
295
|
-
updateOn: "change"
|
|
296
|
-
},
|
|
297
|
-
fieldGroupClassName: "field-container",
|
|
298
|
-
expressions: {
|
|
299
|
-
hide,
|
|
300
|
-
additional,
|
|
301
|
-
className: (target) => {
|
|
302
|
-
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(" ");
|
|
303
|
-
},
|
|
304
|
-
...this.getExpressions(options)
|
|
305
|
-
}
|
|
306
|
-
};
|
|
307
|
-
}
|
|
308
353
|
resolveFormFields(target, parent, options) {
|
|
309
354
|
const prototype = target?.prototype || {};
|
|
310
355
|
const fields = ReflectUtils.getMetadata("dynamicFormFields", target?.prototype || {}) || new Set();
|
|
@@ -344,7 +389,7 @@ class DynamicFormBuilderService {
|
|
|
344
389
|
}
|
|
345
390
|
// Create a field-set wrapper for each group and concat the other fields to the end
|
|
346
391
|
return Object.keys(groups).map(group => {
|
|
347
|
-
|
|
392
|
+
const fieldSet = {
|
|
348
393
|
fieldGroup: groups[group],
|
|
349
394
|
wrappers: ["form-fieldset"],
|
|
350
395
|
className: `dynamic-form-fieldset dynamic-form-fieldset-${group}`,
|
|
@@ -352,11 +397,10 @@ class DynamicFormBuilderService {
|
|
|
352
397
|
props: {
|
|
353
398
|
label: this.getLabel(group, group, parent, options),
|
|
354
399
|
hidden: false
|
|
355
|
-
},
|
|
356
|
-
expressions: {
|
|
357
|
-
...this.getExpressions(options)
|
|
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) {
|
|
@@ -499,8 +543,61 @@ class DynamicFormBuilderService {
|
|
|
499
543
|
control.setValue(options[0].value);
|
|
500
544
|
return options;
|
|
501
545
|
}
|
|
502
|
-
|
|
503
|
-
|
|
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 = {
|
|
504
601
|
path: target => {
|
|
505
602
|
const tp = target.parent;
|
|
506
603
|
const key = !target.key ? `` : `.${target.key}`;
|
|
@@ -513,6 +610,13 @@ class DynamicFormBuilderService {
|
|
|
513
610
|
return !tp?.testId ? `${prefix}${target.key || key}` : `${tp.testId}${key}`;
|
|
514
611
|
}
|
|
515
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
|
+
});
|
|
516
620
|
}
|
|
517
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 });
|
|
518
622
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DynamicFormBuilderService });
|
|
@@ -527,28 +631,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
|
|
|
527
631
|
args: [LANGUAGE_SERVICE]
|
|
528
632
|
}] }] });
|
|
529
633
|
|
|
530
|
-
|
|
531
|
-
const errors = [];
|
|
532
|
-
Object.entries(controls).forEach(([name, control], ix) => {
|
|
533
|
-
const path = !parentPath ? name : `${parentPath}.${name}`;
|
|
534
|
-
if (control instanceof FormGroup$1) {
|
|
535
|
-
getFormValidationErrors(control.controls, path).forEach(error => errors.push(error));
|
|
536
|
-
return;
|
|
537
|
-
}
|
|
538
|
-
if (control instanceof FormArray$1) {
|
|
539
|
-
control.controls.forEach((control, ix) => {
|
|
540
|
-
getFormValidationErrors(control.controls, `${path}.${ix}`).forEach(error => errors.push(error));
|
|
541
|
-
});
|
|
542
|
-
return;
|
|
543
|
-
}
|
|
544
|
-
Object.entries(control.errors || {}).forEach(([errorKey, errorValue]) => {
|
|
545
|
-
errors.push({ control, path, errorKey, errorValue });
|
|
546
|
-
});
|
|
547
|
-
});
|
|
548
|
-
return errors;
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
class DynamicFormService {
|
|
634
|
+
class DynamicFormSchemaService {
|
|
552
635
|
openApi;
|
|
553
636
|
injector;
|
|
554
637
|
builder;
|
|
@@ -558,149 +641,32 @@ class DynamicFormService {
|
|
|
558
641
|
get language() {
|
|
559
642
|
return this.api.language;
|
|
560
643
|
}
|
|
561
|
-
schemas;
|
|
562
644
|
constructor(openApi, injector, builder) {
|
|
563
645
|
this.openApi = openApi;
|
|
564
646
|
this.injector = injector;
|
|
565
647
|
this.builder = builder;
|
|
566
648
|
}
|
|
567
|
-
async
|
|
568
|
-
|
|
569
|
-
if (!group)
|
|
570
|
-
return Promise.resolve();
|
|
571
|
-
return new Promise((resolve, reject) => {
|
|
572
|
-
group.statusChanges
|
|
573
|
-
.pipe(first(status => status == "VALID" || status == "INVALID"))
|
|
574
|
-
.subscribe(status => {
|
|
575
|
-
if (showErrors) {
|
|
576
|
-
this.showErrorsForGroup(group);
|
|
577
|
-
}
|
|
578
|
-
if (status == "VALID") {
|
|
579
|
-
resolve(null);
|
|
580
|
-
return;
|
|
581
|
-
}
|
|
582
|
-
reject(getFormValidationErrors(group.controls));
|
|
583
|
-
});
|
|
584
|
-
group.updateValueAndValidity();
|
|
585
|
-
});
|
|
586
|
-
}
|
|
587
|
-
async serializeForm(form, validate = true) {
|
|
588
|
-
const fields = form.config();
|
|
589
|
-
if (!fields)
|
|
590
|
-
return null;
|
|
591
|
-
if (validate) {
|
|
592
|
-
await this.validateForm(form);
|
|
593
|
-
}
|
|
594
|
-
return this.serialize(fields);
|
|
649
|
+
async getSchema(name) {
|
|
650
|
+
return this.openApi.getSchema(name);
|
|
595
651
|
}
|
|
596
|
-
async
|
|
597
|
-
const
|
|
598
|
-
if (!fields)
|
|
599
|
-
return result;
|
|
600
|
-
for (const field of fields) {
|
|
601
|
-
const serializer = field.serializer;
|
|
602
|
-
const key = `${field.key}`;
|
|
603
|
-
if (ObjectUtils.isFunction(serializer)) {
|
|
604
|
-
result[key] = await serializer(field, this.injector);
|
|
605
|
-
continue;
|
|
606
|
-
}
|
|
607
|
-
if (field.hide && !field.serialize) {
|
|
608
|
-
continue;
|
|
609
|
-
}
|
|
610
|
-
const control = field.formControl;
|
|
611
|
-
if (field.fieldGroup) {
|
|
612
|
-
const group = await this.serialize(field.fieldGroup);
|
|
613
|
-
if (field.key) {
|
|
614
|
-
result[key] = !field.fieldArray ? group : Object.values(group);
|
|
615
|
-
continue;
|
|
616
|
-
}
|
|
617
|
-
Object.assign(result, group);
|
|
618
|
-
continue;
|
|
619
|
-
}
|
|
620
|
-
result[key] = control.value;
|
|
621
|
-
}
|
|
622
|
-
return result;
|
|
623
|
-
}
|
|
624
|
-
async getFormFieldsForSchema(name, customizeOrOptions) {
|
|
625
|
-
const group = await this.getFormFieldGroupForSchema(name, customizeOrOptions);
|
|
626
|
-
return group.fieldGroup;
|
|
627
|
-
}
|
|
628
|
-
async getFormFieldGroupForSchema(name, customizeOrOptions) {
|
|
629
|
-
this.schemas = await this.openApi.getSchemas();
|
|
630
|
-
const schemaOptions = ObjectUtils.isObject(customizeOrOptions) ? customizeOrOptions : {};
|
|
631
|
-
const customizeConfig = ObjectUtils.isFunction(customizeOrOptions) ? customizeOrOptions : schemaOptions.customizer;
|
|
632
|
-
const schema = this.schemas[name];
|
|
633
|
-
const wrapOptions = {
|
|
634
|
-
...schemaOptions,
|
|
635
|
-
schema,
|
|
636
|
-
injector: this.injector,
|
|
637
|
-
customizer: async (property, options, config) => {
|
|
638
|
-
config.defaultValue = `${config.type}`.startsWith("date")
|
|
639
|
-
? this.convertToDate(property.default) : property.default;
|
|
640
|
-
if (!ObjectUtils.isFunction(customizeConfig))
|
|
641
|
-
return [config];
|
|
642
|
-
let res = customizeConfig(property, schema, config, options, this.injector);
|
|
643
|
-
if (!res)
|
|
644
|
-
return [config];
|
|
645
|
-
if (res instanceof Promise) {
|
|
646
|
-
res = await res;
|
|
647
|
-
}
|
|
648
|
-
return Array.isArray(res) ? res : [res];
|
|
649
|
-
}
|
|
650
|
-
};
|
|
651
|
-
const config = {
|
|
652
|
-
key: FORM_ROOT_KEY,
|
|
653
|
-
path: "",
|
|
654
|
-
wrappers: ["form-group"]
|
|
655
|
-
};
|
|
656
|
-
const fields = await this.getFormFieldsForSchemaDef(schema, config, wrapOptions);
|
|
657
|
-
const fieldGroup = [...fields];
|
|
658
|
-
// Add id fields if necessary
|
|
659
|
-
if (fields.length > 0) {
|
|
660
|
-
const idFields = [
|
|
661
|
-
{ key: "id", props: { hidden: true } },
|
|
662
|
-
{ key: "_id", props: { hidden: true } },
|
|
663
|
-
];
|
|
664
|
-
fieldGroup.unshift(...idFields
|
|
665
|
-
.filter(t => !fields.some(c => c.key == t.key)));
|
|
666
|
-
}
|
|
667
|
-
config.fieldGroup = fieldGroup;
|
|
668
|
-
const root = await wrapOptions.customizer({
|
|
669
|
-
id: FORM_ROOT_KEY,
|
|
670
|
-
type: "object",
|
|
671
|
-
properties: schema?.properties || {}
|
|
672
|
-
}, wrapOptions, config);
|
|
673
|
-
// Check if the customized root wrapper returned an array
|
|
674
|
-
fields.length = 0;
|
|
675
|
-
for (const model of root) {
|
|
676
|
-
if (model.key === FORM_ROOT_KEY) {
|
|
677
|
-
return model;
|
|
678
|
-
}
|
|
679
|
-
else {
|
|
680
|
-
fields.push(model);
|
|
681
|
-
}
|
|
682
|
-
}
|
|
683
|
-
return {
|
|
684
|
-
...config,
|
|
685
|
-
fieldGroup: fields
|
|
686
|
-
};
|
|
687
|
-
}
|
|
688
|
-
async getFormFieldsForSchemaDef(schema, parent, options) {
|
|
652
|
+
async getFormFieldsForSchema(name, parent, customizeOrOptions) {
|
|
653
|
+
const schema = await this.getSchema(name);
|
|
689
654
|
if (!schema)
|
|
690
655
|
return [];
|
|
656
|
+
const options = await toWrapOptions(customizeOrOptions, this.injector, schema);
|
|
691
657
|
const keys = Object.keys(schema.properties || {});
|
|
692
658
|
const fields = [];
|
|
693
659
|
// Collect all properties of this schema def
|
|
694
660
|
for (const key of keys) {
|
|
695
661
|
const property = schema.properties[key];
|
|
696
|
-
const propFields = await this.getFormFieldsForProp(property, options, parent);
|
|
662
|
+
const propFields = await this.getFormFieldsForProp(property, schema, options, parent);
|
|
697
663
|
fields.push(...propFields);
|
|
698
664
|
}
|
|
699
665
|
return this.builder.createFieldSets(fields.filter(f => null !== f), parent, options);
|
|
700
666
|
}
|
|
701
|
-
async getFormFieldsForProp(property, options, parent) {
|
|
667
|
+
async getFormFieldsForProp(property, schema, options, parent) {
|
|
702
668
|
const field = await this.getFormFieldForProp(property, options, parent);
|
|
703
|
-
return !field ? [] : options.
|
|
669
|
+
return !field ? [] : options.customize(field, property, schema);
|
|
704
670
|
}
|
|
705
671
|
async getFormFieldForProp(property, options, parent) {
|
|
706
672
|
const $enum = property.items?.enum || property.enum;
|
|
@@ -754,9 +720,9 @@ class DynamicFormService {
|
|
|
754
720
|
}
|
|
755
721
|
async getFormArrayConfig(property, options, parent) {
|
|
756
722
|
return this.builder.createFormArray(property.id, async (sp) => {
|
|
757
|
-
const subSchemas = findRefs(property)
|
|
723
|
+
const subSchemas = findRefs(property);
|
|
758
724
|
if (subSchemas.length > 0) {
|
|
759
|
-
const subModels = await Promise.all(subSchemas.map(s => this.
|
|
725
|
+
const subModels = await Promise.all(subSchemas.map(s => this.getFormFieldsForSchema(s, sp, options)));
|
|
760
726
|
return mergeFormFields(ObjectUtils.copy(subModels));
|
|
761
727
|
}
|
|
762
728
|
return this.getFormFieldForProp(property.items, options, null);
|
|
@@ -775,9 +741,9 @@ class DynamicFormService {
|
|
|
775
741
|
}, parent, options);
|
|
776
742
|
}
|
|
777
743
|
async getFormGroupConfig(property, options, parent) {
|
|
778
|
-
const subSchemas = findRefs(property).map(ref => this.schemas[ref]);
|
|
779
744
|
return this.builder.createFormGroup(property.id, async (sp) => {
|
|
780
|
-
const
|
|
745
|
+
const subSchemas = findRefs(property);
|
|
746
|
+
const subModels = await Promise.all(subSchemas.map(s => this.getFormFieldsForSchema(s, sp, options)));
|
|
781
747
|
return mergeFormFields(subModels);
|
|
782
748
|
}, {
|
|
783
749
|
...this.getFormFieldData(property, options),
|
|
@@ -827,7 +793,7 @@ class DynamicFormService {
|
|
|
827
793
|
placeholder: property.placeholder || ""
|
|
828
794
|
}, parent, options);
|
|
829
795
|
}
|
|
830
|
-
// getFormEditorConfig(property: IOpenApiSchemaProperty, options:
|
|
796
|
+
// getFormEditorConfig(property: IOpenApiSchemaProperty, options: ConfigForSchemaWrap): DynamicEditorModelConfig {
|
|
831
797
|
// const sub = property.type == "array" ? property.items || property : property;
|
|
832
798
|
// return Object.assign(
|
|
833
799
|
// this.getFormControlConfig(property, options),
|
|
@@ -851,8 +817,8 @@ class DynamicFormService {
|
|
|
851
817
|
...this.getFormFieldData(property, options),
|
|
852
818
|
type: property.format == "date-time" ? "datetime-local" : "date",
|
|
853
819
|
// format: property.dateFormat || "dd.MM.yyyy",
|
|
854
|
-
min:
|
|
855
|
-
max:
|
|
820
|
+
min: convertToDate(property.min),
|
|
821
|
+
max: convertToDate(property.max),
|
|
856
822
|
}, parent, options);
|
|
857
823
|
}
|
|
858
824
|
getFormSelectConfig(property, options, parent) {
|
|
@@ -975,14 +941,6 @@ class DynamicFormService {
|
|
|
975
941
|
}
|
|
976
942
|
});
|
|
977
943
|
}
|
|
978
|
-
convertToDate(value) {
|
|
979
|
-
if (ObjectUtils.isNullOrUndefined(value))
|
|
980
|
-
return null;
|
|
981
|
-
const date = ObjectUtils.isDate(value)
|
|
982
|
-
? value
|
|
983
|
-
: new Date(value);
|
|
984
|
-
return isNaN(date) ? new Date() : date;
|
|
985
|
-
}
|
|
986
944
|
addPropertyValidators(validators, property) {
|
|
987
945
|
if (!property)
|
|
988
946
|
return;
|
|
@@ -1023,12 +981,155 @@ class DynamicFormService {
|
|
|
1023
981
|
validators.itemsMaxValue = maxValueValidation(items.maximum, true);
|
|
1024
982
|
}
|
|
1025
983
|
}
|
|
1026
|
-
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 });
|
|
1027
1125
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DynamicFormService });
|
|
1028
1126
|
}
|
|
1029
1127
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DynamicFormService, decorators: [{
|
|
1030
1128
|
type: Injectable
|
|
1031
|
-
}], ctorParameters: () => [{ type:
|
|
1129
|
+
}], ctorParameters: () => [{ type: DynamicFormSchemaService }, { type: i0.Injector }, { type: undefined, decorators: [{
|
|
1130
|
+
type: Inject,
|
|
1131
|
+
args: [API_SERVICE]
|
|
1132
|
+
}] }] });
|
|
1032
1133
|
|
|
1033
1134
|
class AsyncSubmitDirective {
|
|
1034
1135
|
method = input(null, { alias: "async-submit" });
|
|
@@ -1132,6 +1233,7 @@ class DynamicFormComponent {
|
|
|
1132
1233
|
events = inject(EventsService);
|
|
1133
1234
|
languages = inject(LANGUAGE_SERVICE);
|
|
1134
1235
|
labelPrefix = input("label");
|
|
1236
|
+
labelCustomizer = input(null);
|
|
1135
1237
|
testId = input("");
|
|
1136
1238
|
data = input({});
|
|
1137
1239
|
fields = input(null);
|
|
@@ -1142,6 +1244,7 @@ class DynamicFormComponent {
|
|
|
1142
1244
|
config = computed(() => {
|
|
1143
1245
|
return this.fields() || this.builder.resolveFormFields(this.data()?.constructor, null, {
|
|
1144
1246
|
labelPrefix: this.labelPrefix(),
|
|
1247
|
+
labelCustomizer: this.labelCustomizer(),
|
|
1145
1248
|
testId: this.testId(),
|
|
1146
1249
|
});
|
|
1147
1250
|
});
|
|
@@ -1180,7 +1283,7 @@ class DynamicFormComponent {
|
|
|
1180
1283
|
this.options?.resetModel?.();
|
|
1181
1284
|
}
|
|
1182
1285
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DynamicFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1183
|
-
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 }, 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 });
|
|
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 });
|
|
1184
1287
|
}
|
|
1185
1288
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DynamicFormComponent, decorators: [{
|
|
1186
1289
|
type: Component,
|
|
@@ -1294,7 +1397,8 @@ class NgxDynamicFormModule {
|
|
|
1294
1397
|
return [
|
|
1295
1398
|
...providers,
|
|
1296
1399
|
DynamicFormService,
|
|
1297
|
-
DynamicFormBuilderService
|
|
1400
|
+
DynamicFormBuilderService,
|
|
1401
|
+
DynamicFormSchemaService
|
|
1298
1402
|
];
|
|
1299
1403
|
}
|
|
1300
1404
|
static forRoot(config) {
|
|
@@ -1360,5 +1464,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
|
|
|
1360
1464
|
* Generated bundle index. Do not edit.
|
|
1361
1465
|
*/
|
|
1362
1466
|
|
|
1363
|
-
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 };
|
|
1364
1468
|
//# sourceMappingURL=stemy-ngx-dynamic-form.mjs.map
|