@stemy/ngx-dynamic-form 19.1.14 → 19.2.1
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-ui-nebular.mjs +4 -4
- package/fesm2022/stemy-ngx-dynamic-form-ui-nebular.mjs.map +1 -1
- package/fesm2022/stemy-ngx-dynamic-form.mjs +858 -1661
- package/fesm2022/stemy-ngx-dynamic-form.mjs.map +1 -1
- package/ngx-dynamic-form/common-types.d.ts +109 -26
- package/ngx-dynamic-form/components/dynamic-form/dynamic-form.component.d.ts +21 -0
- package/ngx-dynamic-form/components/dynamic-form-array/dynamic-form-array.component.d.ts +9 -0
- package/ngx-dynamic-form/components/dynamic-form-chips/dynamic-form-chips.component.d.ts +7 -0
- package/ngx-dynamic-form/components/dynamic-form-field/dynamic-form-field.component.d.ts +6 -0
- package/ngx-dynamic-form/components/dynamic-form-fieldset/dynamic-form-fieldset.component.d.ts +7 -0
- package/ngx-dynamic-form/components/dynamic-form-group/dynamic-form-group.component.d.ts +6 -0
- package/ngx-dynamic-form/components/dynamic-form-upload/dynamic-form-upload.component.d.ts +7 -0
- package/ngx-dynamic-form/directives/async-submit.directive.d.ts +17 -23
- package/ngx-dynamic-form/ngx-dynamic-form.imports.d.ts +5 -9
- package/ngx-dynamic-form/ngx-dynamic-form.module.d.ts +13 -11
- package/ngx-dynamic-form/services/dynamic-form-builder.service.d.ts +27 -0
- package/ngx-dynamic-form/services/dynamic-form.service.d.ts +28 -46
- package/ngx-dynamic-form/utils/customizer.d.ts +5 -12
- package/ngx-dynamic-form/utils/decorators.d.ts +10 -0
- package/ngx-dynamic-form/utils/misc.d.ts +2 -4
- package/ngx-dynamic-form/utils/validation.d.ts +13 -0
- package/package.json +21 -16
- package/public_api.d.ts +13 -18
- package/ui-nebular/index.d.ts +1 -5
- package/common-types.d.ts +0 -37
- package/components/base/dynamic-base-form-array.component.d.ts +0 -38
- package/components/base/dynamic-base-form-control-container.component.d.ts +0 -39
- package/components/base/dynamic-base-form-control.component.d.ts +0 -26
- package/components/base/dynamic-base-form-group.component.d.ts +0 -25
- package/components/base/dynamic-base-form.component.d.ts +0 -46
- package/components/base/dynamic-base-select.component.d.ts +0 -15
- package/directives/async-submit.directive.d.ts +0 -31
- package/esm2020/ngx-dynamic-form/common-types.mjs +0 -2
- package/esm2020/ngx-dynamic-form/components/base/dynamic-base-form-array.component.mjs +0 -104
- package/esm2020/ngx-dynamic-form/components/base/dynamic-base-form-control-container.component.mjs +0 -127
- package/esm2020/ngx-dynamic-form/components/base/dynamic-base-form-control.component.mjs +0 -57
- package/esm2020/ngx-dynamic-form/components/base/dynamic-base-form-group.component.mjs +0 -75
- package/esm2020/ngx-dynamic-form/components/base/dynamic-base-form.component.mjs +0 -182
- package/esm2020/ngx-dynamic-form/components/base/dynamic-base-select.component.mjs +0 -66
- package/esm2020/ngx-dynamic-form/directives/async-submit.directive.mjs +0 -116
- package/esm2020/ngx-dynamic-form/ngx-dynamic-form.imports.mjs +0 -26
- package/esm2020/ngx-dynamic-form/ngx-dynamic-form.module.mjs +0 -116
- package/esm2020/ngx-dynamic-form/services/dynamic-form.service.mjs +0 -615
- package/esm2020/ngx-dynamic-form/utils/creators.mjs +0 -67
- package/esm2020/ngx-dynamic-form/utils/customizer.mjs +0 -28
- package/esm2020/ngx-dynamic-form/utils/dynamic-editor.model.mjs +0 -14
- package/esm2020/ngx-dynamic-form/utils/dynamic-form-array.model.mjs +0 -128
- package/esm2020/ngx-dynamic-form/utils/dynamic-form-group.model.mjs +0 -26
- package/esm2020/ngx-dynamic-form/utils/dynamic-select.model.mjs +0 -59
- package/esm2020/ngx-dynamic-form/utils/form-select-subject.mjs +0 -26
- package/esm2020/ngx-dynamic-form/utils/form-subject.mjs +0 -29
- package/esm2020/ngx-dynamic-form/utils/misc.mjs +0 -47
- package/esm2020/ngx-dynamic-form/utils/validation-errors.mjs +0 -22
- package/esm2020/ngx-dynamic-form/utils/validators.mjs +0 -56
- package/esm2020/public_api.mjs +0 -21
- package/esm2020/stemy-ngx-dynamic-form.mjs +0 -5
- package/fesm2015/stemy-ngx-dynamic-form.mjs +0 -1927
- package/fesm2015/stemy-ngx-dynamic-form.mjs.map +0 -1
- package/fesm2020/stemy-ngx-dynamic-form.mjs +0 -1893
- package/fesm2020/stemy-ngx-dynamic-form.mjs.map +0 -1
- package/fesm2022/stemy-ngx-dynamic-form-src-ngx-dynamic-form-nebular.mjs +0 -50
- package/fesm2022/stemy-ngx-dynamic-form-src-ngx-dynamic-form-nebular.mjs.map +0 -1
- package/imports.d.ts +0 -12
- package/ngx-dynamic-form/components/base/dynamic-base-form-array.component.d.ts +0 -38
- package/ngx-dynamic-form/components/base/dynamic-base-form-control-container.component.d.ts +0 -39
- package/ngx-dynamic-form/components/base/dynamic-base-form-control.component.d.ts +0 -26
- package/ngx-dynamic-form/components/base/dynamic-base-form-group.component.d.ts +0 -25
- package/ngx-dynamic-form/components/base/dynamic-base-form.component.d.ts +0 -46
- package/ngx-dynamic-form/components/base/dynamic-base-select.component.d.ts +0 -15
- package/ngx-dynamic-form/services/dynamic-form-layout.service.d.ts +0 -7
- package/ngx-dynamic-form/utils/creators.d.ts +0 -18
- package/ngx-dynamic-form/utils/dynamic-editor.model.d.ts +0 -11
- package/ngx-dynamic-form/utils/dynamic-form-array.model.d.ts +0 -69
- package/ngx-dynamic-form/utils/dynamic-form-group.model.d.ts +0 -14
- package/ngx-dynamic-form/utils/dynamic-select.model.d.ts +0 -39
- package/ngx-dynamic-form/utils/form-select-subject.d.ts +0 -6
- package/ngx-dynamic-form/utils/form-subject.d.ts +0 -10
- package/ngx-dynamic-form/utils/validators.d.ts +0 -8
- package/ngx-dynamic-form.imports.d.ts +0 -12
- package/ngx-dynamic-form.module.d.ts +0 -21
- package/services/dynamic-form.service.d.ts +0 -61
- package/src/ngx-dynamic-form/nebular/imports.d.ts +0 -4
- package/src/ngx-dynamic-form/nebular/index.d.ts +0 -5
- package/src/ngx-dynamic-form/nebular/ngx-dynamic-form.nebular.module.d.ts +0 -9
- package/src/ngx-dynamic-form/nebular/public_api.d.ts +0 -1
- package/stemy-ngx-dynamic-form.d.ts +0 -5
- package/ui-nebular/public_api.d.ts +0 -1
- package/utils/creators.d.ts +0 -18
- package/utils/customizer.d.ts +0 -14
- package/utils/dynamic-editor.model.d.ts +0 -11
- package/utils/dynamic-form-array.model.d.ts +0 -69
- package/utils/dynamic-form-group.model.d.ts +0 -14
- package/utils/dynamic-select.model.d.ts +0 -39
- package/utils/form-select-subject.d.ts +0 -6
- package/utils/form-subject.d.ts +0 -10
- package/utils/misc.d.ts +0 -11
- package/utils/validation-errors.d.ts +0 -11
- package/utils/validators.d.ts +0 -8
|
@@ -1,324 +1,174 @@
|
|
|
1
|
-
import * as i1 from '@ng-dynamic-forms/core';
|
|
2
|
-
import { DynamicInputControlModel, DYNAMIC_FORM_CONTROL_TYPE_EDITOR, serializable, DynamicFormArrayGroupModel as DynamicFormArrayGroupModel$1, DynamicFormArrayModel as DynamicFormArrayModel$1, DynamicFormGroupModel as DynamicFormGroupModel$1, DynamicFormOption as DynamicFormOption$1, DynamicSelectModel as DynamicSelectModel$1, DynamicCheckboxModel, DynamicDatePickerModel, DynamicInputModel, DynamicTextAreaModel, DynamicFileUploadModel, DynamicFormService as DynamicFormService$1, DynamicRadioGroupModel, DynamicFormValueControlModel, isString, DynamicFormComponent, DynamicTemplateDirective, DynamicFormControlContainerComponent, DYNAMIC_FORM_CONTROL_TYPE_ARRAY, DynamicFormArrayComponent, DynamicFormControlComponent, DynamicFormGroupComponent, DYNAMIC_FORM_CONTROL_MAP_FN, DYNAMIC_VALIDATORS } from '@ng-dynamic-forms/core';
|
|
3
|
-
export { DYNAMIC_FORM_CONTROL_TYPE_ARRAY, DYNAMIC_FORM_CONTROL_TYPE_CHECKBOX, DYNAMIC_FORM_CONTROL_TYPE_CHECKBOX_GROUP, DYNAMIC_FORM_CONTROL_TYPE_DATEPICKER, DYNAMIC_FORM_CONTROL_TYPE_EDITOR, DYNAMIC_FORM_CONTROL_TYPE_FILE_UPLOAD, DYNAMIC_FORM_CONTROL_TYPE_GROUP, DYNAMIC_FORM_CONTROL_TYPE_INPUT, DYNAMIC_FORM_CONTROL_TYPE_RADIO_GROUP, DYNAMIC_FORM_CONTROL_TYPE_SELECT, DYNAMIC_FORM_CONTROL_TYPE_TEXTAREA, DynamicCheckboxGroupModel, DynamicCheckboxModel, DynamicDatePickerModel, DynamicFileUploadModel, DynamicFormControlComponent, DynamicFormControlModel, DynamicFormsCoreModule, DynamicInputModel, DynamicListDirective, DynamicRadioGroupModel, DynamicTemplateDirective, DynamicTextAreaModel } from '@ng-dynamic-forms/core';
|
|
4
1
|
import * as i2 from '@stemy/ngx-utils';
|
|
5
|
-
import {
|
|
6
|
-
import { __decorate } from 'tslib';
|
|
7
|
-
import { BehaviorSubject, isObservable, of, Subject, firstValueFrom, Subscription } from 'rxjs';
|
|
8
|
-
import { map, debounceTime, first, groupBy, mergeMap } from 'rxjs/operators';
|
|
2
|
+
import { cachedFactory, ReflectUtils, ObjectUtils, LANGUAGE_SERVICE, API_SERVICE, StringUtils, TOASTER_SERVICE, NgxUtilsModule } from '@stemy/ngx-utils';
|
|
9
3
|
import * as i0 from '@angular/core';
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
4
|
+
import { Inject, Injectable, input, output, inject, Renderer2, ElementRef, computed, signal, effect, HostListener, HostBinding, Directive, resource, Injector, ChangeDetectionStrategy, ViewEncapsulation, Component, makeEnvironmentProviders, NgModule } from '@angular/core';
|
|
5
|
+
import { startWith, distinctUntilChanged, switchMap, first, from, isObservable, firstValueFrom } from 'rxjs';
|
|
6
|
+
import * as i1 from '@angular/forms';
|
|
7
|
+
import { FormGroup as FormGroup$1, FormArray as FormArray$1, FormsModule, ReactiveFormsModule } from '@angular/forms';
|
|
8
|
+
import { outputToObservable, rxResource } from '@angular/core/rxjs-interop';
|
|
9
|
+
import { debounceTime } from 'rxjs/operators';
|
|
10
|
+
import * as i3 from '@ngx-formly/core';
|
|
11
|
+
import { FieldArrayType, FieldType, FieldWrapper, FormlyModule } from '@ngx-formly/core';
|
|
12
|
+
import * as i1$1 from '@angular/common';
|
|
12
13
|
import { CommonModule } from '@angular/common';
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
15
|
+
// --- Basic frm constants ---
|
|
16
|
+
const FORM_ROOT_KEY = "__root";
|
|
17
|
+
|
|
18
|
+
function customizeFormField(...providers) {
|
|
19
|
+
const factory = cachedFactory(providers);
|
|
20
|
+
return async (property, schema, config, parent, options, injector) => {
|
|
21
|
+
const customizers = factory(injector);
|
|
22
|
+
const configs = [config];
|
|
23
|
+
for (const customizer of customizers) {
|
|
24
|
+
const index = configs.findIndex(m => customizer.acceptField(m, parent));
|
|
25
|
+
if (index >= 0) {
|
|
26
|
+
const custom = await customizer.customizeField(configs[index], property, schema, parent, options);
|
|
27
|
+
const result = Array.isArray(custom) ? custom : [custom];
|
|
28
|
+
configs.splice(index, 1, ...result);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return configs;
|
|
32
|
+
};
|
|
23
33
|
}
|
|
24
|
-
__decorate([
|
|
25
|
-
serializable()
|
|
26
|
-
], DynamicEditorModel.prototype, "type", void 0);
|
|
27
34
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
isHidden;
|
|
40
|
-
constructor(context, group, index = -1) {
|
|
41
|
-
super(context, group, index);
|
|
42
|
-
this.context = context;
|
|
43
|
-
this.isHidden = false;
|
|
44
|
-
}
|
|
35
|
+
function defineFormControl(target, propertyKey, cb) {
|
|
36
|
+
const fields = ReflectUtils.getMetadata("dynamicFormFields", target) || new Set();
|
|
37
|
+
const existing = ReflectUtils.getMetadata("dynamicFormField", target, propertyKey);
|
|
38
|
+
const builder = !ObjectUtils.isFunction(existing) ? cb : ((fb, opts, path) => {
|
|
39
|
+
const data = existing(fb, opts, path);
|
|
40
|
+
return ObjectUtils.assign(data || {}, cb(fb, opts, path) || {});
|
|
41
|
+
});
|
|
42
|
+
fields.add(propertyKey);
|
|
43
|
+
ReflectUtils.defineMetadata("dynamicFormField", builder, target, propertyKey);
|
|
44
|
+
ReflectUtils.defineMetadata("dynamicFormFields", fields, target);
|
|
45
45
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
return this.config.addItem !== false;
|
|
64
|
-
}
|
|
65
|
-
get insertItem() {
|
|
66
|
-
return !this._sortBy && this.config.insertItem !== false;
|
|
67
|
-
}
|
|
68
|
-
get cloneItem() {
|
|
69
|
-
return this.config.cloneItem !== false;
|
|
70
|
-
}
|
|
71
|
-
get moveItem() {
|
|
72
|
-
return !this._sortBy && this.config.moveItem !== false;
|
|
73
|
-
}
|
|
74
|
-
get removeItem() {
|
|
75
|
-
return this.config.removeItem !== false;
|
|
76
|
-
}
|
|
77
|
-
get clearItems() {
|
|
78
|
-
return this.config.clearItems !== false;
|
|
79
|
-
}
|
|
80
|
-
get sortBy() {
|
|
81
|
-
return this._sortBy;
|
|
82
|
-
}
|
|
83
|
-
set sortBy(value) {
|
|
84
|
-
if (!this.sortable)
|
|
85
|
-
return;
|
|
86
|
-
value = value || null;
|
|
87
|
-
if (this._sortBy !== value) {
|
|
88
|
-
this._sortBy = value;
|
|
89
|
-
this._sortDescending = false;
|
|
90
|
-
}
|
|
91
|
-
else if (this._sortDescending) {
|
|
92
|
-
this._sortBy = null;
|
|
93
|
-
this._sortDescending = false;
|
|
94
|
-
}
|
|
95
|
-
else {
|
|
96
|
-
this._sortDescending = true;
|
|
46
|
+
function FormSerializable(serializer) {
|
|
47
|
+
return (target, key) => {
|
|
48
|
+
defineFormControl(target, key, () => ({ key, serializer, serialize: true }));
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function FormInput(data) {
|
|
52
|
+
return (target, key) => {
|
|
53
|
+
const meta = ReflectUtils.getOwnMetadata("design:type", target, key);
|
|
54
|
+
const type = meta ? meta.name : "";
|
|
55
|
+
let inputType = key.indexOf("password") < 0 ? "text" : "password";
|
|
56
|
+
switch (type) {
|
|
57
|
+
case "Number":
|
|
58
|
+
inputType = "number";
|
|
59
|
+
break;
|
|
60
|
+
case "Boolean":
|
|
61
|
+
inputType = "checkbox";
|
|
62
|
+
break;
|
|
97
63
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
64
|
+
data.type = data.type || inputType;
|
|
65
|
+
defineFormControl(target, key, (fb, path, options) => fb.createFormInput(key, data, path, options));
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
function FormSelect(data) {
|
|
69
|
+
return (target, key) => {
|
|
70
|
+
defineFormControl(target, key, (fb, path, options) => fb.createFormSelect(key, data, path, options));
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
function FormUpload(data) {
|
|
74
|
+
return (target, key) => {
|
|
75
|
+
defineFormControl(target, key, (fb, path, options) => fb.createFormUpload(key, data, path, options));
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function FormFile(data) {
|
|
79
|
+
console.warn(`@FormFile decorator is deprecated, use @FormUpload instead`);
|
|
80
|
+
return FormUpload(data);
|
|
81
|
+
}
|
|
82
|
+
function FormGroup(data) {
|
|
83
|
+
return (target, key) => {
|
|
84
|
+
defineFormControl(target, key, (fb, path, options) => {
|
|
85
|
+
const targetType = ReflectUtils.getOwnMetadata("design:type", target, key);
|
|
86
|
+
return fb.resolveFormGroup(key, targetType, data, path, options);
|
|
117
87
|
});
|
|
118
|
-
|
|
119
|
-
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function FormArray(itemType, data) {
|
|
91
|
+
return (target, key) => {
|
|
92
|
+
defineFormControl(target, key, (fb, path, options) => {
|
|
93
|
+
return fb.resolveFormArray(key, itemType, data, path, options);
|
|
120
94
|
});
|
|
121
|
-
|
|
122
|
-
this.tabIndex = 0;
|
|
123
|
-
this._sortBy = null;
|
|
124
|
-
this._sortDescending = false;
|
|
125
|
-
this._formArray = null;
|
|
126
|
-
}
|
|
127
|
-
initialize(array) {
|
|
128
|
-
this._formArray = array || this._formArray;
|
|
129
|
-
this.filterGroups();
|
|
130
|
-
}
|
|
131
|
-
filterGroups() {
|
|
132
|
-
this._filterTimer = this._filterTimer || TimerUtils.createTimeout();
|
|
133
|
-
this._filterTimer.set(() => {
|
|
134
|
-
const filtered = this.groups.filter(g => !g.hidden);
|
|
135
|
-
if (this._sortBy && this._formArray) {
|
|
136
|
-
const compare = this._sortDescending
|
|
137
|
-
? (a, b) => this.compareModels(b, a)
|
|
138
|
-
: (a, b) => this.compareModels(a, b);
|
|
139
|
-
filtered.sort(compare);
|
|
140
|
-
}
|
|
141
|
-
this._filteredGroups = filtered;
|
|
142
|
-
this.filteredGroups.next(filtered);
|
|
143
|
-
}, 100);
|
|
144
|
-
}
|
|
145
|
-
getFiltered(index) {
|
|
146
|
-
return !this._filteredGroups ? null : this._filteredGroups[index];
|
|
147
|
-
}
|
|
148
|
-
insertGroup(index) {
|
|
149
|
-
const group = new DynamicFormArrayGroupModel(this, this.groupFactory());
|
|
150
|
-
this.groups.splice(index, 0, group);
|
|
151
|
-
this.groups.forEach((g, index) => g.index = index);
|
|
152
|
-
this.filterGroups();
|
|
153
|
-
return group;
|
|
154
|
-
}
|
|
155
|
-
moveGroup(index, step) {
|
|
156
|
-
super.moveGroup(index, step);
|
|
157
|
-
this.filterGroups();
|
|
158
|
-
}
|
|
159
|
-
removeGroup(index) {
|
|
160
|
-
super.removeGroup(index);
|
|
161
|
-
this.filterGroups();
|
|
162
|
-
}
|
|
163
|
-
compareModels(a, b) {
|
|
164
|
-
const aGroup = this._formArray.at(a.index).get(this._sortBy)?.value || null;
|
|
165
|
-
const bGroup = this._formArray.at(b.index).get(this._sortBy)?.value || null;
|
|
166
|
-
return ObjectUtils.compare(aGroup, bGroup);
|
|
167
|
-
}
|
|
95
|
+
};
|
|
168
96
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
constructor(config, layout) {
|
|
173
|
-
super(config, layout);
|
|
174
|
-
const controls = [...config.group];
|
|
175
|
-
const groups = [];
|
|
176
|
-
const sets = config.fieldSets || [];
|
|
177
|
-
for (const fs of sets) {
|
|
178
|
-
const fields = [];
|
|
179
|
-
for (const f of fs.fields) {
|
|
180
|
-
const ix = controls.findIndex(c => c.id === f);
|
|
181
|
-
if (ix < 0)
|
|
182
|
-
continue;
|
|
183
|
-
fields.push(controls.splice(ix, 1)[0]);
|
|
184
|
-
}
|
|
185
|
-
if (fields.length === 0)
|
|
186
|
-
continue;
|
|
187
|
-
groups.push({ id: fs.id, legend: fs.legend, fields });
|
|
188
|
-
}
|
|
189
|
-
if (controls.length > 0) {
|
|
190
|
-
groups.unshift({ id: "root-controls", legend: config.legend, fields: controls });
|
|
191
|
-
}
|
|
192
|
-
this.groups = groups;
|
|
193
|
-
}
|
|
97
|
+
function FormModel(data) {
|
|
98
|
+
console.warn(`@FormModel decorator is deprecated, use @FormGroup instead`);
|
|
99
|
+
return FormGroup(data);
|
|
194
100
|
}
|
|
195
101
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
super(config);
|
|
202
|
-
this.classes = config.classes || "";
|
|
203
|
-
this.props = Object.keys(config).reduce((res, k) => {
|
|
204
|
-
if (ignoredKeys.indexOf(k) >= 0)
|
|
205
|
-
return res;
|
|
206
|
-
res[k] = config[k];
|
|
207
|
-
return res;
|
|
208
|
-
}, {});
|
|
209
|
-
}
|
|
102
|
+
function validationMessage(injector, key, labelPrefix) {
|
|
103
|
+
const language = injector.get(LANGUAGE_SERVICE);
|
|
104
|
+
return (_, field) => {
|
|
105
|
+
return language.getTranslationSync(labelPrefix ? `${labelPrefix}.error.${key}` : `error.${key}`, field);
|
|
106
|
+
};
|
|
210
107
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
getClasses;
|
|
215
|
-
allowEmpty;
|
|
216
|
-
options$ = null;
|
|
217
|
-
mOptions = [];
|
|
218
|
-
constructor(config, layout) {
|
|
219
|
-
super(config, layout);
|
|
220
|
-
this.groupBy = config.groupBy || null;
|
|
221
|
-
this.inline = config.inline || false;
|
|
222
|
-
this.getClasses = ObjectUtils.isFunction(config.getClasses) ? config.getClasses : (() => "");
|
|
223
|
-
this.allowEmpty = config.allowEmpty || false;
|
|
224
|
-
this.options = config.options;
|
|
225
|
-
}
|
|
226
|
-
set options(options) {
|
|
227
|
-
if (Array.isArray(options)) {
|
|
228
|
-
this.mOptions = options.map(optionConfig => new DynamicFormOption(optionConfig));
|
|
229
|
-
this.updateOptions();
|
|
230
|
-
}
|
|
231
|
-
else if (isObservable(options)) {
|
|
232
|
-
this.options$ = options.pipe(map(optionsConfig => {
|
|
233
|
-
this.mOptions = optionsConfig.map(optionConfig => new DynamicFormOption(optionConfig));
|
|
234
|
-
return this.mOptions;
|
|
235
|
-
}));
|
|
236
|
-
}
|
|
237
|
-
else {
|
|
238
|
-
this.updateOptions();
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
get options() {
|
|
242
|
-
return this.mOptions;
|
|
243
|
-
}
|
|
244
|
-
insert(index, optionConfig) {
|
|
245
|
-
const option = new DynamicFormOption(optionConfig);
|
|
246
|
-
this.mOptions.splice(index, 0, option);
|
|
247
|
-
this.updateOptions();
|
|
248
|
-
return option;
|
|
249
|
-
}
|
|
250
|
-
remove(...indices) {
|
|
251
|
-
indices.forEach(index => this.mOptions.splice(index, 1));
|
|
252
|
-
this.updateOptions();
|
|
253
|
-
}
|
|
254
|
-
updateOptions() {
|
|
255
|
-
this.options$ = of(this.mOptions);
|
|
256
|
-
}
|
|
108
|
+
function withName(fn, name) {
|
|
109
|
+
fn.validatorName = name;
|
|
110
|
+
return fn;
|
|
257
111
|
}
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
res.disabled = config.disabled || false;
|
|
264
|
-
res.hidden = config.hidden || false;
|
|
265
|
-
res.additional = Object.assign({
|
|
266
|
-
// For material components
|
|
267
|
-
appearance: "fill",
|
|
268
|
-
}, res.additional || {});
|
|
269
|
-
return res;
|
|
112
|
+
function validateEach(each, cb, name) {
|
|
113
|
+
return withName((control) => {
|
|
114
|
+
const value = control.value;
|
|
115
|
+
return each ? Array.isArray(value) && value.every(cb) : cb(value);
|
|
116
|
+
}, name);
|
|
270
117
|
}
|
|
271
|
-
function
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
118
|
+
function jsonValidation() {
|
|
119
|
+
return withName((control) => {
|
|
120
|
+
const value = control.value;
|
|
121
|
+
if (!value)
|
|
122
|
+
return false;
|
|
123
|
+
try {
|
|
124
|
+
JSON.parse(value);
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
catch (e) {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
}, "json");
|
|
275
131
|
}
|
|
276
|
-
function
|
|
277
|
-
|
|
278
|
-
res.autoFocus = config.autoFocus || false;
|
|
279
|
-
res.focusedDate = config.focusedDate || new Date();
|
|
280
|
-
res.inline = config.inline || false;
|
|
281
|
-
return new DynamicDatePickerModel(res, layout);
|
|
132
|
+
function requiredValidation() {
|
|
133
|
+
return withName((control) => ObjectUtils.isString(control.value) ? control.value.length > 0 : ObjectUtils.isDefined(control.value), "required");
|
|
282
134
|
}
|
|
283
|
-
function
|
|
284
|
-
|
|
285
|
-
|
|
135
|
+
function translationValidation(langs = ["de", "en"]) {
|
|
136
|
+
return withName((control) => {
|
|
137
|
+
const value = control.value;
|
|
138
|
+
if (!value || value.length == 0)
|
|
139
|
+
return false;
|
|
140
|
+
return value.findIndex(t => langs.includes(t.lang) && !t.translation) < 0;
|
|
141
|
+
}, "translation");
|
|
286
142
|
}
|
|
287
|
-
function
|
|
288
|
-
|
|
289
|
-
|
|
143
|
+
function phoneValidation() {
|
|
144
|
+
return withName((control) => {
|
|
145
|
+
const value = control.value;
|
|
146
|
+
if (!value)
|
|
147
|
+
return true;
|
|
148
|
+
const phoneRegexp = /^\d{10,12}$/;
|
|
149
|
+
return phoneRegexp.test(value);
|
|
150
|
+
}, "phone");
|
|
290
151
|
}
|
|
291
|
-
function
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
152
|
+
function emailValidation() {
|
|
153
|
+
return withName((control) => {
|
|
154
|
+
const value = control.value;
|
|
155
|
+
if (!value)
|
|
156
|
+
return true;
|
|
157
|
+
const emailRegexp = /^[\w-.]+@([\w-]+\.)+[\w-]{2,4}$/g;
|
|
158
|
+
return emailRegexp.test(value);
|
|
159
|
+
}, "email");
|
|
295
160
|
}
|
|
296
|
-
function
|
|
297
|
-
|
|
298
|
-
res.inputType = config.inputType || type;
|
|
299
|
-
res.placeholder = config.placeholder || (config.inputType == "mask" ? "_" : "");
|
|
300
|
-
res.step = config.step || 1;
|
|
301
|
-
res.mask = config.mask || null;
|
|
302
|
-
return new DynamicInputModel(res, layout);
|
|
161
|
+
function minLengthValidation(minLength, each) {
|
|
162
|
+
return validateEach(each, v => typeof v == "string" && v.length >= minLength, "minLength");
|
|
303
163
|
}
|
|
304
|
-
function
|
|
305
|
-
|
|
306
|
-
res.options = config.options || [];
|
|
307
|
-
return new DynamicSelectModel(res, layout);
|
|
164
|
+
function maxLengthValidation(maxLength, each) {
|
|
165
|
+
return validateEach(each, v => typeof v == "string" && v.length <= maxLength, "maxLength");
|
|
308
166
|
}
|
|
309
|
-
function
|
|
310
|
-
|
|
311
|
-
res.cols = config.cols || 10;
|
|
312
|
-
res.rows = config.rows || 3;
|
|
313
|
-
res.wrap = config.wrap || "soft";
|
|
314
|
-
return new DynamicTextAreaModel(res, layout);
|
|
167
|
+
function minValueValidation(min, each) {
|
|
168
|
+
return validateEach(each, v => typeof v == "number" && v >= min, "minValue");
|
|
315
169
|
}
|
|
316
|
-
function
|
|
317
|
-
|
|
318
|
-
res.accept = config.accept || ["jpg", "jpeg", "png"];
|
|
319
|
-
res.multiple = config.multiple || false;
|
|
320
|
-
res.url = ObjectUtils.isString(config.url) ? config.url : "assets";
|
|
321
|
-
return new DynamicFileUploadModel(res, layout);
|
|
170
|
+
function maxValueValidation(max, each) {
|
|
171
|
+
return validateEach(each, v => typeof v == "number" && v <= max, "maxValue");
|
|
322
172
|
}
|
|
323
173
|
|
|
324
174
|
function isStringWithVal(val) {
|
|
@@ -333,11 +183,11 @@ function findRefs(property) {
|
|
|
333
183
|
function replaceSpecialChars(str, to = "-") {
|
|
334
184
|
return `${str}`.replace(/[&\/\\#, +()$~%.@'":*?<>{}]/g, to);
|
|
335
185
|
}
|
|
336
|
-
function
|
|
186
|
+
function mergeFormFields(formFields) {
|
|
337
187
|
const res = [];
|
|
338
|
-
for (const formModel of
|
|
188
|
+
for (const formModel of formFields) {
|
|
339
189
|
for (const subModel of formModel) {
|
|
340
|
-
const index = res.findIndex(t => t.
|
|
190
|
+
const index = res.findIndex(t => t.key == subModel.key);
|
|
341
191
|
if (index >= 0) {
|
|
342
192
|
res[index] = subModel;
|
|
343
193
|
continue;
|
|
@@ -347,176 +197,263 @@ function mergeFormModels(formModels) {
|
|
|
347
197
|
}
|
|
348
198
|
return res;
|
|
349
199
|
}
|
|
350
|
-
function collectPathAble(start, getter) {
|
|
351
|
-
if (!start || !getter(start))
|
|
352
|
-
return [];
|
|
353
|
-
const parts = [];
|
|
354
|
-
let currentPath = start;
|
|
355
|
-
while (currentPath) {
|
|
356
|
-
const val = getter(currentPath);
|
|
357
|
-
if (val) {
|
|
358
|
-
parts.unshift(val);
|
|
359
|
-
}
|
|
360
|
-
currentPath = currentPath.parent;
|
|
361
|
-
}
|
|
362
|
-
return parts;
|
|
363
|
-
}
|
|
364
|
-
function getDynamicPath(start) {
|
|
365
|
-
return collectPathAble(start, t => t.id).join(".");
|
|
366
|
-
}
|
|
367
200
|
const MIN_INPUT_NUM = -999999999;
|
|
368
201
|
const MAX_INPUT_NUM = 999999999;
|
|
369
202
|
const EDITOR_FORMATS = ["php", "json", "html", "css", "scss"];
|
|
370
203
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
204
|
+
class DynamicFormBuilderService {
|
|
205
|
+
injector;
|
|
206
|
+
api;
|
|
207
|
+
language;
|
|
208
|
+
constructor(injector, api, language) {
|
|
209
|
+
this.injector = injector;
|
|
210
|
+
this.api = api;
|
|
211
|
+
this.language = language;
|
|
212
|
+
}
|
|
213
|
+
getLabel(key, label, parent, options) {
|
|
214
|
+
const labelPrefix = !ObjectUtils.isString(options.labelPrefix) ? `` : options.labelPrefix;
|
|
215
|
+
const pathPrefix = `${parent?.props?.label || labelPrefix}`;
|
|
216
|
+
const labelItems = ObjectUtils.isString(label)
|
|
217
|
+
? (!label ? [] : [labelPrefix, label])
|
|
218
|
+
: [pathPrefix, `${key || ""}`];
|
|
219
|
+
return labelItems.filter(l => l.length > 0).join(".");
|
|
220
|
+
}
|
|
221
|
+
createFormField(key, type, data, props, parent, options) {
|
|
222
|
+
const validators = Array.isArray(data.validators)
|
|
223
|
+
? data.validators.reduce((res, validator, ix) => {
|
|
224
|
+
res[validator.validatorName || `validator_${ix}`] = validator;
|
|
225
|
+
return res;
|
|
226
|
+
}, {})
|
|
227
|
+
: data.validators || {};
|
|
228
|
+
return {
|
|
229
|
+
key,
|
|
230
|
+
type,
|
|
231
|
+
validators,
|
|
232
|
+
parent,
|
|
233
|
+
className: Array.isArray(data.classes) ? data.classes.join(" ") : data.classes || "",
|
|
234
|
+
hide: data.hidden === true,
|
|
235
|
+
fieldSet: String(data.fieldSet || ""),
|
|
236
|
+
validation: {
|
|
237
|
+
messages: Object.keys(validators).reduce((res, key) => {
|
|
238
|
+
res[key] = validationMessage(this.injector, key, options.labelPrefix);
|
|
239
|
+
return res;
|
|
240
|
+
}, {})
|
|
241
|
+
},
|
|
242
|
+
props: {
|
|
243
|
+
...props,
|
|
244
|
+
formCheck: "nolabel",
|
|
245
|
+
required: !!validators.required,
|
|
246
|
+
label: this.getLabel(key, data.label, parent, options),
|
|
379
247
|
}
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
if (index >= 0) {
|
|
392
|
-
const custom = await customizer.customizeModel(models[index], config, property, schema, path);
|
|
393
|
-
const result = Array.isArray(custom) ? custom : [custom];
|
|
394
|
-
models.splice(index, 1, ...result);
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
resolveFormFields(target, parent, options) {
|
|
251
|
+
const prototype = target?.prototype || {};
|
|
252
|
+
const fields = ReflectUtils.getMetadata("dynamicFormFields", target?.prototype || {}) || new Set();
|
|
253
|
+
const result = [];
|
|
254
|
+
for (const key of fields) {
|
|
255
|
+
const builder = ReflectUtils.getMetadata("dynamicFormField", prototype, key);
|
|
256
|
+
const field = builder(this, parent, options);
|
|
257
|
+
if (field) {
|
|
258
|
+
result.push(field);
|
|
395
259
|
}
|
|
396
260
|
}
|
|
397
|
-
return
|
|
398
|
-
};
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
function validateJSON(control) {
|
|
402
|
-
const value = control.value;
|
|
403
|
-
if (!value)
|
|
404
|
-
return null;
|
|
405
|
-
try {
|
|
406
|
-
JSON.parse(value);
|
|
407
|
-
return null;
|
|
408
|
-
}
|
|
409
|
-
catch (e) {
|
|
410
|
-
return { json: true };
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
function validateRequiredTranslation(control) {
|
|
414
|
-
const value = control.value;
|
|
415
|
-
if (!value || value.length == 0)
|
|
416
|
-
return { requiredTranslation: true };
|
|
417
|
-
return value.findIndex(t => (t.lang == "de" || t.lang == "en") && !t.translation) < 0
|
|
418
|
-
? null
|
|
419
|
-
: { requiredTranslation: true };
|
|
420
|
-
}
|
|
421
|
-
function validatePhone(control) {
|
|
422
|
-
const value = control.value;
|
|
423
|
-
if (!value)
|
|
424
|
-
return Promise.resolve(null);
|
|
425
|
-
const phoneRegexp = /^(?:\d){10,12}$/;
|
|
426
|
-
return phoneRegexp.test(value) ? null : { phone: true };
|
|
427
|
-
}
|
|
428
|
-
function validateItemsMinLength(minLength) {
|
|
429
|
-
return (control) => {
|
|
430
|
-
const value = control.value;
|
|
431
|
-
return (Array.isArray(value) && value.every(v => typeof v == "string" && v.length >= minLength))
|
|
432
|
-
? null : { itemsMinLength: minLength };
|
|
433
|
-
};
|
|
434
|
-
}
|
|
435
|
-
function validateItemsMaxLength(maxLength) {
|
|
436
|
-
return (control) => {
|
|
437
|
-
const value = control.value;
|
|
438
|
-
return (Array.isArray(value) && value.every(v => typeof v == "string" && v.length <= maxLength))
|
|
439
|
-
? null : { itemsMaxLength: maxLength };
|
|
440
|
-
};
|
|
441
|
-
}
|
|
442
|
-
function validateItemsMinValue(min) {
|
|
443
|
-
return (control) => {
|
|
444
|
-
const value = control.value;
|
|
445
|
-
return (Array.isArray(value) && value.every(v => typeof v == "number" && v >= min))
|
|
446
|
-
? null : { itemsMinValue: min };
|
|
447
|
-
};
|
|
448
|
-
}
|
|
449
|
-
function validateItemsMaxValue(max) {
|
|
450
|
-
return (control) => {
|
|
451
|
-
const value = control.value;
|
|
452
|
-
return (Array.isArray(value) && value.every(v => typeof v == "number" && v <= max))
|
|
453
|
-
? null : { itemsMaxValue: max };
|
|
454
|
-
};
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
const indexLabels = ["$ix", "$pix"];
|
|
458
|
-
class FormSubject extends Subject {
|
|
459
|
-
notifyCallback;
|
|
460
|
-
constructor(notifyCallback) {
|
|
461
|
-
super();
|
|
462
|
-
this.notifyCallback = notifyCallback;
|
|
261
|
+
return this.createFieldSets(result, parent, options);
|
|
463
262
|
}
|
|
464
|
-
|
|
465
|
-
|
|
263
|
+
resolveFormGroup(key, target, data, parent = null, options = {}) {
|
|
264
|
+
return this.createFormGroup(key, sp => this.resolveFormFields(target, sp, options), data, parent, options);
|
|
466
265
|
}
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
while (path) {
|
|
472
|
-
if (!isNaN(path.index)) {
|
|
473
|
-
const key = indexLabels[ix++] || `$pix${ix}`;
|
|
474
|
-
indexes[key] = path.index;
|
|
475
|
-
}
|
|
476
|
-
path = path.parent;
|
|
477
|
-
}
|
|
478
|
-
let value = this.notifyCallback(controlModel, control, root, indexes);
|
|
479
|
-
if (!(value instanceof Promise)) {
|
|
480
|
-
value = Promise.resolve(value);
|
|
481
|
-
}
|
|
482
|
-
this.handleNotifiedValue(controlModel, control, value);
|
|
266
|
+
resolveFormArray(key, itemType, data, parent = null, options = {}) {
|
|
267
|
+
return this.createFormArray(key, sp => {
|
|
268
|
+
return typeof itemType === "function" ? this.resolveFormFields(itemType, sp, options) : this.createFormInput("", typeof itemType === "string" ? { type: `${itemType}` } : itemType, null, options);
|
|
269
|
+
}, data, parent, options);
|
|
483
270
|
}
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
271
|
+
createFieldSets(fields, parent, options) {
|
|
272
|
+
const others = [];
|
|
273
|
+
const groups = {};
|
|
274
|
+
for (const field of fields) {
|
|
275
|
+
const fsName = field.hide ? null : String(field.fieldSet || "");
|
|
276
|
+
// If we have a fieldset name defined and have actual fields for it
|
|
277
|
+
// then push the property fields into a group
|
|
278
|
+
if (fsName) {
|
|
279
|
+
const group = groups[fsName] || [];
|
|
280
|
+
groups[fsName] = group;
|
|
281
|
+
group.push(field);
|
|
282
|
+
continue;
|
|
492
283
|
}
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
284
|
+
// Otherwise just push the fields to the others
|
|
285
|
+
others.push(field);
|
|
286
|
+
}
|
|
287
|
+
// Create a field-set wrapper for each group and concat the other fields to the end
|
|
288
|
+
return Object.keys(groups).map(group => {
|
|
289
|
+
return {
|
|
290
|
+
fieldGroup: groups[group],
|
|
291
|
+
wrappers: ["form-fieldset"],
|
|
292
|
+
id: !parent ? group : `${parent.props?.label}.${group}`,
|
|
293
|
+
props: {
|
|
294
|
+
label: this.getLabel(group, group, parent, options),
|
|
295
|
+
hidden: false
|
|
498
296
|
}
|
|
297
|
+
};
|
|
298
|
+
}).concat(others);
|
|
299
|
+
}
|
|
300
|
+
createFormInput(key, data, parent, options) {
|
|
301
|
+
data = data || {};
|
|
302
|
+
return this.createFormField(key, data.type === "checkbox" ? "checkbox" : "input", data, {
|
|
303
|
+
type: `${data.type || "text"}`,
|
|
304
|
+
pattern: ObjectUtils.isString(data.pattern) ? data.pattern : "",
|
|
305
|
+
step: data.step,
|
|
306
|
+
cols: data.cols || null,
|
|
307
|
+
rows: data.rows || 10,
|
|
308
|
+
min: isNaN(data.min) ? MIN_INPUT_NUM : data.min,
|
|
309
|
+
max: isNaN(data.max) ? MAX_INPUT_NUM : data.max,
|
|
310
|
+
minLength: isNaN(data.minLength) ? 0 : data.minLength,
|
|
311
|
+
maxLength: isNaN(data.maxLength) ? MAX_INPUT_NUM : data.maxLength,
|
|
312
|
+
placeholder: data.placeholder || "",
|
|
313
|
+
attributes: {
|
|
314
|
+
autocomplete: data.autocomplete || "off"
|
|
315
|
+
},
|
|
316
|
+
}, parent, options);
|
|
317
|
+
}
|
|
318
|
+
createFormSelect(key, data, parent, options) {
|
|
319
|
+
data = data || { options: () => [] };
|
|
320
|
+
const select = this.createFormField(key, data.type === "radio" ? "radio" : "select", data, {
|
|
321
|
+
multiple: data.multiple,
|
|
322
|
+
type: data.type,
|
|
323
|
+
groupBy: data.groupBy,
|
|
324
|
+
inline: data.inline,
|
|
325
|
+
allowEmpty: data.allowEmpty
|
|
326
|
+
}, parent, options);
|
|
327
|
+
select.hooks = {
|
|
328
|
+
onInit: field => {
|
|
329
|
+
const options = data.options(field);
|
|
330
|
+
const control = field.formControl.root;
|
|
331
|
+
field.props.options = options instanceof Promise ? control.valueChanges.pipe(startWith(control.value), distinctUntilChanged(), switchMap(async () => {
|
|
332
|
+
const results = await data.options(field);
|
|
333
|
+
return this.fixSelectOptions(field, results);
|
|
334
|
+
})) : options;
|
|
499
335
|
}
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
336
|
+
};
|
|
337
|
+
return select;
|
|
338
|
+
}
|
|
339
|
+
createFormUpload(key, data, parent, options) {
|
|
340
|
+
data = data || {};
|
|
341
|
+
if (data.asFile) {
|
|
342
|
+
data.inline = true;
|
|
343
|
+
console.warn(`File upload property "asFile" is deprecated. Use "inline" instead.`);
|
|
344
|
+
}
|
|
345
|
+
if (data.multi) {
|
|
346
|
+
data.multiple = true;
|
|
347
|
+
console.warn(`File upload property "multi" is deprecated. Use "multiple" instead.`);
|
|
348
|
+
}
|
|
349
|
+
return this.createFormField(key, "upload", data, {
|
|
350
|
+
inline: data.inline === true,
|
|
351
|
+
multiple: data.multiple === true,
|
|
352
|
+
accept: data.accept || [".png", ".jpg"],
|
|
353
|
+
url: data.url?.startsWith("http") ? data.url : this.api.url(data.url || "assets"),
|
|
354
|
+
maxSize: isNaN(data.maxSize) ? MAX_INPUT_NUM : data.maxSize,
|
|
355
|
+
uploadOptions: data.uploadOptions || {},
|
|
356
|
+
createUploadData: data.createUploadData
|
|
357
|
+
}, parent, options);
|
|
358
|
+
}
|
|
359
|
+
createFormGroup(key, fields, data, parent, options) {
|
|
360
|
+
data = data || {};
|
|
361
|
+
const group = this.createFormField(key, undefined, data, {}, parent, options);
|
|
362
|
+
group.wrappers = ["form-group"];
|
|
363
|
+
const result = fields(group);
|
|
364
|
+
const handleGroup = (fieldGroup) => {
|
|
365
|
+
group.fieldGroup = fieldGroup;
|
|
366
|
+
return group;
|
|
367
|
+
};
|
|
368
|
+
return result instanceof Promise
|
|
369
|
+
? result.then(handleGroup)
|
|
370
|
+
: handleGroup(result);
|
|
371
|
+
}
|
|
372
|
+
createFormArray(key, fields, data, parent, options) {
|
|
373
|
+
data = data || {};
|
|
374
|
+
const array = this.createFormField(key, "array", data, {
|
|
375
|
+
// initialCount: data.initialCount || 0,
|
|
376
|
+
// sortable: data.sortable || false,
|
|
377
|
+
useTabs: data.useTabs === true,
|
|
378
|
+
tabsLabel: `${data.tabsLabel || "label"}`,
|
|
379
|
+
addItem: data.addItem !== false,
|
|
380
|
+
insertItem: data.insertItem !== false,
|
|
381
|
+
cloneItem: data.cloneItem !== false,
|
|
382
|
+
moveItem: data.moveItem !== false,
|
|
383
|
+
removeItem: data.removeItem !== false,
|
|
384
|
+
clearItems: data.clearItems !== false
|
|
385
|
+
}, parent, options);
|
|
386
|
+
const result = fields(array);
|
|
387
|
+
const handleItems = (items) => {
|
|
388
|
+
if (Array.isArray(items)) {
|
|
389
|
+
array.fieldArray = {
|
|
390
|
+
wrappers: ["form-group"],
|
|
391
|
+
fieldGroup: items,
|
|
392
|
+
};
|
|
393
|
+
return array;
|
|
505
394
|
}
|
|
506
|
-
|
|
507
|
-
|
|
395
|
+
const props = items.props || {};
|
|
396
|
+
if (props.type === "text" || props.type === "number") {
|
|
397
|
+
array.type = "chips";
|
|
398
|
+
array.wrappers = ["form-field"];
|
|
399
|
+
array.props = {
|
|
400
|
+
...props,
|
|
401
|
+
...array.props,
|
|
402
|
+
multiple: true
|
|
403
|
+
};
|
|
404
|
+
return array;
|
|
405
|
+
}
|
|
406
|
+
array.fieldArray = {
|
|
407
|
+
...items,
|
|
408
|
+
props: {
|
|
409
|
+
...items.props,
|
|
410
|
+
label: ""
|
|
411
|
+
}
|
|
412
|
+
};
|
|
413
|
+
return array;
|
|
414
|
+
};
|
|
415
|
+
return result instanceof Promise
|
|
416
|
+
? result.then(handleItems)
|
|
417
|
+
: handleItems(result);
|
|
508
418
|
}
|
|
419
|
+
async fixSelectOptions(field, options) {
|
|
420
|
+
if (!options)
|
|
421
|
+
return [];
|
|
422
|
+
for (const option of options) {
|
|
423
|
+
const classes = Array.isArray(option.classes) ? option.classes : [`${option.classes}`];
|
|
424
|
+
option.className = classes.filter(isStringWithVal).join(" ");
|
|
425
|
+
option.label = await this.language.getTranslation(option.label);
|
|
426
|
+
option.value = option.value ?? option.id;
|
|
427
|
+
option.id = option.id ?? option.value;
|
|
428
|
+
}
|
|
429
|
+
const control = field.formControl;
|
|
430
|
+
if (field.props.multiple || options.length === 0 || options.findIndex(o => o.value === control.value) >= 0)
|
|
431
|
+
return options;
|
|
432
|
+
control.setValue(options[0].value);
|
|
433
|
+
return options;
|
|
434
|
+
}
|
|
435
|
+
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 });
|
|
436
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DynamicFormBuilderService });
|
|
509
437
|
}
|
|
438
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DynamicFormBuilderService, decorators: [{
|
|
439
|
+
type: Injectable
|
|
440
|
+
}], ctorParameters: () => [{ type: i0.Injector }, { type: undefined, decorators: [{
|
|
441
|
+
type: Inject,
|
|
442
|
+
args: [API_SERVICE]
|
|
443
|
+
}] }, { type: undefined, decorators: [{
|
|
444
|
+
type: Inject,
|
|
445
|
+
args: [LANGUAGE_SERVICE]
|
|
446
|
+
}] }] });
|
|
510
447
|
|
|
511
448
|
function getFormValidationErrors(controls, parentPath = "") {
|
|
512
449
|
const errors = [];
|
|
513
450
|
Object.entries(controls).forEach(([name, control], ix) => {
|
|
514
451
|
const path = !parentPath ? name : `${parentPath}.${name}`;
|
|
515
|
-
if (control instanceof FormGroup) {
|
|
452
|
+
if (control instanceof FormGroup$1) {
|
|
516
453
|
getFormValidationErrors(control.controls, path).forEach(error => errors.push(error));
|
|
517
454
|
return;
|
|
518
455
|
}
|
|
519
|
-
if (control instanceof FormArray) {
|
|
456
|
+
if (control instanceof FormArray$1) {
|
|
520
457
|
control.controls.forEach((control, ix) => {
|
|
521
458
|
getFormValidationErrors(control.controls, `${path}.${ix}`).forEach(error => errors.push(error));
|
|
522
459
|
});
|
|
@@ -529,9 +466,10 @@ function getFormValidationErrors(controls, parentPath = "") {
|
|
|
529
466
|
return errors;
|
|
530
467
|
}
|
|
531
468
|
|
|
532
|
-
class DynamicFormService
|
|
469
|
+
class DynamicFormService {
|
|
533
470
|
openApi;
|
|
534
471
|
injector;
|
|
472
|
+
builder;
|
|
535
473
|
get api() {
|
|
536
474
|
return this.openApi.api;
|
|
537
475
|
}
|
|
@@ -539,183 +477,72 @@ class DynamicFormService extends DynamicFormService$1 {
|
|
|
539
477
|
return this.api.language;
|
|
540
478
|
}
|
|
541
479
|
schemas;
|
|
542
|
-
constructor(
|
|
543
|
-
super(cs, vs);
|
|
480
|
+
constructor(openApi, injector, builder) {
|
|
544
481
|
this.openApi = openApi;
|
|
545
482
|
this.injector = injector;
|
|
483
|
+
this.builder = builder;
|
|
484
|
+
}
|
|
485
|
+
async getFormFieldsForSchema(name, customizeOrOptions) {
|
|
486
|
+
const group = await this.getFormFieldGroupForSchema(name, customizeOrOptions);
|
|
487
|
+
return group.fieldGroup;
|
|
546
488
|
}
|
|
547
|
-
async serializeForm(form, validate) {
|
|
548
|
-
|
|
489
|
+
async serializeForm(form, validate = true) {
|
|
490
|
+
const fields = form.config();
|
|
491
|
+
if (!fields)
|
|
549
492
|
return null;
|
|
550
493
|
if (validate) {
|
|
551
494
|
await this.validateForm(form);
|
|
552
495
|
}
|
|
553
|
-
return this.serialize(
|
|
554
|
-
}
|
|
555
|
-
async getFormModelForSchema(name, customizeOrOptions) {
|
|
556
|
-
return (await this.getFormGroupModelForSchema(name, customizeOrOptions)).group;
|
|
557
|
-
}
|
|
558
|
-
getErrors(form) {
|
|
559
|
-
this.showErrors(form);
|
|
560
|
-
return new Promise(resolve => {
|
|
561
|
-
setTimeout(() => {
|
|
562
|
-
resolve(getFormValidationErrors(form.group.controls, ""));
|
|
563
|
-
}, 500);
|
|
564
|
-
});
|
|
565
|
-
}
|
|
566
|
-
createFormGroup(formModel, options, parent) {
|
|
567
|
-
const group = super.createFormGroup(formModel, options, parent);
|
|
568
|
-
if (!parent) {
|
|
569
|
-
group.valueChanges.pipe(debounceTime(500)).subscribe(() => {
|
|
570
|
-
this.notifyChanges(formModel, group, formModel);
|
|
571
|
-
});
|
|
572
|
-
}
|
|
573
|
-
return group;
|
|
496
|
+
return this.serialize(fields);
|
|
574
497
|
}
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
formGroup.patchValue(value);
|
|
579
|
-
this.detectChanges();
|
|
580
|
-
}
|
|
581
|
-
patchForm(value, component) {
|
|
582
|
-
value = ObjectUtils.copy(value);
|
|
583
|
-
this.patchValues(value, component.model, component.group);
|
|
584
|
-
component.group.patchValue(value);
|
|
585
|
-
this.detectChanges(component);
|
|
586
|
-
}
|
|
587
|
-
validateForm(form, showErrors = true) {
|
|
588
|
-
if (!form.group)
|
|
498
|
+
async validateForm(form, showErrors = true) {
|
|
499
|
+
const group = form.group();
|
|
500
|
+
if (!group)
|
|
589
501
|
return Promise.resolve();
|
|
590
502
|
return new Promise((resolve, reject) => {
|
|
591
|
-
|
|
503
|
+
group.statusChanges
|
|
504
|
+
.pipe(first(status => status == "VALID" || status == "INVALID"))
|
|
505
|
+
.subscribe(status => {
|
|
592
506
|
if (showErrors) {
|
|
593
|
-
this.
|
|
507
|
+
this.showErrorsForGroup(group);
|
|
594
508
|
}
|
|
595
509
|
if (status == "VALID") {
|
|
596
510
|
resolve(null);
|
|
597
511
|
return;
|
|
598
512
|
}
|
|
599
|
-
|
|
600
|
-
reject(null);
|
|
513
|
+
reject(getFormValidationErrors(group.controls));
|
|
601
514
|
});
|
|
602
|
-
|
|
515
|
+
group.updateValueAndValidity();
|
|
603
516
|
});
|
|
604
517
|
}
|
|
605
|
-
async serialize(
|
|
518
|
+
async serialize(fields) {
|
|
606
519
|
const result = {};
|
|
607
|
-
if (!
|
|
520
|
+
if (!fields)
|
|
608
521
|
return result;
|
|
609
|
-
for (const
|
|
610
|
-
const
|
|
611
|
-
const
|
|
612
|
-
const
|
|
522
|
+
for (const field of fields) {
|
|
523
|
+
const serializer = field.serializer;
|
|
524
|
+
const key = `${field.key}`;
|
|
525
|
+
const props = field.props || {};
|
|
613
526
|
if (ObjectUtils.isFunction(serializer)) {
|
|
614
|
-
result[
|
|
615
|
-
continue;
|
|
616
|
-
}
|
|
617
|
-
if (subModel.hidden && !subModel.additional?.serialize)
|
|
618
|
-
continue;
|
|
619
|
-
if (subModel instanceof DynamicFormArrayModel) {
|
|
620
|
-
const length = Array.isArray(subControl.value) ? subControl.value.length : 0;
|
|
621
|
-
const subArray = subControl;
|
|
622
|
-
const resArray = [];
|
|
623
|
-
for (let i = 0; i < length; i++) {
|
|
624
|
-
const itemModel = subModel.get(i);
|
|
625
|
-
resArray.push(await this.serialize(itemModel.group, subArray.at(i)));
|
|
626
|
-
}
|
|
627
|
-
result[subModel.id] = resArray;
|
|
628
|
-
continue;
|
|
629
|
-
}
|
|
630
|
-
if (subModel instanceof DynamicInputModel && !ObjectUtils.isNullOrUndefined(subControl.value)) {
|
|
631
|
-
result[subModel.id] = subModel.inputType == "number"
|
|
632
|
-
? parseFloat((`${subControl.value}` || "0").replace(/,/gi, ".")) ?? null
|
|
633
|
-
: subControl.value;
|
|
527
|
+
result[key] = await serializer(field, this.injector);
|
|
634
528
|
continue;
|
|
635
529
|
}
|
|
636
|
-
if (
|
|
637
|
-
result[subModel.id] = await this.serialize(subModel.group, subControl);
|
|
530
|
+
if (field.hide && !field.serialize) {
|
|
638
531
|
continue;
|
|
639
532
|
}
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
this.detectChanges(form);
|
|
647
|
-
}
|
|
648
|
-
notifyChanges(formModel, formGroup, root) {
|
|
649
|
-
if (!formModel || !formGroup)
|
|
650
|
-
return;
|
|
651
|
-
for (const i in formModel) {
|
|
652
|
-
const subModel = formModel[i];
|
|
653
|
-
const subControl = this.findControlByModel(subModel, formGroup);
|
|
654
|
-
if (subModel instanceof DynamicFormArrayModel) {
|
|
655
|
-
const length = Array.isArray(subControl.value) ? subControl.value.length : 0;
|
|
656
|
-
const subArray = subControl;
|
|
657
|
-
for (let i = 0; i < length; i++) {
|
|
658
|
-
const itemModel = subModel.get(i);
|
|
659
|
-
this.notifyChanges(itemModel.group, subArray.at(i), root);
|
|
533
|
+
const control = field.formControl;
|
|
534
|
+
if (field.fieldGroup) {
|
|
535
|
+
const group = await this.serialize(field.fieldGroup);
|
|
536
|
+
if (field.key) {
|
|
537
|
+
result[key] = !field.fieldArray ? group : Object.values(group);
|
|
538
|
+
continue;
|
|
660
539
|
}
|
|
540
|
+
Object.assign(result, group);
|
|
661
541
|
continue;
|
|
662
542
|
}
|
|
663
|
-
|
|
664
|
-
this.notifyChanges(subModel.group, subControl, root);
|
|
665
|
-
continue;
|
|
666
|
-
}
|
|
667
|
-
this.updateSelectOptions(subModel, subControl, root);
|
|
668
|
-
}
|
|
669
|
-
}
|
|
670
|
-
patchValues(value, formModel, formGroup) {
|
|
671
|
-
if (!value)
|
|
672
|
-
return;
|
|
673
|
-
formModel?.forEach(subModel => {
|
|
674
|
-
const key = subModel.id;
|
|
675
|
-
const subValue = value[key];
|
|
676
|
-
const subControl = this.findControlByModel(subModel, formGroup);
|
|
677
|
-
if ((subModel instanceof DynamicSelectModel || subModel instanceof DynamicRadioGroupModel) && ObjectUtils.isObject(subValue)) {
|
|
678
|
-
value[key] = subValue.id || subValue._id || subValue;
|
|
679
|
-
return;
|
|
680
|
-
}
|
|
681
|
-
if (subModel instanceof DynamicDatePickerModel) {
|
|
682
|
-
value[key] = this.convertToDate(subValue);
|
|
683
|
-
return;
|
|
684
|
-
}
|
|
685
|
-
if (subModel instanceof DynamicFormArrayModel) {
|
|
686
|
-
const length = Array.isArray(subValue) ? subValue.length : 0;
|
|
687
|
-
const subArray = subControl;
|
|
688
|
-
while (subModel.size > length) {
|
|
689
|
-
this.removeFormArrayGroup(0, subArray, subModel);
|
|
690
|
-
}
|
|
691
|
-
while (subModel.size < length) {
|
|
692
|
-
this.insertFormArrayGroup(subModel.size, subArray, subModel);
|
|
693
|
-
}
|
|
694
|
-
for (let i = 0; i < length; i++) {
|
|
695
|
-
const itemModel = subModel.get(i);
|
|
696
|
-
this.patchValues(subValue[i], itemModel.group, subArray.at(i));
|
|
697
|
-
}
|
|
698
|
-
return;
|
|
699
|
-
}
|
|
700
|
-
if (subModel instanceof DynamicFormGroupModel) {
|
|
701
|
-
this.patchValues(subValue, subModel.group, subControl);
|
|
702
|
-
}
|
|
703
|
-
});
|
|
704
|
-
}
|
|
705
|
-
updateSelectOptions(formControlModel, formControl, root) {
|
|
706
|
-
if (formControlModel instanceof DynamicSelectModel) {
|
|
707
|
-
let options = formControlModel.options$;
|
|
708
|
-
if (options instanceof FormSubject) {
|
|
709
|
-
options.notify(formControlModel, formControl, root);
|
|
710
|
-
return;
|
|
711
|
-
}
|
|
712
|
-
while (options instanceof Subject && options.source) {
|
|
713
|
-
options = options.source;
|
|
714
|
-
if (options instanceof FormSubject) {
|
|
715
|
-
options.notify(formControlModel, formControl, root);
|
|
716
|
-
}
|
|
717
|
-
}
|
|
543
|
+
result[key] = control.value;
|
|
718
544
|
}
|
|
545
|
+
return result;
|
|
719
546
|
}
|
|
720
547
|
showErrorsForGroup(formGroup) {
|
|
721
548
|
if (!formGroup)
|
|
@@ -726,12 +553,12 @@ class DynamicFormService extends DynamicFormService$1 {
|
|
|
726
553
|
}
|
|
727
554
|
showErrorsForControls(controls) {
|
|
728
555
|
controls.forEach(control => {
|
|
729
|
-
if (control instanceof FormGroup) {
|
|
556
|
+
if (control instanceof FormGroup$1) {
|
|
730
557
|
this.showErrorsForGroup(control);
|
|
731
558
|
return;
|
|
732
559
|
}
|
|
733
560
|
control.markAsTouched({ onlySelf: true });
|
|
734
|
-
if (control instanceof FormArray) {
|
|
561
|
+
if (control instanceof FormArray$1) {
|
|
735
562
|
this.showErrorsForControls(control.controls);
|
|
736
563
|
}
|
|
737
564
|
});
|
|
@@ -744,326 +571,287 @@ class DynamicFormService extends DynamicFormService$1 {
|
|
|
744
571
|
: new Date(value);
|
|
745
572
|
return isNaN(date) ? new Date() : date;
|
|
746
573
|
}
|
|
747
|
-
async
|
|
748
|
-
this.api.cache = {};
|
|
574
|
+
async getFormFieldGroupForSchema(name, customizeOrOptions) {
|
|
749
575
|
this.schemas = await this.openApi.getSchemas();
|
|
750
|
-
const fieldSets = [];
|
|
751
576
|
const schemaOptions = ObjectUtils.isObject(customizeOrOptions) ? customizeOrOptions : {};
|
|
752
|
-
const
|
|
577
|
+
const customizeConfig = ObjectUtils.isFunction(customizeOrOptions) ? customizeOrOptions : schemaOptions.customizer;
|
|
753
578
|
const schema = this.schemas[name];
|
|
754
579
|
const wrapOptions = {
|
|
755
580
|
...schemaOptions,
|
|
756
581
|
schema,
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
config.
|
|
760
|
-
?
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
model.value = (model instanceof DynamicDatePickerModel)
|
|
765
|
-
? this.convertToDate(property.default) : property.default;
|
|
766
|
-
}
|
|
767
|
-
const modelPath = `${pathPrefix}${model.id}`;
|
|
768
|
-
const layout = modelPath.toLowerCase().replace(/\./g, "-");
|
|
769
|
-
model.layout = {
|
|
770
|
-
grid: {
|
|
771
|
-
host: `${layout} control-${model.id}`,
|
|
772
|
-
container: `${layout}-container`
|
|
773
|
-
}
|
|
774
|
-
};
|
|
775
|
-
if (!ObjectUtils.isFunction(customizeModel))
|
|
776
|
-
return [model];
|
|
777
|
-
let res = customizeModel(property, schema, model, config, modelPath, this.injector);
|
|
582
|
+
injector: this.injector,
|
|
583
|
+
customizer: async (property, options, config, parent) => {
|
|
584
|
+
config.defaultValue = `${config.type}`.startsWith("date")
|
|
585
|
+
? this.convertToDate(property.default) : property.default;
|
|
586
|
+
if (!ObjectUtils.isFunction(customizeConfig))
|
|
587
|
+
return [config];
|
|
588
|
+
let res = customizeConfig(property, schema, config, parent, options, this.injector);
|
|
778
589
|
if (!res)
|
|
779
|
-
return [
|
|
590
|
+
return [config];
|
|
780
591
|
if (res instanceof Promise) {
|
|
781
592
|
res = await res;
|
|
782
593
|
}
|
|
783
594
|
return Array.isArray(res) ? res : [res];
|
|
784
595
|
}
|
|
785
596
|
};
|
|
786
|
-
const
|
|
787
|
-
|
|
597
|
+
const config = {
|
|
598
|
+
key: FORM_ROOT_KEY,
|
|
599
|
+
wrappers: ["form-group"]
|
|
600
|
+
};
|
|
601
|
+
const fields = await this.getFormFieldsForSchemaDef(schema, config, wrapOptions);
|
|
602
|
+
const fieldGroup = [...fields];
|
|
788
603
|
// Add id fields if necessary
|
|
789
|
-
if (
|
|
604
|
+
if (fields.length > 0) {
|
|
790
605
|
const idFields = [
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
]
|
|
794
|
-
|
|
606
|
+
{ key: "id", props: { hidden: true } },
|
|
607
|
+
{ key: "_id", props: { hidden: true } },
|
|
608
|
+
];
|
|
609
|
+
fieldGroup.unshift(...idFields
|
|
610
|
+
.filter(t => !fields.some(c => c.key == t.key)));
|
|
795
611
|
}
|
|
796
|
-
|
|
797
|
-
id: "root",
|
|
798
|
-
group,
|
|
799
|
-
fieldSets
|
|
800
|
-
};
|
|
612
|
+
config.fieldGroup = fieldGroup;
|
|
801
613
|
const root = await wrapOptions.customizer({
|
|
802
|
-
id:
|
|
614
|
+
id: FORM_ROOT_KEY,
|
|
803
615
|
type: "object",
|
|
804
616
|
properties: schema?.properties || {}
|
|
805
|
-
}, wrapOptions,
|
|
617
|
+
}, wrapOptions, config, null);
|
|
806
618
|
// Check if the customized root wrapper returned an array
|
|
807
|
-
|
|
619
|
+
fields.length = 0;
|
|
808
620
|
for (const model of root) {
|
|
809
|
-
if (model
|
|
621
|
+
if (model.key === FORM_ROOT_KEY) {
|
|
810
622
|
return model;
|
|
811
623
|
}
|
|
812
624
|
else {
|
|
813
|
-
|
|
625
|
+
fields.push(model);
|
|
814
626
|
}
|
|
815
627
|
}
|
|
816
|
-
return
|
|
628
|
+
return {
|
|
817
629
|
...config,
|
|
818
|
-
|
|
819
|
-
}
|
|
630
|
+
fieldGroup: fields
|
|
631
|
+
};
|
|
820
632
|
}
|
|
821
|
-
async
|
|
633
|
+
async getFormFieldsForSchemaDef(schema, parent, options) {
|
|
822
634
|
if (!schema)
|
|
823
635
|
return [];
|
|
824
636
|
const keys = Object.keys(schema.properties || {});
|
|
825
|
-
const
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
const
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
if (fs) {
|
|
832
|
-
fs.fields.push(p);
|
|
833
|
-
}
|
|
834
|
-
else {
|
|
835
|
-
fieldSets.push({ id: fsName, legend: `legend.${fsName}`, fields: [p] });
|
|
836
|
-
}
|
|
837
|
-
}
|
|
838
|
-
const models = await this.getFormControlModels(property, options, path);
|
|
839
|
-
controls.push(...models);
|
|
637
|
+
const fields = [];
|
|
638
|
+
// Collect all properties of this schema def
|
|
639
|
+
for (const key of keys) {
|
|
640
|
+
const property = schema.properties[key];
|
|
641
|
+
const propFields = await this.getFormFieldsForProp(property, options, parent);
|
|
642
|
+
fields.push(...propFields);
|
|
840
643
|
}
|
|
841
|
-
return
|
|
644
|
+
return this.builder.createFieldSets(fields.filter(f => null !== f), parent, options);
|
|
842
645
|
}
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
return EDITOR_FORMATS.indexOf(property.format) >= 0 || property.format.endsWith("script");
|
|
646
|
+
async getFormFieldsForProp(property, options, parent) {
|
|
647
|
+
const field = await this.getFormFieldForProp(property, options, parent);
|
|
648
|
+
return !field ? [] : options.customizer(property, options, field, parent);
|
|
847
649
|
}
|
|
848
|
-
async
|
|
650
|
+
async getFormFieldForProp(property, options, parent) {
|
|
849
651
|
const $enum = property.items?.enum || property.enum;
|
|
850
652
|
if (Array.isArray($enum) || isStringWithVal(property.optionsPath) || isStringWithVal(property.endpoint)) {
|
|
851
653
|
if (property.format == "radio") {
|
|
852
|
-
return
|
|
654
|
+
return this.getFormRadioConfig(property, options, parent);
|
|
853
655
|
}
|
|
854
|
-
return
|
|
656
|
+
return this.getFormSelectConfig(property, options, parent);
|
|
855
657
|
}
|
|
856
658
|
switch (property.type) {
|
|
857
659
|
case "string":
|
|
858
660
|
case "number":
|
|
859
661
|
case "integer":
|
|
860
662
|
case "textarea":
|
|
861
|
-
if (this.checkIsEditorProperty(property)) {
|
|
862
|
-
|
|
863
|
-
}
|
|
663
|
+
// if (this.checkIsEditorProperty(property)) {
|
|
664
|
+
// return this.getFormEditorConfig(property, options, parent);
|
|
665
|
+
// }
|
|
864
666
|
if (property.format == "textarea") {
|
|
865
|
-
return
|
|
667
|
+
return this.getFormTextareaConfig(property, options, parent);
|
|
866
668
|
}
|
|
867
669
|
if (property.format == "date" || property.format == "date-time") {
|
|
868
|
-
return
|
|
670
|
+
return this.getFormDatepickerConfig(property, options, parent);
|
|
869
671
|
}
|
|
870
|
-
return
|
|
871
|
-
case "object":
|
|
872
|
-
|
|
672
|
+
return this.getFormInputConfig(property, options, parent);
|
|
673
|
+
// case "object":
|
|
674
|
+
// return this.getFormEditorConfig(property, options, parent);
|
|
873
675
|
case "boolean":
|
|
874
|
-
return
|
|
676
|
+
return this.getFormCheckboxConfig(property, options, parent);
|
|
875
677
|
case "array":
|
|
876
|
-
|
|
877
|
-
return options.customizer(property, options, DynamicFormArrayModel, await this.getFormArrayConfig(property, options, path), path);
|
|
878
|
-
}
|
|
879
|
-
else {
|
|
880
|
-
return options.customizer(property, options, DynamicInputModel, this.getFormInputConfig(property, options), path);
|
|
881
|
-
}
|
|
678
|
+
return this.getFormArrayConfig(property, options, parent);
|
|
882
679
|
case "file":
|
|
883
|
-
|
|
680
|
+
case "upload":
|
|
681
|
+
return this.getFormUploadConfig(property, options, parent);
|
|
884
682
|
}
|
|
885
683
|
if (findRefs(property).length > 0) {
|
|
886
|
-
return
|
|
684
|
+
return this.getFormGroupConfig(property, options, parent);
|
|
887
685
|
}
|
|
888
|
-
return
|
|
686
|
+
return null;
|
|
889
687
|
}
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
return this.findModelByPath(parent.find(t => t.id == next), path);
|
|
896
|
-
}
|
|
897
|
-
if (parent instanceof DynamicFormGroupModel || parent instanceof DynamicFormArrayGroupModel) {
|
|
898
|
-
return this.findModelByPath(parent.group.find(t => t.id == next), path);
|
|
899
|
-
}
|
|
900
|
-
if (parent instanceof DynamicFormArrayModel) {
|
|
901
|
-
return this.findModelByPath(parent.groups.find(t => t.index == next), path);
|
|
688
|
+
getFormFieldData(property, options) {
|
|
689
|
+
const validators = {};
|
|
690
|
+
const schema = options.schema;
|
|
691
|
+
if (ObjectUtils.isArray(schema.required) && schema.required.indexOf(property.id) >= 0) {
|
|
692
|
+
validators.required = requiredValidation();
|
|
902
693
|
}
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
getFormControlConfig(property, options) {
|
|
906
|
-
const validators = this.getValidators(property, options);
|
|
907
|
-
const errorMessages = Object.keys(validators).reduce((res, key) => {
|
|
908
|
-
res[key] = options.labelPrefix
|
|
909
|
-
? this.language.getTranslationSync(`${options.labelPrefix}.error.${key}`) : `error.${key}`;
|
|
910
|
-
return res;
|
|
911
|
-
}, {});
|
|
694
|
+
this.addPropertyValidators(validators, property);
|
|
695
|
+
this.addItemsValidators(validators, property.items);
|
|
912
696
|
return {
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
disabled: property.disabled,
|
|
917
|
-
validators,
|
|
918
|
-
errorMessages,
|
|
919
|
-
additional: Object.assign({
|
|
920
|
-
// For material components
|
|
921
|
-
appearance: "fill"
|
|
922
|
-
}, property)
|
|
697
|
+
hidden: property.hidden === true,
|
|
698
|
+
fieldSet: property.fieldSet,
|
|
699
|
+
validators
|
|
923
700
|
};
|
|
924
701
|
}
|
|
925
|
-
async getFormArrayConfig(property, options,
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
702
|
+
async getFormArrayConfig(property, options, parent) {
|
|
703
|
+
return this.builder.createFormArray(property.id, async (sp) => {
|
|
704
|
+
const subSchemas = findRefs(property).map(ref => this.schemas[ref]);
|
|
705
|
+
if (subSchemas.length > 0) {
|
|
706
|
+
const subModels = await Promise.all(subSchemas.map(s => this.getFormFieldsForSchemaDef(s, sp, options)));
|
|
707
|
+
return mergeFormFields(ObjectUtils.copy(subModels));
|
|
708
|
+
}
|
|
709
|
+
return this.getFormFieldForProp(property.items, options, null);
|
|
710
|
+
}, {
|
|
711
|
+
...this.getFormFieldData(property, options),
|
|
712
|
+
// initialCount: property.initialCount || 0,
|
|
713
|
+
// sortable: property.sortable || false,
|
|
714
|
+
useTabs: property.useTabs,
|
|
715
|
+
tabsLabel: property.tabsLabel,
|
|
716
|
+
addItem: property.addItem,
|
|
717
|
+
insertItem: property.insertItem,
|
|
718
|
+
cloneItem: property.cloneItem,
|
|
719
|
+
moveItem: property.moveItem,
|
|
720
|
+
removeItem: property.removeItem,
|
|
721
|
+
clearItems: property.clearItems
|
|
722
|
+
}, parent, options);
|
|
723
|
+
}
|
|
724
|
+
async getFormGroupConfig(property, options, parent) {
|
|
944
725
|
const subSchemas = findRefs(property).map(ref => this.schemas[ref]);
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
726
|
+
return this.builder.createFormGroup(property.id, async (sp) => {
|
|
727
|
+
const subModels = await Promise.all(subSchemas.map(s => this.getFormFieldsForSchemaDef(s, sp, options)));
|
|
728
|
+
return mergeFormFields(subModels);
|
|
729
|
+
}, {
|
|
730
|
+
...this.getFormFieldData(property, options),
|
|
731
|
+
}, parent, options);
|
|
732
|
+
}
|
|
733
|
+
getFormInputConfig(property, options, parent) {
|
|
734
|
+
let type = StringUtils.has(property.id || "", "password", "Password") ? "password" : (property.format || property.type);
|
|
735
|
+
switch (type) {
|
|
954
736
|
case "string":
|
|
955
|
-
|
|
737
|
+
type = "text";
|
|
956
738
|
break;
|
|
957
739
|
case "boolean":
|
|
958
|
-
|
|
740
|
+
type = "checkbox";
|
|
959
741
|
break;
|
|
960
742
|
case "textarea":
|
|
961
|
-
|
|
743
|
+
type = "textarea";
|
|
962
744
|
break;
|
|
963
745
|
case "integer":
|
|
964
|
-
|
|
746
|
+
type = "number";
|
|
965
747
|
break;
|
|
966
748
|
}
|
|
967
749
|
const sub = property.type == "array" ? property.items || property : property;
|
|
968
|
-
return
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
inputType: property.format || "json",
|
|
987
|
-
convertObject: property.type !== "string",
|
|
988
|
-
autoComplete: property.autoComplete || "off",
|
|
989
|
-
multiple: property.type == "array",
|
|
990
|
-
accept: ObjectUtils.isString(property.accept) ? property.accept : null,
|
|
991
|
-
mask: ObjectUtils.isString(property.mask) ? property.mask : null,
|
|
992
|
-
pattern: ObjectUtils.isString(property.pattern) ? property.pattern : null,
|
|
993
|
-
step: isNaN(sub.step) ? (isNaN(property.step) ? 1 : property.step) : sub.step,
|
|
994
|
-
minLength: isNaN(sub.minLength) ? 0 : sub.minLength,
|
|
995
|
-
maxLength: isNaN(sub.maxLength) ? MAX_INPUT_NUM : sub.maxLength,
|
|
996
|
-
placeholder: property.placeholder || ""
|
|
997
|
-
});
|
|
998
|
-
}
|
|
999
|
-
getFormTextareaConfig(property, options) {
|
|
1000
|
-
return Object.assign(this.getFormControlConfig(property, options), {
|
|
750
|
+
return this.builder.createFormInput(property.id, {
|
|
751
|
+
...this.getFormFieldData(property, options),
|
|
752
|
+
type,
|
|
753
|
+
autocomplete: property.autocomplete,
|
|
754
|
+
pattern: property.pattern,
|
|
755
|
+
step: isNaN(sub.step) ? property.step : sub.step,
|
|
756
|
+
min: sub.minimum,
|
|
757
|
+
max: sub.maximum,
|
|
758
|
+
minLength: sub.minLength,
|
|
759
|
+
maxLength: sub.maxLength,
|
|
760
|
+
placeholder: property.placeholder
|
|
761
|
+
}, parent, options);
|
|
762
|
+
}
|
|
763
|
+
getFormTextareaConfig(property, options, parent) {
|
|
764
|
+
return this.builder.createFormInput(property.id, {
|
|
765
|
+
...this.getFormFieldData(property, options),
|
|
766
|
+
type: "textarea",
|
|
767
|
+
autocomplete: property.autoComplete,
|
|
1001
768
|
cols: property.cols || null,
|
|
1002
769
|
rows: property.rows || 10,
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
multiple: property.type == "array",
|
|
1006
|
-
minLength: isNaN(property.minLength) ? 0 : property.minLength,
|
|
1007
|
-
maxLength: isNaN(property.maxLength) ? MAX_INPUT_NUM : property.maxLength,
|
|
770
|
+
minLength: property.minLength,
|
|
771
|
+
maxLength: property.maxLength,
|
|
1008
772
|
placeholder: property.placeholder || ""
|
|
1009
|
-
});
|
|
1010
|
-
}
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
773
|
+
}, parent, options);
|
|
774
|
+
}
|
|
775
|
+
// getFormEditorConfig(property: IOpenApiSchemaProperty, options: ConfigForSchemaWrapOptions): DynamicEditorModelConfig {
|
|
776
|
+
// const sub = property.type == "array" ? property.items || property : property;
|
|
777
|
+
// return Object.assign(
|
|
778
|
+
// this.getFormControlConfig(property, options),
|
|
779
|
+
// {
|
|
780
|
+
// inputType: property.format || "json",
|
|
781
|
+
// convertObject: property.type !== "string",
|
|
782
|
+
// autoComplete: property.autoComplete || "off",
|
|
783
|
+
// multiple: property.type == "array",
|
|
784
|
+
// accept: ObjectUtils.isString(property.accept) ? property.accept : null,
|
|
785
|
+
// mask: ObjectUtils.isString(property.mask) ? property.mask : null,
|
|
786
|
+
// pattern: ObjectUtils.isString(property.pattern) ? property.pattern : null,
|
|
787
|
+
// step: isNaN(sub.step) ? (isNaN(property.step) ? 1 : property.step) : sub.step,
|
|
788
|
+
// minLength: isNaN(sub.minLength) ? 0 : sub.minLength,
|
|
789
|
+
// maxLength: isNaN(sub.maxLength) ? MAX_INPUT_NUM : sub.maxLength,
|
|
790
|
+
// placeholder: property.placeholder || ""
|
|
791
|
+
// }
|
|
792
|
+
// );
|
|
793
|
+
// }
|
|
794
|
+
getFormDatepickerConfig(property, options, parent) {
|
|
795
|
+
return this.builder.createFormInput(property.id, {
|
|
796
|
+
...this.getFormFieldData(property, options),
|
|
797
|
+
type: property.format == "date-time" ? "datetime-local" : "date",
|
|
798
|
+
// format: property.dateFormat || "dd.MM.yyyy",
|
|
1014
799
|
min: this.convertToDate(property.min),
|
|
1015
800
|
max: this.convertToDate(property.max),
|
|
1016
|
-
});
|
|
801
|
+
}, parent, options);
|
|
1017
802
|
}
|
|
1018
|
-
|
|
803
|
+
getFormRadioConfig(property, options, parent) {
|
|
804
|
+
return this.builder.createFormSelect(property.id, {
|
|
805
|
+
...this.getFormFieldData(property, options),
|
|
806
|
+
options: field => this.getFormSelectOptions(property, options, field),
|
|
807
|
+
type: "radio",
|
|
808
|
+
multiple: property.type == "array",
|
|
809
|
+
groupBy: property.groupBy,
|
|
810
|
+
inline: property.inline,
|
|
811
|
+
allowEmpty: property.allowEmpty
|
|
812
|
+
}, parent, options);
|
|
813
|
+
}
|
|
814
|
+
getFormSelectConfig(property, options, parent) {
|
|
815
|
+
return this.builder.createFormSelect(property.id, {
|
|
816
|
+
...this.getFormFieldData(property, options),
|
|
817
|
+
options: field => this.getFormSelectOptions(property, options, field),
|
|
818
|
+
type: "select",
|
|
819
|
+
multiple: property.type == "array",
|
|
820
|
+
groupBy: property.groupBy,
|
|
821
|
+
inline: property.inline,
|
|
822
|
+
allowEmpty: property.allowEmpty
|
|
823
|
+
}, parent, options);
|
|
824
|
+
}
|
|
825
|
+
getFormUploadConfig(property, options, parent) {
|
|
826
|
+
return this.builder.createFormUpload(property.id, {
|
|
827
|
+
...this.getFormFieldData(property, options),
|
|
828
|
+
multiple: property.type === "array",
|
|
829
|
+
inline: property.inline,
|
|
830
|
+
accept: property.accept,
|
|
831
|
+
url: property.url,
|
|
832
|
+
maxSize: property.maxSize,
|
|
833
|
+
uploadOptions: property.uploadOptions
|
|
834
|
+
}, parent, options);
|
|
835
|
+
}
|
|
836
|
+
getFormCheckboxConfig(property, options, parent) {
|
|
837
|
+
return this.builder.createFormInput(property.id, {
|
|
838
|
+
...this.getFormFieldData(property, options),
|
|
839
|
+
type: "checkbox",
|
|
840
|
+
indeterminate: property.indeterminate || false
|
|
841
|
+
}, parent, options);
|
|
842
|
+
}
|
|
843
|
+
getFormSelectOptions(property, options, field) {
|
|
1019
844
|
const $enum = property.items?.enum || property.enum;
|
|
1020
845
|
if (Array.isArray($enum)) {
|
|
1021
|
-
return
|
|
1022
|
-
const
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
});
|
|
1030
|
-
}
|
|
1031
|
-
if (isStringWithVal(property.optionsPath)) {
|
|
1032
|
-
return new FormSelectSubject(async (selectModel, control, root, indexes) => {
|
|
1033
|
-
let path = property.optionsPath;
|
|
1034
|
-
let target = control;
|
|
1035
|
-
let model = selectModel;
|
|
1036
|
-
if (path.startsWith("$root")) {
|
|
1037
|
-
path = path.substring(5);
|
|
1038
|
-
while (target.parent) {
|
|
1039
|
-
target = target.parent;
|
|
1040
|
-
}
|
|
1041
|
-
model = root;
|
|
1042
|
-
}
|
|
1043
|
-
while (path.startsWith(".")) {
|
|
1044
|
-
path = path.substring(1);
|
|
1045
|
-
if (target.parent) {
|
|
1046
|
-
target = target.parent;
|
|
1047
|
-
}
|
|
1048
|
-
model = model.parent || root;
|
|
1049
|
-
}
|
|
1050
|
-
Object.keys(indexes).forEach(key => {
|
|
1051
|
-
path = path.replace(key, indexes[key]);
|
|
1052
|
-
});
|
|
1053
|
-
model = this.findModelByPath(model, path.split("."));
|
|
1054
|
-
const modelOptions = model instanceof DynamicSelectModel
|
|
1055
|
-
? await firstValueFrom(model.options$) :
|
|
1056
|
-
[];
|
|
1057
|
-
const value = ObjectUtils.getValue(target.value, path);
|
|
1058
|
-
const options = (!ObjectUtils.isArray(value) ? [] : value).map(value => {
|
|
1059
|
-
const modelOption = modelOptions.find(t => t.value == value);
|
|
1060
|
-
return { value, label: modelOption?.label || value };
|
|
1061
|
-
});
|
|
1062
|
-
return this.fixSelectOptions(selectModel, control, options);
|
|
1063
|
-
});
|
|
1064
|
-
}
|
|
1065
|
-
return new FormSelectSubject(async (selectModel, control) => {
|
|
1066
|
-
const entries = Object.entries(control.root?.controls || {});
|
|
846
|
+
return from(this.builder.fixSelectOptions(field, $enum.map(value => {
|
|
847
|
+
const label = options.labelPrefix
|
|
848
|
+
? this.language.getTranslationSync(`${options.labelPrefix}.${property.id}.${value}`)
|
|
849
|
+
: `${property.id}.${value}`;
|
|
850
|
+
return { value, label };
|
|
851
|
+
})));
|
|
852
|
+
}
|
|
853
|
+
if (isStringWithVal(property.endpoint)) {
|
|
854
|
+
const entries = Object.entries(field.formControl.root?.controls || {});
|
|
1067
855
|
const endpoint = entries.reduce((res, [key, control]) => {
|
|
1068
856
|
return this.replaceOptionsEndpoint(res, key, control?.value);
|
|
1069
857
|
}, `${property.endpoint}`);
|
|
@@ -1080,46 +868,37 @@ class DynamicFormService extends DynamicFormService$1 {
|
|
|
1080
868
|
};
|
|
1081
869
|
});
|
|
1082
870
|
});
|
|
1083
|
-
const options =
|
|
1084
|
-
return
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
return
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
getFormCheckboxConfig(property, options) {
|
|
1115
|
-
return Object.assign(this.getFormControlConfig(property, options), {
|
|
1116
|
-
indeterminate: property.indeterminate || false
|
|
1117
|
-
});
|
|
1118
|
-
}
|
|
1119
|
-
cloneFormArrayGroup(index, formArray, formArrayModel) {
|
|
1120
|
-
this.insertFormArrayGroup(index, formArray, formArrayModel);
|
|
1121
|
-
this.patchGroup(formArray.at(index + 1).value, formArrayModel.groups[index].group, formArray.at(index));
|
|
1122
|
-
formArrayModel.filterGroups();
|
|
871
|
+
const options = this.api.cache[endpoint];
|
|
872
|
+
return from(options.then(opts => {
|
|
873
|
+
return this.builder.fixSelectOptions(field, opts.map(o => Object.assign({}, o)));
|
|
874
|
+
}));
|
|
875
|
+
}
|
|
876
|
+
let path = property.optionsPath;
|
|
877
|
+
let control = field.formControl;
|
|
878
|
+
let current = field;
|
|
879
|
+
if (path.startsWith("$root")) {
|
|
880
|
+
path = path.substring(5);
|
|
881
|
+
control = control.root || control;
|
|
882
|
+
while (current.parent) {
|
|
883
|
+
current = current.parent;
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
while (path.startsWith(".")) {
|
|
887
|
+
path = path.substring(1);
|
|
888
|
+
control = control.parent || control;
|
|
889
|
+
current = current.parent || current;
|
|
890
|
+
}
|
|
891
|
+
control = !path ? control : control.get(path);
|
|
892
|
+
return control.valueChanges.pipe(startWith(control.value), distinctUntilChanged(), switchMap(async (controlVal) => {
|
|
893
|
+
const currentOpts = current.props.options;
|
|
894
|
+
const finalOpts = isObservable(currentOpts)
|
|
895
|
+
? await firstValueFrom(currentOpts)
|
|
896
|
+
: (Array.isArray(currentOpts) ? currentOpts : []);
|
|
897
|
+
return this.builder.fixSelectOptions(field, (!Array.isArray(controlVal) ? [] : controlVal).map(value => {
|
|
898
|
+
const modelOption = finalOpts.find(t => t.value == value);
|
|
899
|
+
return { value, label: modelOption?.label || value };
|
|
900
|
+
}));
|
|
901
|
+
}));
|
|
1123
902
|
}
|
|
1124
903
|
replaceOptionsEndpoint(endpoint, key, value) {
|
|
1125
904
|
if (ObjectUtils.isObject(value)) {
|
|
@@ -1134,46 +913,27 @@ class DynamicFormService extends DynamicFormService$1 {
|
|
|
1134
913
|
}
|
|
1135
914
|
return endpoint.replace(new RegExp(`\\$${key}`, "gi"), `${value ?? ""}`);
|
|
1136
915
|
}
|
|
1137
|
-
async fixSelectOptions(model, control, options) {
|
|
1138
|
-
if (!options)
|
|
1139
|
-
return [];
|
|
1140
|
-
for (const option of options) {
|
|
1141
|
-
option.classes = [option.classes, model.getClasses(option, model, control, this.injector)].filter(isStringWithVal).join(" ");
|
|
1142
|
-
option.label = await this.language.getTranslation(option.label);
|
|
1143
|
-
}
|
|
1144
|
-
return options;
|
|
1145
|
-
}
|
|
1146
|
-
getValidators(property, options) {
|
|
1147
|
-
const validators = {};
|
|
1148
|
-
const schema = options.schema;
|
|
1149
|
-
if (ObjectUtils.isArray(schema.required) && schema.required.indexOf(property.id) >= 0) {
|
|
1150
|
-
validators.required = null;
|
|
1151
|
-
}
|
|
1152
|
-
this.addPropertyValidators(validators, property);
|
|
1153
|
-
this.addItemsValidators(validators, property.items);
|
|
1154
|
-
return validators;
|
|
1155
|
-
}
|
|
1156
916
|
addPropertyValidators(validators, property) {
|
|
1157
917
|
if (!property)
|
|
1158
918
|
return;
|
|
1159
919
|
if (!isNaN(property.minLength)) {
|
|
1160
|
-
validators.minLength = property.minLength;
|
|
920
|
+
validators.minLength = minLengthValidation(property.minLength);
|
|
1161
921
|
}
|
|
1162
922
|
if (!isNaN(property.maxLength)) {
|
|
1163
|
-
validators.maxLength = property.maxLength;
|
|
923
|
+
validators.maxLength = maxLengthValidation(property.maxLength);
|
|
1164
924
|
}
|
|
1165
925
|
if (!isNaN(property.minimum)) {
|
|
1166
|
-
validators.min = property.minimum;
|
|
926
|
+
validators.min = minValueValidation(property.minimum);
|
|
1167
927
|
}
|
|
1168
928
|
if (!isNaN(property.maximum)) {
|
|
1169
|
-
validators.max = property.maximum;
|
|
1170
|
-
}
|
|
1171
|
-
if (isString(property.pattern) && property.pattern.length) {
|
|
1172
|
-
validators.pattern = property.pattern;
|
|
929
|
+
validators.max = maxValueValidation(property.maximum);
|
|
1173
930
|
}
|
|
931
|
+
// if (isString(property.pattern) && property.pattern.length) {
|
|
932
|
+
// validators.pattern = property.pattern;
|
|
933
|
+
// }
|
|
1174
934
|
switch (property.format) {
|
|
1175
935
|
case "email":
|
|
1176
|
-
validators.email =
|
|
936
|
+
validators.email = emailValidation();
|
|
1177
937
|
break;
|
|
1178
938
|
}
|
|
1179
939
|
}
|
|
@@ -1181,123 +941,89 @@ class DynamicFormService extends DynamicFormService$1 {
|
|
|
1181
941
|
if (!items)
|
|
1182
942
|
return;
|
|
1183
943
|
if (!isNaN(items.minLength)) {
|
|
1184
|
-
validators.itemsMinLength = items.minLength;
|
|
944
|
+
validators.itemsMinLength = minLengthValidation(items.minLength, true);
|
|
1185
945
|
}
|
|
1186
946
|
if (!isNaN(items.maxLength)) {
|
|
1187
|
-
validators.itemsMaxLength = items.maxLength;
|
|
947
|
+
validators.itemsMaxLength = maxLengthValidation(items.maxLength, true);
|
|
1188
948
|
}
|
|
1189
949
|
if (!isNaN(items.minimum)) {
|
|
1190
|
-
validators.itemsMinValue = items.minimum;
|
|
950
|
+
validators.itemsMinValue = minValueValidation(items.minimum, true);
|
|
1191
951
|
}
|
|
1192
952
|
if (!isNaN(items.maximum)) {
|
|
1193
|
-
validators.itemsMaxValue = items.maximum;
|
|
953
|
+
validators.itemsMaxValue = maxValueValidation(items.maximum, true);
|
|
1194
954
|
}
|
|
1195
955
|
}
|
|
1196
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.
|
|
1197
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.
|
|
956
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DynamicFormService, deps: [{ token: i2.OpenApiService }, { token: i0.Injector }, { token: DynamicFormBuilderService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
957
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DynamicFormService });
|
|
1198
958
|
}
|
|
1199
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.
|
|
959
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DynamicFormService, decorators: [{
|
|
1200
960
|
type: Injectable
|
|
1201
|
-
}], ctorParameters: () => [{ type:
|
|
1202
|
-
type: Inject,
|
|
1203
|
-
args: [OpenApiService]
|
|
1204
|
-
}] }, { type: i0.Injector, decorators: [{
|
|
1205
|
-
type: Inject,
|
|
1206
|
-
args: [Injector]
|
|
1207
|
-
}] }] });
|
|
961
|
+
}], ctorParameters: () => [{ type: i2.OpenApiService }, { type: i0.Injector }, { type: DynamicFormBuilderService }] });
|
|
1208
962
|
|
|
1209
963
|
class AsyncSubmitDirective {
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
964
|
+
method = input(null, { alias: "async-submit" });
|
|
965
|
+
form = input();
|
|
966
|
+
context = input();
|
|
967
|
+
onSuccess = output();
|
|
968
|
+
onError = output();
|
|
969
|
+
toaster = inject(TOASTER_SERVICE);
|
|
970
|
+
renderer = inject(Renderer2);
|
|
971
|
+
elem = inject(ElementRef);
|
|
972
|
+
status = computed(() => {
|
|
973
|
+
const form = this.form();
|
|
974
|
+
return form?.status() || null;
|
|
975
|
+
});
|
|
976
|
+
group = computed(() => {
|
|
977
|
+
const form = this.form();
|
|
978
|
+
return form?.group() || null;
|
|
979
|
+
});
|
|
980
|
+
loading = signal(false);
|
|
981
|
+
callback = signal(null);
|
|
1224
982
|
get isDisabled() {
|
|
1225
|
-
return this.
|
|
1226
|
-
}
|
|
1227
|
-
set isDisabled(value) {
|
|
1228
|
-
this.disabled = value;
|
|
1229
|
-
if (value) {
|
|
1230
|
-
this.renderer.setAttribute(this.elem.nativeElement, "disabled", "disabled");
|
|
1231
|
-
return;
|
|
1232
|
-
}
|
|
1233
|
-
this.renderer.removeAttribute(this.elem.nativeElement, "disabled");
|
|
983
|
+
return this.status() !== "VALID";
|
|
1234
984
|
}
|
|
1235
985
|
get isLoading() {
|
|
1236
|
-
return this.loading;
|
|
1237
|
-
}
|
|
1238
|
-
constructor(toaster, cdr, zone, elem, renderer) {
|
|
1239
|
-
this.toaster = toaster;
|
|
1240
|
-
this.cdr = cdr;
|
|
1241
|
-
this.zone = zone;
|
|
1242
|
-
this.elem = elem;
|
|
1243
|
-
this.renderer = renderer;
|
|
1244
|
-
this.onSuccess = new EventEmitter();
|
|
1245
|
-
this.onError = new EventEmitter();
|
|
1246
|
-
if (elem.nativeElement.tagName !== "BUTTON")
|
|
1247
|
-
return;
|
|
1248
|
-
renderer.setAttribute(elem.nativeElement, "type", "button");
|
|
986
|
+
return this.loading();
|
|
1249
987
|
}
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
// console.log(
|
|
1261
|
-
// this.elem.nativeElement,
|
|
1262
|
-
// this.elem.nativeElement.focus
|
|
1263
|
-
// );
|
|
1264
|
-
// this.elem.nativeElement.focus?.();
|
|
1265
|
-
// }, 1500);
|
|
1266
|
-
}
|
|
1267
|
-
// Handle other things if we have a form instance
|
|
1268
|
-
if (!this.form)
|
|
1269
|
-
return;
|
|
1270
|
-
this.isDisabled = this.form.group?.status !== "VALID";
|
|
1271
|
-
this.cdr.detectChanges();
|
|
1272
|
-
this.subscription = ObservableUtils.multiSubscription(this.form.group?.statusChanges.subscribe(() => {
|
|
1273
|
-
const status = this.form.group?.status;
|
|
1274
|
-
this.isDisabled = status !== "VALID";
|
|
1275
|
-
this.cdr.detectChanges();
|
|
1276
|
-
if (!this.callback || status == "PENDING")
|
|
988
|
+
constructor() {
|
|
989
|
+
effect(() => {
|
|
990
|
+
if (this.elem.nativeElement.tagName === "BUTTON") {
|
|
991
|
+
this.renderer.setAttribute(this.elem.nativeElement, "type", "button");
|
|
992
|
+
}
|
|
993
|
+
});
|
|
994
|
+
effect(() => {
|
|
995
|
+
const status = this.status();
|
|
996
|
+
const cb = this.callback();
|
|
997
|
+
if (!cb || status == "PENDING")
|
|
1277
998
|
return;
|
|
1278
|
-
if (
|
|
1279
|
-
|
|
999
|
+
if (status === "VALID") {
|
|
1000
|
+
cb();
|
|
1280
1001
|
}
|
|
1281
|
-
this.callback
|
|
1282
|
-
})
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1002
|
+
this.callback.set(null);
|
|
1003
|
+
});
|
|
1004
|
+
effect(() => {
|
|
1005
|
+
const form = this.form();
|
|
1006
|
+
if (!form)
|
|
1007
|
+
return;
|
|
1008
|
+
const sub = outputToObservable(form.onSubmit)
|
|
1009
|
+
.pipe(debounceTime(200)).subscribe(() => this.callMethod());
|
|
1010
|
+
return () => sub.unsubscribe();
|
|
1011
|
+
});
|
|
1286
1012
|
}
|
|
1287
1013
|
click() {
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1014
|
+
const status = this.status();
|
|
1015
|
+
if (status !== "VALID" && status !== "INVALID") {
|
|
1016
|
+
this.callback.set(() => this.callMethod());
|
|
1291
1017
|
return;
|
|
1292
|
-
|
|
1293
|
-
this.
|
|
1018
|
+
}
|
|
1019
|
+
this.callMethod();
|
|
1294
1020
|
}
|
|
1295
1021
|
callMethod() {
|
|
1296
|
-
if (this.loading)
|
|
1022
|
+
if (this.loading())
|
|
1297
1023
|
return;
|
|
1298
|
-
this.loading
|
|
1299
|
-
this.method(this.form, this.context).then(result => {
|
|
1300
|
-
this.loading
|
|
1024
|
+
this.loading.set(true);
|
|
1025
|
+
this.method()(this.form(), this.context).then(result => {
|
|
1026
|
+
this.loading.set(false);
|
|
1301
1027
|
if (result) {
|
|
1302
1028
|
this.onSuccess.emit(result);
|
|
1303
1029
|
this.toaster.success(result.message, result.context);
|
|
@@ -1305,36 +1031,22 @@ class AsyncSubmitDirective {
|
|
|
1305
1031
|
}, reason => {
|
|
1306
1032
|
if (!reason || !reason.message)
|
|
1307
1033
|
throw new Error("Reason must implement IAsyncMessage interface");
|
|
1308
|
-
this.loading
|
|
1034
|
+
this.loading.set(false);
|
|
1309
1035
|
this.onError.emit(reason);
|
|
1310
1036
|
this.toaster.error(reason.message, reason.context);
|
|
1311
1037
|
});
|
|
1312
1038
|
}
|
|
1313
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.
|
|
1314
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "
|
|
1039
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AsyncSubmitDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
1040
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.14", type: AsyncSubmitDirective, isStandalone: false, selector: "[async-submit]", inputs: { method: { classPropertyName: "method", publicName: "async-submit", isSignal: true, isRequired: false, transformFunction: null }, form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null }, context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onSuccess: "onSuccess", onError: "onError" }, host: { listeners: { "click": "click()" }, properties: { "class.disabled": "this.isDisabled", "class.loading": "this.isLoading" } }, exportAs: ["async-submit"], ngImport: i0 });
|
|
1315
1041
|
}
|
|
1316
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.
|
|
1042
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AsyncSubmitDirective, decorators: [{
|
|
1317
1043
|
type: Directive,
|
|
1318
1044
|
args: [{
|
|
1319
1045
|
standalone: false,
|
|
1320
1046
|
selector: "[async-submit]",
|
|
1321
1047
|
exportAs: "async-submit"
|
|
1322
1048
|
}]
|
|
1323
|
-
}], ctorParameters: () => [
|
|
1324
|
-
type: Inject,
|
|
1325
|
-
args: [TOASTER_SERVICE]
|
|
1326
|
-
}] }, { type: i0.ChangeDetectorRef }, { type: i0.NgZone }, { type: i0.ElementRef }, { type: i0.Renderer2 }], propDecorators: { method: [{
|
|
1327
|
-
type: Input,
|
|
1328
|
-
args: ["async-submit"]
|
|
1329
|
-
}], form: [{
|
|
1330
|
-
type: Input
|
|
1331
|
-
}], context: [{
|
|
1332
|
-
type: Input
|
|
1333
|
-
}], onSuccess: [{
|
|
1334
|
-
type: Output
|
|
1335
|
-
}], onError: [{
|
|
1336
|
-
type: Output
|
|
1337
|
-
}], isDisabled: [{
|
|
1049
|
+
}], ctorParameters: () => [], propDecorators: { isDisabled: [{
|
|
1338
1050
|
type: HostBinding,
|
|
1339
1051
|
args: ["class.disabled"]
|
|
1340
1052
|
}], isLoading: [{
|
|
@@ -1345,616 +1057,124 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImpor
|
|
|
1345
1057
|
args: ["click"]
|
|
1346
1058
|
}] } });
|
|
1347
1059
|
|
|
1348
|
-
class
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
return !this.group ? null : this.group.status;
|
|
1364
|
-
}
|
|
1365
|
-
onValueChange;
|
|
1366
|
-
onStatusChange;
|
|
1367
|
-
onSubmit;
|
|
1368
|
-
onDetectChanges;
|
|
1369
|
-
subscription = new Subscription();
|
|
1370
|
-
groupSubscription = new Subscription();
|
|
1371
|
-
constructor(formService, events, changeDetectorRef, componentService) {
|
|
1372
|
-
super(changeDetectorRef, componentService);
|
|
1373
|
-
this.formService = formService;
|
|
1374
|
-
this.events = events;
|
|
1375
|
-
this.groupModel = undefined;
|
|
1376
|
-
this.labelPrefix = "";
|
|
1377
|
-
this.getComponentType = () => null;
|
|
1378
|
-
this.templates = new QueryList();
|
|
1379
|
-
this.onValueChange = new EventEmitter();
|
|
1380
|
-
this.onStatusChange = new EventEmitter();
|
|
1381
|
-
this.onSubmit = new EventEmitter();
|
|
1382
|
-
this.onDetectChanges = new EventEmitter();
|
|
1383
|
-
}
|
|
1384
|
-
submit() {
|
|
1385
|
-
this.onSubmit.emit(this);
|
|
1386
|
-
}
|
|
1387
|
-
ngOnChanges(changes) {
|
|
1388
|
-
this.groupSubscription.unsubscribe();
|
|
1389
|
-
if (this.group) {
|
|
1390
|
-
this.groupSubscription = ObservableUtils.multiSubscription(this.group.statusChanges.subscribe(() => {
|
|
1391
|
-
this.onStatusChange.emit(this);
|
|
1392
|
-
}), this.change.pipe(groupBy(ev => ev.model))
|
|
1393
|
-
.pipe(mergeMap(t => t.pipe(debounceTime(500))))
|
|
1394
|
-
.subscribe(ev => {
|
|
1395
|
-
this.onValueChange.emit({ ...ev, form: this });
|
|
1396
|
-
}));
|
|
1397
|
-
}
|
|
1398
|
-
if (changes.groupModel) {
|
|
1399
|
-
this.model = this.groupModel?.group;
|
|
1400
|
-
}
|
|
1401
|
-
if (changes.model) {
|
|
1402
|
-
this.groupModel = new DynamicFormGroupModel({ id: "root", group: this.model || [] });
|
|
1060
|
+
class DynamicFormComponent {
|
|
1061
|
+
builder = inject(DynamicFormBuilderService);
|
|
1062
|
+
labelPrefix = input("label");
|
|
1063
|
+
data = input({});
|
|
1064
|
+
fields = input(null);
|
|
1065
|
+
config$ = resource({
|
|
1066
|
+
request: () => ({
|
|
1067
|
+
fields: this.fields(),
|
|
1068
|
+
labelPrefix: this.labelPrefix()
|
|
1069
|
+
}),
|
|
1070
|
+
loader: async (p) => {
|
|
1071
|
+
const { fields, labelPrefix } = p.request;
|
|
1072
|
+
return fields || this.builder.resolveFormFields(this.data()?.constructor, null, {
|
|
1073
|
+
labelPrefix
|
|
1074
|
+
});
|
|
1403
1075
|
}
|
|
1404
|
-
}
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
this.subscription.unsubscribe();
|
|
1420
|
-
this.groupSubscription.unsubscribe();
|
|
1421
|
-
}
|
|
1422
|
-
detectChanges() {
|
|
1423
|
-
super.detectChanges();
|
|
1424
|
-
this.onDetectChanges.emit(this);
|
|
1425
|
-
}
|
|
1426
|
-
insertFormArrayGroup(index, formArray, formArrayModel) {
|
|
1427
|
-
this.formService.insertFormArrayGroup(index, formArray, formArrayModel);
|
|
1428
|
-
this.detectChanges();
|
|
1429
|
-
}
|
|
1430
|
-
cloneFormArrayGroup(index, formArray, formArrayModel) {
|
|
1431
|
-
this.formService.cloneFormArrayGroup(index, formArray, formArrayModel);
|
|
1432
|
-
this.detectChanges();
|
|
1433
|
-
}
|
|
1434
|
-
removeFormArrayGroup(index, formArray, formArrayModel) {
|
|
1435
|
-
this.formService.removeFormArrayGroup(index, formArray, formArrayModel);
|
|
1436
|
-
this.detectChanges();
|
|
1437
|
-
}
|
|
1438
|
-
moveFormArrayGroup(index, step, formArray, formArrayModel) {
|
|
1439
|
-
this.formService.moveFormArrayGroup(index, step, formArray, formArrayModel);
|
|
1440
|
-
this.detectChanges();
|
|
1441
|
-
}
|
|
1442
|
-
clearFormArray(formArray, formArrayModel) {
|
|
1443
|
-
this.formService.clearFormArray(formArray, formArrayModel);
|
|
1444
|
-
this.detectChanges();
|
|
1445
|
-
}
|
|
1446
|
-
getClass(model) {
|
|
1447
|
-
const parts = collectPathAble(model, p => p.id);
|
|
1448
|
-
if (parts.length == 0)
|
|
1449
|
-
return "";
|
|
1450
|
-
if (model instanceof DynamicFormGroupModel) {
|
|
1451
|
-
return `form-group-${parts.join("-")}`;
|
|
1076
|
+
});
|
|
1077
|
+
config = computed(() => this.config$.value());
|
|
1078
|
+
group = computed(() => {
|
|
1079
|
+
this.config();
|
|
1080
|
+
return new FormGroup$1({});
|
|
1081
|
+
});
|
|
1082
|
+
status$ = rxResource({
|
|
1083
|
+
request: () => this.group(),
|
|
1084
|
+
loader: p => p.request.statusChanges
|
|
1085
|
+
});
|
|
1086
|
+
status = computed(() => this.status$.value());
|
|
1087
|
+
onSubmit = output();
|
|
1088
|
+
options = {
|
|
1089
|
+
formState: {
|
|
1090
|
+
injector: inject(Injector)
|
|
1452
1091
|
}
|
|
1453
|
-
|
|
1092
|
+
};
|
|
1093
|
+
submit() {
|
|
1094
|
+
this.onSubmit.emit(this);
|
|
1454
1095
|
}
|
|
1455
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.
|
|
1456
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
1096
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DynamicFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1097
|
+
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()\">\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 });
|
|
1457
1098
|
}
|
|
1458
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.
|
|
1099
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DynamicFormComponent, decorators: [{
|
|
1459
1100
|
type: Component,
|
|
1460
|
-
args: [{
|
|
1461
|
-
|
|
1462
|
-
selector: "dynamic-base-form",
|
|
1463
|
-
template: "",
|
|
1464
|
-
changeDetection: ChangeDetectionStrategy.Default
|
|
1465
|
-
}]
|
|
1466
|
-
}], ctorParameters: () => [{ type: DynamicFormService, decorators: [{
|
|
1467
|
-
type: Inject,
|
|
1468
|
-
args: [DynamicFormService]
|
|
1469
|
-
}] }, { type: i2.EventsService, decorators: [{
|
|
1470
|
-
type: Inject,
|
|
1471
|
-
args: [EventsService]
|
|
1472
|
-
}] }, { type: i0.ChangeDetectorRef }, { type: i1.DynamicFormComponentService }], propDecorators: { group: [{
|
|
1473
|
-
type: Input
|
|
1474
|
-
}], model: [{
|
|
1475
|
-
type: Input
|
|
1476
|
-
}], layout: [{
|
|
1477
|
-
type: Input
|
|
1478
|
-
}], blur: [{
|
|
1479
|
-
type: Output
|
|
1480
|
-
}], change: [{
|
|
1481
|
-
type: Output
|
|
1482
|
-
}], focus: [{
|
|
1483
|
-
type: Output
|
|
1484
|
-
}], groupModel: [{
|
|
1485
|
-
type: Input
|
|
1486
|
-
}], labelPrefix: [{
|
|
1487
|
-
type: Input
|
|
1488
|
-
}], getComponentType: [{
|
|
1489
|
-
type: Input
|
|
1490
|
-
}], contentTemplates: [{
|
|
1491
|
-
type: ContentChildren,
|
|
1492
|
-
args: [DynamicTemplateDirective]
|
|
1493
|
-
}], viewTemplates: [{
|
|
1494
|
-
type: ViewChildren,
|
|
1495
|
-
args: [DynamicTemplateDirective]
|
|
1496
|
-
}], onValueChange: [{
|
|
1497
|
-
type: Output
|
|
1498
|
-
}], onStatusChange: [{
|
|
1499
|
-
type: Output
|
|
1500
|
-
}], onSubmit: [{
|
|
1501
|
-
type: Output
|
|
1502
|
-
}], onDetectChanges: [{
|
|
1503
|
-
type: Output
|
|
1504
|
-
}] } });
|
|
1101
|
+
args: [{ standalone: false, selector: "dynamic-form", encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (config() && group()) {\n <form [formGroup]=\"group()\" (ngSubmit)=\"submit()\">\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" }]
|
|
1102
|
+
}] });
|
|
1505
1103
|
|
|
1506
|
-
class
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
context = null;
|
|
1513
|
-
group = null;
|
|
1514
|
-
hostClass = null;
|
|
1515
|
-
inputTemplateList = null;
|
|
1516
|
-
layout = null;
|
|
1517
|
-
model = null;
|
|
1518
|
-
blur = new EventEmitter();
|
|
1519
|
-
change = new EventEmitter();
|
|
1520
|
-
focus = new EventEmitter();
|
|
1521
|
-
componentViewContainerRef = null;
|
|
1522
|
-
get componentType() {
|
|
1523
|
-
return this.form.getComponentType?.(this.model, this.injector)
|
|
1524
|
-
?? this.componentService.getCustomComponentType(this.model);
|
|
1525
|
-
}
|
|
1526
|
-
get startTemplate() {
|
|
1527
|
-
return (this.model.type == DYNAMIC_FORM_CONTROL_TYPE_ARRAY)
|
|
1528
|
-
? this.layoutService.getAlignedTemplate(this.model, this.templates, "ARRAY_START")
|
|
1529
|
-
: this.layoutService.getStartTemplate(this.model, this.templates);
|
|
1530
|
-
}
|
|
1531
|
-
get endTemplate() {
|
|
1532
|
-
return (this.model.type == DYNAMIC_FORM_CONTROL_TYPE_ARRAY)
|
|
1533
|
-
? this.layoutService.getAlignedTemplate(this.model, this.templates, "ARRAY_END")
|
|
1534
|
-
: this.layoutService.getEndTemplate(this.model, this.templates);
|
|
1535
|
-
}
|
|
1536
|
-
get formService() {
|
|
1537
|
-
return this.form.formService;
|
|
1538
|
-
}
|
|
1539
|
-
onDetectChanges;
|
|
1540
|
-
constructor(form, cdr, injector, cfr, layoutService, validationService, componentService, relationService) {
|
|
1541
|
-
super(cdr, cfr, layoutService, validationService, componentService, relationService);
|
|
1542
|
-
this.form = form;
|
|
1543
|
-
this.cdr = cdr;
|
|
1544
|
-
this.injector = injector;
|
|
1545
|
-
}
|
|
1546
|
-
ngOnInit() {
|
|
1547
|
-
super.ngOnInit();
|
|
1548
|
-
this.onDetectChanges = this.form.onDetectChanges.subscribe(() => {
|
|
1549
|
-
this.changeDetectorRef.detectChanges();
|
|
1550
|
-
});
|
|
1551
|
-
}
|
|
1552
|
-
ngOnDestroy() {
|
|
1553
|
-
super.ngOnDestroy();
|
|
1554
|
-
this.onDetectChanges.unsubscribe();
|
|
1555
|
-
}
|
|
1556
|
-
getLabel() {
|
|
1557
|
-
if (this.form?.labelPrefix) {
|
|
1558
|
-
const label = collectPathAble(this.model, p => p.id);
|
|
1559
|
-
if (label.length == 0) {
|
|
1560
|
-
return this.model.label;
|
|
1561
|
-
}
|
|
1562
|
-
label.unshift(this.form.labelPrefix);
|
|
1563
|
-
return label.join(".");
|
|
1104
|
+
class DynamicFormArrayComponent extends FieldArrayType {
|
|
1105
|
+
currentTab = signal(0);
|
|
1106
|
+
clear() {
|
|
1107
|
+
const control = this.formControl;
|
|
1108
|
+
while (control.length > 0) {
|
|
1109
|
+
this.remove(0);
|
|
1564
1110
|
}
|
|
1565
|
-
return this.model.label;
|
|
1566
1111
|
}
|
|
1567
|
-
|
|
1568
|
-
if (
|
|
1569
|
-
const arrayModel = this.context.context;
|
|
1570
|
-
if (arrayModel && arrayModel.sortBy == this.model.id) {
|
|
1571
|
-
return arrayModel.sortOrder;
|
|
1572
|
-
}
|
|
1573
|
-
}
|
|
1574
|
-
return null;
|
|
1575
|
-
}
|
|
1576
|
-
clickLabel() {
|
|
1577
|
-
if (this.context instanceof DynamicFormArrayGroupModel) {
|
|
1578
|
-
const arrayModel = this.context.context;
|
|
1579
|
-
if (arrayModel) {
|
|
1580
|
-
arrayModel.sortBy = this.model.id;
|
|
1581
|
-
}
|
|
1582
|
-
}
|
|
1583
|
-
}
|
|
1584
|
-
createFormControlComponent() {
|
|
1585
|
-
super.createFormControlComponent();
|
|
1586
|
-
const component = this.componentRef?.instance;
|
|
1587
|
-
if (!component || !ObjectUtils.isFunction(component.initialize))
|
|
1588
|
-
return;
|
|
1589
|
-
component.initialize(this.changeDetectorRef);
|
|
1590
|
-
}
|
|
1591
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: DynamicBaseFormControlContainerComponent, deps: [{ token: DynamicBaseFormComponent }, { token: i0.ChangeDetectorRef }, { token: i0.Injector }, { token: i0.ComponentFactoryResolver }, { token: i1.DynamicFormLayoutService }, { token: i1.DynamicFormValidationService }, { token: i1.DynamicFormComponentService }, { token: i1.DynamicFormRelationService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1592
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.3", type: DynamicBaseFormControlContainerComponent, isStandalone: false, selector: "dynamic-base-form-control", inputs: { context: "context", group: "group", hostClass: "hostClass", inputTemplateList: ["templates", "inputTemplateList"], layout: "layout", model: "model" }, outputs: { blur: "blur", change: "change", focus: "focus" }, host: { properties: { "class": "this.klass" } }, providers: [
|
|
1593
|
-
{ provide: DynamicFormControlContainerComponent, useExisting: DynamicBaseFormControlContainerComponent }
|
|
1594
|
-
], queries: [{ propertyName: "contentTemplateList", predicate: DynamicTemplateDirective }], viewQueries: [{ propertyName: "componentViewContainerRef", first: true, predicate: ["componentViewContainer"], descendants: true, read: ViewContainerRef, static: true }], usesInheritance: true, ngImport: i0, template: "", isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1112
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DynamicFormArrayComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
1113
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: DynamicFormArrayComponent, isStandalone: false, selector: "dynamic-form-array", usesInheritance: true, ngImport: i0, template: "<div class=\"ngx-dynamic-form-array\">\n <label class=\"form-label\" *ngIf=\"props.label\">\n {{ props.label }}\n <p class=\"form-array-description\" *ngIf=\"props.description\">{{ props.description }}</p>\n </label>\n <div class=\"ngx-dynamic-form-container\">\n @if (props.useTabs) {\n <ul class=\"form-array-tabs\">\n @for (field of field.fieldGroup; track field.key; let ix = $index) {\n <li>\n <a class=\"btn\" [ngClass]=\"[currentTab() === ix ? 'btn-primary' : 'btn-secondary']\"\n (click)=\"currentTab.set(ix)\">\n {{ (field.formControl.value | getValue : props.tabsLabel) || ix + 1 }}\n </a>\n </li>\n }\n </ul>\n }\n @for (field of field.fieldGroup; track field.key; let ix = $index) {\n @if (!props.useTabs || ix === currentTab()) {\n <div class=\"form-array-item\">\n <div class=\"form-array-buttons\">\n @if (props.removeItem) {\n <button type=\"button\" class=\"btn btn-sm btn-primary\" (click)=\"remove(ix)\">\n <i icon=\"trash-outline\"></i>\n </button>\n }\n @if (props.insertItem) {\n <button type=\"button\" class=\"btn btn-sm btn-primary\" (click)=\"add(ix)\">\n <i icon=\"plus-outline\"></i>\n </button>\n }\n </div>\n <formly-field [field]=\"field\"></formly-field>\n </div>\n }\n }\n <div class=\"form-array-buttons\">\n @if (props.clearItems) {\n <button type=\"button\" class=\"btn btn-sm btn-primary\" (click)=\"clear()\">\n <i icon=\"trash-outline\"></i>\n {{ 'button.clear-items' | translate }}\n </button>\n }\n @if (props.addItem) {\n <button type=\"button\" class=\"btn btn-sm btn-primary\" (click)=\"add()\">\n <i icon=\"plus-outline\"></i>\n {{ 'button.insert-item' | translate }}\n </button>\n }\n </div>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.IconDirective, selector: "[icon]", inputs: ["icon", "activeIcon", "active"], outputs: ["activeChange"] }, { kind: "component", type: i3.FormlyField, selector: "formly-field", inputs: ["field"] }, { kind: "pipe", type: i2.GetValuePipe, name: "getValue" }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None });
|
|
1595
1114
|
}
|
|
1596
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.
|
|
1115
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DynamicFormArrayComponent, decorators: [{
|
|
1597
1116
|
type: Component,
|
|
1598
|
-
args: [{
|
|
1599
|
-
|
|
1600
|
-
selector: "dynamic-base-form-control",
|
|
1601
|
-
template: "",
|
|
1602
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1603
|
-
providers: [
|
|
1604
|
-
{ provide: DynamicFormControlContainerComponent, useExisting: DynamicBaseFormControlContainerComponent }
|
|
1605
|
-
]
|
|
1606
|
-
}]
|
|
1607
|
-
}], ctorParameters: () => [{ type: DynamicBaseFormComponent }, { type: i0.ChangeDetectorRef }, { type: i0.Injector }, { type: i0.ComponentFactoryResolver }, { type: i1.DynamicFormLayoutService }, { type: i1.DynamicFormValidationService }, { type: i1.DynamicFormComponentService }, { type: i1.DynamicFormRelationService }], propDecorators: { contentTemplateList: [{
|
|
1608
|
-
type: ContentChildren,
|
|
1609
|
-
args: [DynamicTemplateDirective]
|
|
1610
|
-
}], klass: [{
|
|
1611
|
-
type: HostBinding,
|
|
1612
|
-
args: ["class"]
|
|
1613
|
-
}], context: [{
|
|
1614
|
-
type: Input
|
|
1615
|
-
}], group: [{
|
|
1616
|
-
type: Input
|
|
1617
|
-
}], hostClass: [{
|
|
1618
|
-
type: Input
|
|
1619
|
-
}], inputTemplateList: [{
|
|
1620
|
-
type: Input,
|
|
1621
|
-
args: ["templates"]
|
|
1622
|
-
}], layout: [{
|
|
1623
|
-
type: Input
|
|
1624
|
-
}], model: [{
|
|
1625
|
-
type: Input
|
|
1626
|
-
}], blur: [{
|
|
1627
|
-
type: Output
|
|
1628
|
-
}], change: [{
|
|
1629
|
-
type: Output
|
|
1630
|
-
}], focus: [{
|
|
1631
|
-
type: Output
|
|
1632
|
-
}], componentViewContainerRef: [{
|
|
1633
|
-
type: ViewChild,
|
|
1634
|
-
args: ["componentViewContainer", {
|
|
1635
|
-
read: ViewContainerRef,
|
|
1636
|
-
static: true
|
|
1637
|
-
}]
|
|
1638
|
-
}] } });
|
|
1117
|
+
args: [{ standalone: false, selector: "dynamic-form-array", encapsulation: ViewEncapsulation.None, template: "<div class=\"ngx-dynamic-form-array\">\n <label class=\"form-label\" *ngIf=\"props.label\">\n {{ props.label }}\n <p class=\"form-array-description\" *ngIf=\"props.description\">{{ props.description }}</p>\n </label>\n <div class=\"ngx-dynamic-form-container\">\n @if (props.useTabs) {\n <ul class=\"form-array-tabs\">\n @for (field of field.fieldGroup; track field.key; let ix = $index) {\n <li>\n <a class=\"btn\" [ngClass]=\"[currentTab() === ix ? 'btn-primary' : 'btn-secondary']\"\n (click)=\"currentTab.set(ix)\">\n {{ (field.formControl.value | getValue : props.tabsLabel) || ix + 1 }}\n </a>\n </li>\n }\n </ul>\n }\n @for (field of field.fieldGroup; track field.key; let ix = $index) {\n @if (!props.useTabs || ix === currentTab()) {\n <div class=\"form-array-item\">\n <div class=\"form-array-buttons\">\n @if (props.removeItem) {\n <button type=\"button\" class=\"btn btn-sm btn-primary\" (click)=\"remove(ix)\">\n <i icon=\"trash-outline\"></i>\n </button>\n }\n @if (props.insertItem) {\n <button type=\"button\" class=\"btn btn-sm btn-primary\" (click)=\"add(ix)\">\n <i icon=\"plus-outline\"></i>\n </button>\n }\n </div>\n <formly-field [field]=\"field\"></formly-field>\n </div>\n }\n }\n <div class=\"form-array-buttons\">\n @if (props.clearItems) {\n <button type=\"button\" class=\"btn btn-sm btn-primary\" (click)=\"clear()\">\n <i icon=\"trash-outline\"></i>\n {{ 'button.clear-items' | translate }}\n </button>\n }\n @if (props.addItem) {\n <button type=\"button\" class=\"btn btn-sm btn-primary\" (click)=\"add()\">\n <i icon=\"plus-outline\"></i>\n {{ 'button.insert-item' | translate }}\n </button>\n }\n </div>\n </div>\n</div>\n" }]
|
|
1118
|
+
}] });
|
|
1639
1119
|
|
|
1640
|
-
class
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
cdr;
|
|
1644
|
-
formLayout = null;
|
|
1645
|
-
group = null;
|
|
1646
|
-
layout = null;
|
|
1647
|
-
model = null;
|
|
1648
|
-
templates = null;
|
|
1649
|
-
blur = new EventEmitter();
|
|
1650
|
-
change = new EventEmitter();
|
|
1651
|
-
customEvent = new EventEmitter();
|
|
1652
|
-
focus = new EventEmitter();
|
|
1653
|
-
components = null;
|
|
1654
|
-
get useTabs() {
|
|
1655
|
-
return this.model?.useTabs;
|
|
1656
|
-
}
|
|
1657
|
-
subscription;
|
|
1658
|
-
constructor(layoutService, validationService, form, injector, cdr) {
|
|
1659
|
-
super(layoutService, validationService);
|
|
1660
|
-
this.form = form;
|
|
1661
|
-
this.injector = injector;
|
|
1662
|
-
this.cdr = cdr;
|
|
1663
|
-
}
|
|
1664
|
-
initialize(cdr) {
|
|
1665
|
-
this.subscription = this.model.filteredGroups.subscribe(filteredGroups => {
|
|
1666
|
-
this.updateGroups(filteredGroups);
|
|
1667
|
-
});
|
|
1668
|
-
this.model.initialize(this.array);
|
|
1669
|
-
}
|
|
1670
|
-
ngOnDestroy() {
|
|
1671
|
-
if (this.subscription)
|
|
1672
|
-
this.subscription.unsubscribe();
|
|
1673
|
-
}
|
|
1674
|
-
saveTab(index) {
|
|
1675
|
-
this.model.saveTab(index, this.model.getFiltered(index), this.model, this.injector);
|
|
1676
|
-
}
|
|
1677
|
-
restoreTab() {
|
|
1678
|
-
return this.model.restoreTab(this.model, this.injector);
|
|
1679
|
-
}
|
|
1680
|
-
getTabLabel(index, model) {
|
|
1681
|
-
return this.model.getTabLabel(index, model, this.model, this.array, this.injector);
|
|
1682
|
-
}
|
|
1683
|
-
getClass(context, place, model) {
|
|
1684
|
-
return [
|
|
1685
|
-
context == "element" ? this.getModelClass(model) : null,
|
|
1686
|
-
context == "element" ? this.getAdditionalClass(model) : null,
|
|
1687
|
-
super.getClass(context, place, model),
|
|
1688
|
-
model instanceof DynamicFormValueControlModel ? model.additional?.classes : null
|
|
1689
|
-
].filter(cls => !!cls).join(" ");
|
|
1690
|
-
}
|
|
1691
|
-
getModelClass(model) {
|
|
1692
|
-
const parts = collectPathAble(model, p => p.id);
|
|
1693
|
-
if (parts.length == 0)
|
|
1694
|
-
return "";
|
|
1695
|
-
if (model instanceof DynamicFormGroupModel$1) {
|
|
1696
|
-
return `form-group-${parts.join("-")}`;
|
|
1697
|
-
}
|
|
1698
|
-
return `form-control-${parts.join("-")}`;
|
|
1699
|
-
}
|
|
1700
|
-
getAdditionalClass(model) {
|
|
1701
|
-
if (model instanceof DynamicFormArrayModel) {
|
|
1702
|
-
return model.additional?.classes;
|
|
1703
|
-
}
|
|
1704
|
-
if (model instanceof DynamicFormValueControlModel) {
|
|
1705
|
-
return model.additional?.classes;
|
|
1706
|
-
}
|
|
1707
|
-
return null;
|
|
1708
|
-
}
|
|
1709
|
-
updateGroups(filteredGroups) {
|
|
1710
|
-
this.cdr.detectChanges();
|
|
1711
|
-
this.components.forEach(t => t.cdr.detectChanges());
|
|
1712
|
-
}
|
|
1713
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: DynamicBaseFormArrayComponent, deps: [{ token: i1.DynamicFormLayoutService }, { token: i1.DynamicFormValidationService }, { token: DynamicBaseFormComponent }, { token: i0.Injector }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
1714
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.3", type: DynamicBaseFormArrayComponent, isStandalone: false, selector: "dynamic-base-form-array", inputs: { formLayout: "formLayout", group: "group", layout: "layout", model: "model", templates: "templates" }, outputs: { blur: "blur", change: "change", customEvent: "customEvent", focus: "focus" }, viewQueries: [{ propertyName: "components", predicate: i0.forwardRef(() => DynamicBaseFormControlContainerComponent), descendants: true }], usesInheritance: true, ngImport: i0, template: "", isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1120
|
+
class DynamicFormChipsComponent extends FieldType {
|
|
1121
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DynamicFormChipsComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
1122
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: DynamicFormChipsComponent, isStandalone: false, selector: "dynamic-form-chips", usesInheritance: true, ngImport: i0, template: "<chips [formControl]=\"formControl\"\n [type]=\"props.type\"\n [step]=\"props.step\"\n [minLength]=\"props.minLength\"\n [maxLength]=\"props.maxLength\"\n [min]=\"props.min\"\n [max]=\"props.max\"\n [multiple]=\"props.multiple\"\n [formlyAttributes]=\"field\">\n</chips>\n", dependencies: [{ 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.ChipsComponent, selector: "chips", inputs: ["value", "multiple", "disabled", "type", "min", "max", "minLength", "maxLength", "step", "placeholder", "unique", "options"], outputs: ["valueChange"] }, { kind: "directive", type: i3.ɵFormlyAttributes, selector: "[formlyAttributes]", inputs: ["formlyAttributes", "id"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
1715
1123
|
}
|
|
1716
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.
|
|
1124
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DynamicFormChipsComponent, decorators: [{
|
|
1717
1125
|
type: Component,
|
|
1718
|
-
args: [{
|
|
1719
|
-
|
|
1720
|
-
selector: "dynamic-base-form-array",
|
|
1721
|
-
template: "",
|
|
1722
|
-
changeDetection: ChangeDetectionStrategy.OnPush
|
|
1723
|
-
}]
|
|
1724
|
-
}], ctorParameters: () => [{ type: i1.DynamicFormLayoutService }, { type: i1.DynamicFormValidationService }, { type: DynamicBaseFormComponent }, { type: i0.Injector }, { type: i0.ChangeDetectorRef }], propDecorators: { formLayout: [{
|
|
1725
|
-
type: Input
|
|
1726
|
-
}], group: [{
|
|
1727
|
-
type: Input
|
|
1728
|
-
}], layout: [{
|
|
1729
|
-
type: Input
|
|
1730
|
-
}], model: [{
|
|
1731
|
-
type: Input
|
|
1732
|
-
}], templates: [{
|
|
1733
|
-
type: Input
|
|
1734
|
-
}], blur: [{
|
|
1735
|
-
type: Output
|
|
1736
|
-
}], change: [{
|
|
1737
|
-
type: Output
|
|
1738
|
-
}], customEvent: [{
|
|
1739
|
-
type: Output
|
|
1740
|
-
}], focus: [{
|
|
1741
|
-
type: Output
|
|
1742
|
-
}], components: [{
|
|
1743
|
-
type: ViewChildren,
|
|
1744
|
-
args: [forwardRef(() => DynamicBaseFormControlContainerComponent)]
|
|
1745
|
-
}] } });
|
|
1126
|
+
args: [{ standalone: false, selector: "dynamic-form-chips", encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<chips [formControl]=\"formControl\"\n [type]=\"props.type\"\n [step]=\"props.step\"\n [minLength]=\"props.minLength\"\n [maxLength]=\"props.maxLength\"\n [min]=\"props.min\"\n [max]=\"props.max\"\n [multiple]=\"props.multiple\"\n [formlyAttributes]=\"field\">\n</chips>\n" }]
|
|
1127
|
+
}] });
|
|
1746
1128
|
|
|
1747
|
-
class
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
cdr;
|
|
1751
|
-
formLayout = null;
|
|
1752
|
-
group = null;
|
|
1753
|
-
layout = null;
|
|
1754
|
-
model = null;
|
|
1755
|
-
blur = new EventEmitter();
|
|
1756
|
-
change = new EventEmitter();
|
|
1757
|
-
focus = new EventEmitter();
|
|
1758
|
-
subscription;
|
|
1759
|
-
constructor(layoutService, validationService, form, injector, cdr) {
|
|
1760
|
-
super(layoutService, validationService);
|
|
1761
|
-
this.form = form;
|
|
1762
|
-
this.injector = injector;
|
|
1763
|
-
this.cdr = cdr;
|
|
1764
|
-
}
|
|
1765
|
-
ngAfterViewInit() {
|
|
1766
|
-
this.subscription = this.control.valueChanges.pipe(debounceTime(500)).subscribe(value => {
|
|
1767
|
-
this.onValueChanged(value);
|
|
1768
|
-
});
|
|
1769
|
-
}
|
|
1770
|
-
ngOnDestroy() {
|
|
1771
|
-
if (!this.subscription)
|
|
1772
|
-
return;
|
|
1773
|
-
this.subscription.unsubscribe();
|
|
1774
|
-
}
|
|
1775
|
-
submit() {
|
|
1776
|
-
this.form?.submit();
|
|
1777
|
-
}
|
|
1778
|
-
onValueChanged(value) {
|
|
1779
|
-
}
|
|
1780
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: DynamicBaseFormControlComponent, deps: [{ token: i1.DynamicFormLayoutService }, { token: i1.DynamicFormValidationService }, { token: DynamicBaseFormComponent, optional: true }, { token: i0.Injector }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
1781
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.3", type: DynamicBaseFormControlComponent, isStandalone: false, selector: "dynamic-base-form-control", inputs: { formLayout: "formLayout", group: "group", layout: "layout", model: "model" }, outputs: { blur: "blur", change: "change", focus: "focus" }, usesInheritance: true, ngImport: i0, template: "", isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1129
|
+
class DynamicFormFieldComponent extends FieldWrapper {
|
|
1130
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DynamicFormFieldComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
1131
|
+
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: "<div [ngClass]=\"['ngx-dynamic-form-field', 'ngx-dynamic-form-' + field.type]\">\n <label class=\"control-label ng-star-inserted\" *ngIf=\"props.label\">\n {{ props.label | translate }}\n <span class=\"form-field-required\" *ngIf=\"props.required && props.hideRequiredMarker !== true\" aria-hidden=\"true\">*</span>\n <p class=\"form-field-description\" *ngIf=\"props.description\">\n {{ props.description | translate }}\n </p>\n </label>\n <div class=\"ngx-dynamic-form-control\">\n <ng-container #fieldComponent></ng-container>\n <div *ngIf=\"showError\" class=\"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</div>\n", dependencies: [{ kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { 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 });
|
|
1782
1132
|
}
|
|
1783
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.
|
|
1133
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DynamicFormFieldComponent, decorators: [{
|
|
1784
1134
|
type: Component,
|
|
1785
|
-
args: [{
|
|
1786
|
-
|
|
1787
|
-
selector: "dynamic-base-form-control",
|
|
1788
|
-
template: "",
|
|
1789
|
-
changeDetection: ChangeDetectionStrategy.OnPush
|
|
1790
|
-
}]
|
|
1791
|
-
}], ctorParameters: () => [{ type: i1.DynamicFormLayoutService }, { type: i1.DynamicFormValidationService }, { type: DynamicBaseFormComponent, decorators: [{
|
|
1792
|
-
type: Optional
|
|
1793
|
-
}] }, { type: i0.Injector }, { type: i0.ChangeDetectorRef }], propDecorators: { formLayout: [{
|
|
1794
|
-
type: Input
|
|
1795
|
-
}], group: [{
|
|
1796
|
-
type: Input
|
|
1797
|
-
}], layout: [{
|
|
1798
|
-
type: Input
|
|
1799
|
-
}], model: [{
|
|
1800
|
-
type: Input
|
|
1801
|
-
}], blur: [{
|
|
1802
|
-
type: Output
|
|
1803
|
-
}], change: [{
|
|
1804
|
-
type: Output
|
|
1805
|
-
}], focus: [{
|
|
1806
|
-
type: Output
|
|
1807
|
-
}] } });
|
|
1135
|
+
args: [{ standalone: false, selector: "dynamic-form-field", encapsulation: ViewEncapsulation.None, template: "<div [ngClass]=\"['ngx-dynamic-form-field', 'ngx-dynamic-form-' + field.type]\">\n <label class=\"control-label ng-star-inserted\" *ngIf=\"props.label\">\n {{ props.label | translate }}\n <span class=\"form-field-required\" *ngIf=\"props.required && props.hideRequiredMarker !== true\" aria-hidden=\"true\">*</span>\n <p class=\"form-field-description\" *ngIf=\"props.description\">\n {{ props.description | translate }}\n </p>\n </label>\n <div class=\"ngx-dynamic-form-control\">\n <ng-container #fieldComponent></ng-container>\n <div *ngIf=\"showError\" class=\"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</div>\n" }]
|
|
1136
|
+
}] });
|
|
1808
1137
|
|
|
1809
|
-
class
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
group = null;
|
|
1814
|
-
layout = null;
|
|
1815
|
-
model = null;
|
|
1816
|
-
templates = [];
|
|
1817
|
-
blur = new EventEmitter();
|
|
1818
|
-
change = new EventEmitter();
|
|
1819
|
-
customEvent = new EventEmitter();
|
|
1820
|
-
focus = new EventEmitter();
|
|
1821
|
-
components = null;
|
|
1822
|
-
constructor(layoutService, validationService) {
|
|
1823
|
-
super(layoutService, validationService);
|
|
1824
|
-
this.layoutService = layoutService;
|
|
1825
|
-
this.validationService = validationService;
|
|
1826
|
-
}
|
|
1827
|
-
getClass(context, place, model) {
|
|
1828
|
-
return [
|
|
1829
|
-
context == "element" ? this.getModelClass(model) : null,
|
|
1830
|
-
context == "element" ? this.getAdditionalClass(model) : null,
|
|
1831
|
-
super.getClass(context, place, model)
|
|
1832
|
-
].filter(cls => !!cls).join(" ");
|
|
1833
|
-
}
|
|
1834
|
-
getModelClass(model) {
|
|
1835
|
-
const parts = collectPathAble(model, p => p.id);
|
|
1836
|
-
if (parts.length == 0)
|
|
1837
|
-
return "";
|
|
1838
|
-
if (model instanceof DynamicFormGroupModel) {
|
|
1839
|
-
return `form-group-${parts.join("-")}`;
|
|
1840
|
-
}
|
|
1841
|
-
return `form-control-${parts.join("-")}`;
|
|
1842
|
-
}
|
|
1843
|
-
getAdditionalClass(model) {
|
|
1844
|
-
if (model instanceof DynamicFormArrayModel) {
|
|
1845
|
-
return model.additional?.classes;
|
|
1846
|
-
}
|
|
1847
|
-
if (model instanceof DynamicFormValueControlModel) {
|
|
1848
|
-
return model.additional?.classes;
|
|
1849
|
-
}
|
|
1850
|
-
return null;
|
|
1138
|
+
class DynamicFormFieldsetComponent extends FieldWrapper {
|
|
1139
|
+
ngOnInit() {
|
|
1140
|
+
// console.log(this.field.id, this.field.props?.label, this.options);
|
|
1141
|
+
// console.log(this.field.parent);
|
|
1851
1142
|
}
|
|
1852
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.
|
|
1853
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.
|
|
1143
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DynamicFormFieldsetComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
1144
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: DynamicFormFieldsetComponent, isStandalone: false, selector: "dynamic-form-field", usesInheritance: true, ngImport: i0, template: "<div class=\"ngx-dynamic-form-fieldset\">\n <legend class=\"form-label\" *ngIf=\"props.label\">\n {{ props.label }}\n <p class=\"form-group-description\" *ngIf=\"props.description\">{{ props.description }}</p>\n </legend>\n <div class=\"ngx-dynamic-form-container\">\n <ng-container #fieldComponent></ng-container>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], encapsulation: i0.ViewEncapsulation.None });
|
|
1854
1145
|
}
|
|
1855
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.
|
|
1146
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DynamicFormFieldsetComponent, decorators: [{
|
|
1856
1147
|
type: Component,
|
|
1857
|
-
args: [{
|
|
1858
|
-
|
|
1859
|
-
selector: "dynamic-base-form-group",
|
|
1860
|
-
template: "",
|
|
1861
|
-
changeDetection: ChangeDetectionStrategy.OnPush
|
|
1862
|
-
}]
|
|
1863
|
-
}], ctorParameters: () => [{ type: i1.DynamicFormLayoutService }, { type: i1.DynamicFormValidationService }], propDecorators: { formLayout: [{
|
|
1864
|
-
type: Input
|
|
1865
|
-
}], group: [{
|
|
1866
|
-
type: Input
|
|
1867
|
-
}], layout: [{
|
|
1868
|
-
type: Input
|
|
1869
|
-
}], model: [{
|
|
1870
|
-
type: Input
|
|
1871
|
-
}], templates: [{
|
|
1872
|
-
type: Input
|
|
1873
|
-
}], blur: [{
|
|
1874
|
-
type: Output
|
|
1875
|
-
}], change: [{
|
|
1876
|
-
type: Output
|
|
1877
|
-
}], customEvent: [{
|
|
1878
|
-
type: Output
|
|
1879
|
-
}], focus: [{
|
|
1880
|
-
type: Output
|
|
1881
|
-
}], components: [{
|
|
1882
|
-
type: ViewChildren,
|
|
1883
|
-
args: [forwardRef(() => DynamicFormControlContainerComponent)]
|
|
1884
|
-
}] } });
|
|
1148
|
+
args: [{ standalone: false, selector: "dynamic-form-field", encapsulation: ViewEncapsulation.None, template: "<div class=\"ngx-dynamic-form-fieldset\">\n <legend class=\"form-label\" *ngIf=\"props.label\">\n {{ props.label }}\n <p class=\"form-group-description\" *ngIf=\"props.description\">{{ props.description }}</p>\n </legend>\n <div class=\"ngx-dynamic-form-container\">\n <ng-container #fieldComponent></ng-container>\n </div>\n</div>\n" }]
|
|
1149
|
+
}] });
|
|
1885
1150
|
|
|
1886
|
-
class
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
ngOnInit() {
|
|
1890
|
-
this.groups$ = new BehaviorSubject([]);
|
|
1891
|
-
this.subscription = this.model.options$.subscribe(options => {
|
|
1892
|
-
const groupBy = this.model.inline || !this.model.multiple ? this.model.groupBy : null;
|
|
1893
|
-
const grouped = options.reduce((res, option) => {
|
|
1894
|
-
const key = replaceSpecialChars(groupBy ? option.props[this.model.groupBy] || "default" : "default", "-");
|
|
1895
|
-
res[key] = res[key] || [];
|
|
1896
|
-
res[key].push(option);
|
|
1897
|
-
return res;
|
|
1898
|
-
}, {});
|
|
1899
|
-
const groups = Object.keys(grouped).map(group => {
|
|
1900
|
-
return {
|
|
1901
|
-
group,
|
|
1902
|
-
options: grouped[group]
|
|
1903
|
-
};
|
|
1904
|
-
});
|
|
1905
|
-
this.hasOptions = groups.length > 0;
|
|
1906
|
-
this.groups$.next(groups);
|
|
1907
|
-
this.cdr.detectChanges();
|
|
1908
|
-
});
|
|
1909
|
-
}
|
|
1910
|
-
ngOnDestroy() {
|
|
1911
|
-
if (this.subscription)
|
|
1912
|
-
this.subscription.unsubscribe();
|
|
1913
|
-
}
|
|
1914
|
-
isSelected(option) {
|
|
1915
|
-
if (this.model.multiple) {
|
|
1916
|
-
return this.control.value?.indexOf(option.value) >= 0;
|
|
1917
|
-
}
|
|
1918
|
-
return this.control.value == option.value;
|
|
1919
|
-
}
|
|
1920
|
-
selectToggle(option, state) {
|
|
1921
|
-
if (this.model.multiple) {
|
|
1922
|
-
const value = Array.from(this.control.value || []);
|
|
1923
|
-
const index = value.indexOf(option.value);
|
|
1924
|
-
if (index >= 0) {
|
|
1925
|
-
value.splice(index, 1);
|
|
1926
|
-
}
|
|
1927
|
-
if (state) {
|
|
1928
|
-
value.push(option.value);
|
|
1929
|
-
}
|
|
1930
|
-
this.control.setValue(value);
|
|
1931
|
-
this.onChange(value);
|
|
1932
|
-
return;
|
|
1933
|
-
}
|
|
1934
|
-
this.control.setValue(option.value);
|
|
1935
|
-
this.onChange(option.value);
|
|
1936
|
-
}
|
|
1937
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: DynamicBaseSelectComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
1938
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.3", type: DynamicBaseSelectComponent, isStandalone: false, selector: "dynamic-base-select", usesInheritance: true, ngImport: i0, template: "", isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1151
|
+
class DynamicFormGroupComponent extends FieldWrapper {
|
|
1152
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DynamicFormGroupComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
1153
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: DynamicFormGroupComponent, isStandalone: false, selector: "dynamic-form-group", usesInheritance: true, ngImport: i0, template: "<div class=\"ngx-dynamic-form-group\">\n <label class=\"form-group-label\" *ngIf=\"props.label\">\n {{ props.label }}\n <p class=\"form-group-description\" *ngIf=\"props.description\">{{ props.description }}</p>\n </label>\n <div class=\"ngx-dynamic-form-container\">\n <ng-container #fieldComponent></ng-container>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], encapsulation: i0.ViewEncapsulation.None });
|
|
1939
1154
|
}
|
|
1940
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.
|
|
1155
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DynamicFormGroupComponent, decorators: [{
|
|
1941
1156
|
type: Component,
|
|
1942
|
-
args: [{
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1157
|
+
args: [{ standalone: false, selector: "dynamic-form-group", encapsulation: ViewEncapsulation.None, template: "<div class=\"ngx-dynamic-form-group\">\n <label class=\"form-group-label\" *ngIf=\"props.label\">\n {{ props.label }}\n <p class=\"form-group-description\" *ngIf=\"props.description\">{{ props.description }}</p>\n </label>\n <div class=\"ngx-dynamic-form-container\">\n <ng-container #fieldComponent></ng-container>\n </div>\n</div>\n" }]
|
|
1158
|
+
}] });
|
|
1159
|
+
|
|
1160
|
+
class DynamicFormUploadComponent extends FieldType {
|
|
1161
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DynamicFormUploadComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
1162
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: DynamicFormUploadComponent, isStandalone: false, selector: "dynamic-form-upload", usesInheritance: true, ngImport: i0, template: "<upload [formControl]=\"formControl\"\n [multiple]=\"props.multiple\"\n [inline]=\"props.inline\"\n [accept]=\"props.accept\"\n [baseUrl]=\"props.url\"\n [makeUpload]=\"props.createUploadData\"\n [formlyAttributes]=\"field\">\n</upload>\n", dependencies: [{ 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.UploadComponent, selector: "upload", inputs: ["value", "disabled", "inline", "accept", "baseUrl", "message", "multiple", "buttonText", "makeUpload", "preProcess"], outputs: ["onUploaded", "onRemove"] }, { kind: "directive", type: i3.ɵFormlyAttributes, selector: "[formlyAttributes]", inputs: ["formlyAttributes", "id"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
1163
|
+
}
|
|
1164
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DynamicFormUploadComponent, decorators: [{
|
|
1165
|
+
type: Component,
|
|
1166
|
+
args: [{ standalone: false, selector: "dynamic-form-upload", encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<upload [formControl]=\"formControl\"\n [multiple]=\"props.multiple\"\n [inline]=\"props.inline\"\n [accept]=\"props.accept\"\n [baseUrl]=\"props.url\"\n [makeUpload]=\"props.createUploadData\"\n [formlyAttributes]=\"field\">\n</upload>\n" }]
|
|
1948
1167
|
}] });
|
|
1949
1168
|
|
|
1950
1169
|
// --- Components ---
|
|
1951
1170
|
const components = [
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1171
|
+
DynamicFormComponent,
|
|
1172
|
+
DynamicFormArrayComponent,
|
|
1173
|
+
DynamicFormChipsComponent,
|
|
1174
|
+
DynamicFormFieldComponent,
|
|
1175
|
+
DynamicFormFieldsetComponent,
|
|
1176
|
+
DynamicFormGroupComponent,
|
|
1177
|
+
DynamicFormUploadComponent
|
|
1958
1178
|
];
|
|
1959
1179
|
// --- Directives ---
|
|
1960
1180
|
const directives = [
|
|
@@ -1962,23 +1182,30 @@ const directives = [
|
|
|
1962
1182
|
];
|
|
1963
1183
|
// --- Pipes ---
|
|
1964
1184
|
const pipes = [];
|
|
1965
|
-
function defaultFormControlProvider() {
|
|
1966
|
-
return () => null;
|
|
1967
|
-
}
|
|
1968
1185
|
|
|
1969
1186
|
class NgxDynamicFormModule {
|
|
1970
1187
|
static getProviders(config) {
|
|
1188
|
+
const { providers } = FormlyModule.forRoot({
|
|
1189
|
+
types: [
|
|
1190
|
+
{ name: "array", component: DynamicFormArrayComponent },
|
|
1191
|
+
{ name: "chips", component: DynamicFormChipsComponent },
|
|
1192
|
+
{ name: "upload", component: DynamicFormUploadComponent, wrappers: ["form-field"] },
|
|
1193
|
+
{ name: "file", extends: "upload" },
|
|
1194
|
+
{ name: "translation", extends: "array" },
|
|
1195
|
+
],
|
|
1196
|
+
wrappers: [
|
|
1197
|
+
{ name: "form-field", component: DynamicFormFieldComponent },
|
|
1198
|
+
{ name: "form-fieldset", component: DynamicFormFieldsetComponent },
|
|
1199
|
+
{ name: "form-group", component: DynamicFormGroupComponent },
|
|
1200
|
+
],
|
|
1201
|
+
extras: {
|
|
1202
|
+
renderFormlyFieldElement: false
|
|
1203
|
+
}
|
|
1204
|
+
});
|
|
1971
1205
|
return [
|
|
1206
|
+
...providers,
|
|
1972
1207
|
DynamicFormService,
|
|
1973
|
-
|
|
1974
|
-
provide: DynamicFormService$1,
|
|
1975
|
-
useExisting: DynamicFormService
|
|
1976
|
-
},
|
|
1977
|
-
{
|
|
1978
|
-
provide: DYNAMIC_FORM_CONTROL_MAP_FN,
|
|
1979
|
-
useFactory: (config?.controlProvider || defaultFormControlProvider),
|
|
1980
|
-
deps: [Injector]
|
|
1981
|
-
}
|
|
1208
|
+
DynamicFormBuilderService
|
|
1982
1209
|
];
|
|
1983
1210
|
}
|
|
1984
1211
|
static forRoot(config) {
|
|
@@ -1990,41 +1217,27 @@ class NgxDynamicFormModule {
|
|
|
1990
1217
|
static provideForms(config) {
|
|
1991
1218
|
return makeEnvironmentProviders(NgxDynamicFormModule.getProviders(config));
|
|
1992
1219
|
}
|
|
1993
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.
|
|
1994
|
-
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.
|
|
1220
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: NgxDynamicFormModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
1221
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.14", ngImport: i0, type: NgxDynamicFormModule, declarations: [DynamicFormComponent, DynamicFormArrayComponent, DynamicFormChipsComponent, DynamicFormFieldComponent, DynamicFormFieldsetComponent, DynamicFormGroupComponent, DynamicFormUploadComponent, AsyncSubmitDirective], imports: [CommonModule,
|
|
1995
1222
|
FormsModule,
|
|
1996
1223
|
ReactiveFormsModule,
|
|
1997
|
-
NgxUtilsModule
|
|
1224
|
+
NgxUtilsModule,
|
|
1225
|
+
FormlyModule], exports: [DynamicFormComponent, DynamicFormArrayComponent, DynamicFormChipsComponent, DynamicFormFieldComponent, DynamicFormFieldsetComponent, DynamicFormGroupComponent, DynamicFormUploadComponent, AsyncSubmitDirective, FormsModule,
|
|
1998
1226
|
ReactiveFormsModule,
|
|
1999
|
-
NgxUtilsModule
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
{ provide: NG_VALIDATORS, useValue: validateRequiredTranslation, multi: true },
|
|
2004
|
-
{ provide: NG_VALIDATORS, useValue: validateItemsMinLength, multi: true },
|
|
2005
|
-
{ provide: NG_VALIDATORS, useValue: validateItemsMaxLength, multi: true },
|
|
2006
|
-
{ provide: NG_VALIDATORS, useValue: validateItemsMinValue, multi: true },
|
|
2007
|
-
{ provide: NG_VALIDATORS, useValue: validateItemsMaxValue, multi: true },
|
|
2008
|
-
{
|
|
2009
|
-
provide: DYNAMIC_VALIDATORS,
|
|
2010
|
-
useValue: new Map([
|
|
2011
|
-
["json", validateJSON],
|
|
2012
|
-
["requiredTranslation", validateRequiredTranslation],
|
|
2013
|
-
["phone", validatePhone],
|
|
2014
|
-
["itemsMinLength", validateItemsMinLength],
|
|
2015
|
-
["itemsMaxLength", validateItemsMaxLength],
|
|
2016
|
-
["itemsMinValue", validateItemsMinValue],
|
|
2017
|
-
["itemsMaxValue", validateItemsMaxValue],
|
|
2018
|
-
])
|
|
2019
|
-
}
|
|
1227
|
+
NgxUtilsModule,
|
|
1228
|
+
FormlyModule] });
|
|
1229
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: NgxDynamicFormModule, providers: [
|
|
1230
|
+
...pipes
|
|
2020
1231
|
], imports: [CommonModule,
|
|
2021
1232
|
FormsModule,
|
|
2022
1233
|
ReactiveFormsModule,
|
|
2023
|
-
NgxUtilsModule,
|
|
1234
|
+
NgxUtilsModule,
|
|
1235
|
+
FormlyModule, FormsModule,
|
|
2024
1236
|
ReactiveFormsModule,
|
|
2025
|
-
NgxUtilsModule
|
|
1237
|
+
NgxUtilsModule,
|
|
1238
|
+
FormlyModule] });
|
|
2026
1239
|
}
|
|
2027
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.
|
|
1240
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: NgxDynamicFormModule, decorators: [{
|
|
2028
1241
|
type: NgModule,
|
|
2029
1242
|
args: [{
|
|
2030
1243
|
declarations: [
|
|
@@ -2036,7 +1249,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImpor
|
|
|
2036
1249
|
CommonModule,
|
|
2037
1250
|
FormsModule,
|
|
2038
1251
|
ReactiveFormsModule,
|
|
2039
|
-
NgxUtilsModule
|
|
1252
|
+
NgxUtilsModule,
|
|
1253
|
+
FormlyModule
|
|
2040
1254
|
],
|
|
2041
1255
|
exports: [
|
|
2042
1256
|
...components,
|
|
@@ -2044,28 +1258,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImpor
|
|
|
2044
1258
|
...pipes,
|
|
2045
1259
|
FormsModule,
|
|
2046
1260
|
ReactiveFormsModule,
|
|
2047
|
-
NgxUtilsModule
|
|
1261
|
+
NgxUtilsModule,
|
|
1262
|
+
FormlyModule
|
|
2048
1263
|
],
|
|
2049
1264
|
providers: [
|
|
2050
|
-
...pipes
|
|
2051
|
-
{ provide: NG_VALIDATORS, useValue: validateJSON, multi: true },
|
|
2052
|
-
{ provide: NG_VALIDATORS, useValue: validateRequiredTranslation, multi: true },
|
|
2053
|
-
{ provide: NG_VALIDATORS, useValue: validateItemsMinLength, multi: true },
|
|
2054
|
-
{ provide: NG_VALIDATORS, useValue: validateItemsMaxLength, multi: true },
|
|
2055
|
-
{ provide: NG_VALIDATORS, useValue: validateItemsMinValue, multi: true },
|
|
2056
|
-
{ provide: NG_VALIDATORS, useValue: validateItemsMaxValue, multi: true },
|
|
2057
|
-
{
|
|
2058
|
-
provide: DYNAMIC_VALIDATORS,
|
|
2059
|
-
useValue: new Map([
|
|
2060
|
-
["json", validateJSON],
|
|
2061
|
-
["requiredTranslation", validateRequiredTranslation],
|
|
2062
|
-
["phone", validatePhone],
|
|
2063
|
-
["itemsMinLength", validateItemsMinLength],
|
|
2064
|
-
["itemsMaxLength", validateItemsMaxLength],
|
|
2065
|
-
["itemsMinValue", validateItemsMinValue],
|
|
2066
|
-
["itemsMaxValue", validateItemsMaxValue],
|
|
2067
|
-
])
|
|
2068
|
-
}
|
|
1265
|
+
...pipes
|
|
2069
1266
|
]
|
|
2070
1267
|
}]
|
|
2071
1268
|
}] });
|
|
@@ -2074,5 +1271,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImpor
|
|
|
2074
1271
|
* Generated bundle index. Do not edit.
|
|
2075
1272
|
*/
|
|
2076
1273
|
|
|
2077
|
-
export { AsyncSubmitDirective,
|
|
1274
|
+
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, customizeFormField, emailValidation, jsonValidation, maxLengthValidation, maxValueValidation, mergeFormFields, minLengthValidation, minValueValidation, phoneValidation, replaceSpecialChars, requiredValidation, translationValidation, validationMessage };
|
|
2078
1275
|
//# sourceMappingURL=stemy-ngx-dynamic-form.mjs.map
|