@stemy/ngx-dynamic-form 12.0.0 → 13.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/esm2020/ngx-dynamic-form/common-types.mjs +97 -0
  2. package/esm2020/ngx-dynamic-form/components/base/dynamic-base-form-array.component.mjs +85 -0
  3. package/esm2020/ngx-dynamic-form/components/base/dynamic-base-form-control-container.component.mjs +109 -0
  4. package/esm2020/ngx-dynamic-form/components/base/dynamic-base-form-group.component.mjs +74 -0
  5. package/esm2020/ngx-dynamic-form/components/base/dynamic-base-form.component.mjs +158 -0
  6. package/esm2020/ngx-dynamic-form/directives/async-submit.directive.mjs +111 -0
  7. package/esm2020/ngx-dynamic-form/ngx-dynamic-form.imports.mjs +19 -0
  8. package/esm2020/ngx-dynamic-form/ngx-dynamic-form.module.mjs +110 -0
  9. package/esm2020/ngx-dynamic-form/services/dynamic-form.service.mjs +451 -0
  10. package/esm2020/ngx-dynamic-form/utils/dynamic-form-array.model.mjs +16 -0
  11. package/esm2020/ngx-dynamic-form/utils/form-select-subject.mjs +23 -0
  12. package/esm2020/ngx-dynamic-form/utils/form-subject.mjs +29 -0
  13. package/esm2020/ngx-dynamic-form/utils/misc.mjs +18 -0
  14. package/esm2020/ngx-dynamic-form/utils/validators.mjs +56 -0
  15. package/esm2020/public_api.mjs +13 -0
  16. package/esm2020/stemy-ngx-dynamic-form.mjs +5 -0
  17. package/fesm2015/stemy-ngx-dynamic-form.mjs +1331 -0
  18. package/fesm2015/stemy-ngx-dynamic-form.mjs.map +1 -0
  19. package/fesm2020/stemy-ngx-dynamic-form.mjs +1303 -0
  20. package/fesm2020/stemy-ngx-dynamic-form.mjs.map +1 -0
  21. package/ngx-dynamic-form/common-types.d.ts +38 -262
  22. package/ngx-dynamic-form/components/base/dynamic-base-form-array.component.d.ts +29 -0
  23. package/ngx-dynamic-form/components/base/dynamic-base-form-control-container.component.d.ts +41 -0
  24. package/ngx-dynamic-form/components/base/dynamic-base-form-group.component.d.ts +24 -0
  25. package/ngx-dynamic-form/components/base/dynamic-base-form.component.d.ts +41 -0
  26. package/ngx-dynamic-form/directives/async-submit.directive.d.ts +10 -3
  27. package/ngx-dynamic-form/ngx-dynamic-form.imports.d.ts +8 -0
  28. package/ngx-dynamic-form/ngx-dynamic-form.module.d.ts +13 -17
  29. package/ngx-dynamic-form/services/dynamic-form.service.d.ts +47 -10
  30. package/ngx-dynamic-form/utils/dynamic-form-array.model.d.ts +22 -0
  31. package/ngx-dynamic-form/utils/form-select-subject.d.ts +6 -0
  32. package/ngx-dynamic-form/utils/form-subject.d.ts +10 -0
  33. package/ngx-dynamic-form/utils/misc.d.ts +3 -0
  34. package/ngx-dynamic-form/utils/validators.d.ts +8 -0
  35. package/package.json +42 -22
  36. package/public_api.d.ts +9 -14
  37. package/stemy-ngx-dynamic-form.d.ts +1 -3
  38. package/bundles/stemy-ngx-dynamic-form.umd.js +0 -2344
  39. package/bundles/stemy-ngx-dynamic-form.umd.js.map +0 -1
  40. package/esm2015/ngx-dynamic-form/common-types.js +0 -590
  41. package/esm2015/ngx-dynamic-form/components/base/dynamic-form-base.component.js +0 -87
  42. package/esm2015/ngx-dynamic-form/components/dynamic-form/dynamic-form.component.js +0 -91
  43. package/esm2015/ngx-dynamic-form/components/dynamic-form-file/dynamic-form-file.component.js +0 -112
  44. package/esm2015/ngx-dynamic-form/components/dynamic-form-group/dynamic-form-group.component.js +0 -19
  45. package/esm2015/ngx-dynamic-form/components/dynamic-form-input/dynamic-form-input.component.js +0 -69
  46. package/esm2015/ngx-dynamic-form/components/dynamic-form-model/dynamic-form-model.component.js +0 -23
  47. package/esm2015/ngx-dynamic-form/components/dynamic-form-select/dynamic-form-select.component.js +0 -73
  48. package/esm2015/ngx-dynamic-form/components/dynamic-form-static/dynamic-form-static.component.js +0 -20
  49. package/esm2015/ngx-dynamic-form/components/dynamic-forms/dynamic-forms.component.js +0 -134
  50. package/esm2015/ngx-dynamic-form/directives/async-submit.directive.js +0 -89
  51. package/esm2015/ngx-dynamic-form/directives/dynamic-form-control.directive.js +0 -32
  52. package/esm2015/ngx-dynamic-form/directives/dynamic-form-group.directive.js +0 -40
  53. package/esm2015/ngx-dynamic-form/directives/dynamic-form-template.directive.js +0 -38
  54. package/esm2015/ngx-dynamic-form/ngx-dynamic-form.module.js +0 -83
  55. package/esm2015/ngx-dynamic-form/services/dynamic-form.service.js +0 -48
  56. package/esm2015/ngx-dynamic-form/services/form-utilities.js +0 -108
  57. package/esm2015/ngx-dynamic-form/services/open-api.service.js +0 -130
  58. package/esm2015/public_api.js +0 -18
  59. package/esm2015/stemy-ngx-dynamic-form.js +0 -8
  60. package/fesm2015/stemy-ngx-dynamic-form.js +0 -1731
  61. package/fesm2015/stemy-ngx-dynamic-form.js.map +0 -1
  62. package/ngx-dynamic-form/components/base/dynamic-form-base.component.d.ts +0 -44
  63. package/ngx-dynamic-form/components/dynamic-form/dynamic-form.component.d.ts +0 -21
  64. package/ngx-dynamic-form/components/dynamic-form-file/dynamic-form-file.component.d.ts +0 -16
  65. package/ngx-dynamic-form/components/dynamic-form-group/dynamic-form-group.component.d.ts +0 -6
  66. package/ngx-dynamic-form/components/dynamic-form-input/dynamic-form-input.component.d.ts +0 -12
  67. package/ngx-dynamic-form/components/dynamic-form-model/dynamic-form-model.component.d.ts +0 -6
  68. package/ngx-dynamic-form/components/dynamic-form-select/dynamic-form-select.component.d.ts +0 -9
  69. package/ngx-dynamic-form/components/dynamic-form-static/dynamic-form-static.component.d.ts +0 -5
  70. package/ngx-dynamic-form/components/dynamic-forms/dynamic-forms.component.d.ts +0 -26
  71. package/ngx-dynamic-form/directives/dynamic-form-control.directive.d.ts +0 -12
  72. package/ngx-dynamic-form/directives/dynamic-form-group.directive.d.ts +0 -14
  73. package/ngx-dynamic-form/directives/dynamic-form-template.directive.d.ts +0 -16
  74. package/ngx-dynamic-form/services/form-utilities.d.ts +0 -19
  75. package/ngx-dynamic-form/services/open-api.service.d.ts +0 -37
  76. package/stemy-ngx-dynamic-form.metadata.json +0 -1
@@ -1,1731 +0,0 @@
1
- import { InjectionToken, Directive, HostBinding, Injectable, Inject, Type, ComponentFactoryResolver, Injector, EventEmitter, ChangeDetectorRef, ElementRef, Renderer2, Input, Output, HostListener, ViewContainerRef, TemplateRef, ContentChild, ContentChildren, Component, ViewChildren, ViewChild, NgModule } from '@angular/core';
2
- import { FormGroup, FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms';
3
- import { ObjectUtils, ReflectUtils, UniqueUtils, TimerUtils, FileUtils, FactoryDependencies, StringUtils, ApiService, TOASTER_SERVICE, ArrayUtils, LANGUAGE_SERVICE, NgxUtilsModule } from '@stemy/ngx-utils';
4
- import { __decorate } from 'tslib';
5
- import { DatePipe, CommonModule } from '@angular/common';
6
- import { first } from 'rxjs/operators';
7
-
8
- const FORM_GROUP_TYPE = new InjectionToken("form-group-provider");
9
- const FORM_CONTROL_PROVIDER = new InjectionToken("form-control-provider");
10
- class FormControlComponent {
11
- get form() {
12
- return !this.control ? null : this.control.form;
13
- }
14
- get data() {
15
- return (!this.control ? {} : this.control.data);
16
- }
17
- get value() {
18
- return !this.control ? null : this.control.value;
19
- }
20
- get meta() {
21
- return !this.control ? null : this.control.meta;
22
- }
23
- get inputClass() {
24
- return true;
25
- }
26
- }
27
- FormControlComponent.decorators = [
28
- { type: Directive }
29
- ];
30
- FormControlComponent.propDecorators = {
31
- inputClass: [{ type: HostBinding, args: ["class.form-input",] }]
32
- };
33
- function createValidator(control) {
34
- const data = control.data || {};
35
- const validators = [data.validator].concat(data.validators || []).filter(ObjectUtils.isDefined).map(v => {
36
- return ReflectUtils.resolve(v, control.injector);
37
- });
38
- return (ctrl) => new Promise((resolve) => {
39
- const control = ctrl;
40
- control.shouldValidate().then(should => {
41
- if (!should) {
42
- resolve(null);
43
- return;
44
- }
45
- const validate = validators.map(v => v(control));
46
- const metaValidator = control.meta.validator;
47
- if (ObjectUtils.isFunction(metaValidator)) {
48
- validate.push(metaValidator(control));
49
- }
50
- Promise.all(validate).then(results => {
51
- results = results.filter(error => ObjectUtils.isObject(error) || ObjectUtils.isString(error));
52
- let result = null;
53
- if (results.length > 0) {
54
- result = {};
55
- results.forEach(error => {
56
- if (ObjectUtils.isString(error)) {
57
- result[error] = {};
58
- return;
59
- }
60
- result = Object.assign(result, error);
61
- });
62
- }
63
- resolve(result);
64
- });
65
- });
66
- });
67
- }
68
- class DynamicFormControlHelper {
69
- constructor(form, control = null) {
70
- this.form = form;
71
- this.control = control;
72
- this.formId = UniqueUtils.uuid();
73
- this.meta = {};
74
- this.hidden = false;
75
- this.dummyData = {};
76
- this.readonlyTester = this.createTester("readonly");
77
- this.hideTester = this.createTester("hidden");
78
- this.serializeTester = this.createTester("shouldSerialize", (control) => {
79
- return Promise.resolve(control.visible);
80
- });
81
- this.validateTester = this.createTester("shouldValidate", (control) => {
82
- return Promise.resolve(control.visible);
83
- });
84
- }
85
- get id() {
86
- return !this.control ? null : this.control.id;
87
- }
88
- get type() {
89
- return !this.control ? "" : this.control.type;
90
- }
91
- get data() {
92
- return !this.control ? this.dummyData : this.control.data || this.dummyData;
93
- }
94
- get visible() {
95
- return !this.hidden;
96
- }
97
- get provider() {
98
- return this.ctrlProvider;
99
- }
100
- load(control) {
101
- return !this.ctrlProvider ? Promise.resolve(null) : this.ctrlProvider.loader(control);
102
- }
103
- check(control) {
104
- return new Promise(resolve => {
105
- this.hideTester(control).then(hide => {
106
- this.hidden = hide;
107
- this.readonlyTester(control).then(readonly => {
108
- resolve(control.form.readonly || readonly);
109
- });
110
- });
111
- });
112
- }
113
- shouldSerialize(control) {
114
- return this.serializeTester(control);
115
- }
116
- shouldValidate(control) {
117
- return this.validateTester(control);
118
- }
119
- findProvider(control) {
120
- this.ctrlProvider = !this.control || !this.control.type ? null : this.form.findProvider(control);
121
- }
122
- createTester(test, defaultFunc = null) {
123
- const tester = this.data[test]
124
- ? ReflectUtils.resolve(this.data[test], this.form.injector)
125
- : (defaultFunc || (() => Promise.resolve(false)));
126
- return (control) => tester(control);
127
- }
128
- }
129
- class DynamicFormGroup extends FormGroup {
130
- constructor(form, control = null) {
131
- super({}, { updateOn: ((!control || !control.data) ? null : control.data.updateOn) || form.updateOn || "blur" });
132
- this.form = form;
133
- this.mName = "";
134
- this.mModel = {};
135
- this.mControls = [];
136
- this.mSerializers = [];
137
- this.mFieldSets = {};
138
- this.helper = new DynamicFormControlHelper(form, control);
139
- this.helper.findProvider(this);
140
- this.initialized = false;
141
- this.loading = false;
142
- this.changeTimer = TimerUtils.createTimeout();
143
- this.statusChanges.subscribe(() => {
144
- const root = this.form.root;
145
- root.onStatusChange.emit(root);
146
- });
147
- this.setAsyncValidators(createValidator(this));
148
- }
149
- get id() {
150
- return this.helper.id;
151
- }
152
- get type() {
153
- return this.helper.type;
154
- }
155
- get data() {
156
- return this.helper.data;
157
- }
158
- get visible() {
159
- return this.helper.visible;
160
- }
161
- get meta() {
162
- return this.helper.meta;
163
- }
164
- get injector() {
165
- return this.form.injector;
166
- }
167
- get label() {
168
- return this.data.label !== "" ? `${this.prefix}${this.data.label}` : "";
169
- }
170
- get provider() {
171
- return this.helper.provider;
172
- }
173
- get model() {
174
- return this.mModel;
175
- }
176
- get formId() {
177
- return this.helper.formId;
178
- }
179
- get formControls() {
180
- return this.mControls || [];
181
- }
182
- get formFields() {
183
- return this.mFieldSets || {};
184
- }
185
- get prefix() {
186
- return !this.name ? "" : `${this.name}.`;
187
- }
188
- get name() {
189
- return this.mName;
190
- }
191
- get state() {
192
- return (this.loading ? "LOADING" : this.status);
193
- }
194
- static createFormControls(group, controls) {
195
- if (!controls && ObjectUtils.isObject(group.model)) {
196
- const props = Object.keys(group.model);
197
- controls = props.map(id => {
198
- return getFormControl(group.model, id);
199
- }).filter(ObjectUtils.isDefined);
200
- }
201
- if (!controls)
202
- return [];
203
- return controls.map(ctrl => {
204
- if (ctrl.type == "model") {
205
- const subGroup = new DynamicFormGroup(group.form, ctrl);
206
- const model = group.model[ctrl.id] || {};
207
- const data = subGroup.getData();
208
- data.name = data.name || group.name;
209
- subGroup.setup(model, data);
210
- group.model[ctrl.id] = model;
211
- group.addControl(subGroup.id, subGroup);
212
- return subGroup;
213
- }
214
- return new DynamicFormControl(ctrl, group);
215
- });
216
- }
217
- static createFormSerializers(group, serializers) {
218
- if (!serializers && ObjectUtils.isObject(group.model)) {
219
- const props = Object.keys(group.model);
220
- serializers = props.reduce((result, id) => {
221
- const serializer = getFormSerializer(group.model, id);
222
- if (!serializer)
223
- return result;
224
- result[id] = serializer;
225
- return result;
226
- }, {});
227
- }
228
- if (!serializers)
229
- return [];
230
- return Object.keys(serializers).map(id => {
231
- const serializer = serializers[id] || defaultSerializer;
232
- return !serializer ? null : {
233
- id: id,
234
- func: ReflectUtils.resolve(serializer, group.injector)
235
- };
236
- });
237
- }
238
- getData() {
239
- return this.data;
240
- }
241
- getControl(id) {
242
- return this.get(id);
243
- }
244
- load() {
245
- const promises = this.mControls.map(c => c.load());
246
- promises.push(this.helper.load(this));
247
- return Promise.all(promises);
248
- }
249
- check() {
250
- return new Promise(resolve => {
251
- this.helper.check(this).then(readonly => {
252
- if (readonly)
253
- this.disable({ emitEvent: false });
254
- else
255
- this.enable({ emitEvent: false });
256
- const promises = this.mControls.map(c => c.check());
257
- Promise.all(promises).then(resolve);
258
- });
259
- });
260
- }
261
- shouldSerialize() {
262
- return this.helper.shouldSerialize(this);
263
- }
264
- shouldValidate() {
265
- return this.helper.shouldValidate(this);
266
- }
267
- serialize() {
268
- return new Promise((resolve) => {
269
- const result = {};
270
- const serializers = this.mSerializers.map(s => {
271
- return new Promise(resolve => {
272
- s.func(s.id, this).then(res => {
273
- const ctrl = this.getControl(s.id);
274
- const promise = !ctrl ? Promise.resolve(true) : ctrl.shouldSerialize();
275
- promise.then(should => {
276
- if (should)
277
- result[s.id] = res;
278
- resolve(null);
279
- });
280
- });
281
- });
282
- });
283
- Promise.all(serializers).then(() => resolve(result));
284
- });
285
- }
286
- onFocus() {
287
- this.markAsUntouched({ onlySelf: true });
288
- }
289
- onBlur() {
290
- this.markAsTouched({ onlySelf: true });
291
- }
292
- showErrors() {
293
- this.markAsTouched({ onlySelf: true });
294
- this.mControls.forEach(ctrl => ctrl.showErrors());
295
- }
296
- reloadControls() {
297
- let callback = () => { };
298
- if (this.initialized === false) {
299
- this.initialized = true;
300
- this.loading = true;
301
- callback = () => {
302
- this.loading = false;
303
- // this.cdr.detectChanges();
304
- const root = this.form.root;
305
- root.onInit.emit(root);
306
- root.onStatusChange.emit(root);
307
- // https://github.com/angular/angular/issues/14542
308
- const statusTimer = TimerUtils.createInterval();
309
- statusTimer.set(() => {
310
- if (this.status == "PENDING")
311
- return;
312
- statusTimer.clear();
313
- root.onStatusChange.emit(root);
314
- }, 50);
315
- setTimeout(statusTimer.clear, 5000);
316
- };
317
- }
318
- const promise = new Promise(resolve => {
319
- this.load().then(() => this.check().then(resolve));
320
- });
321
- promise.then(callback, callback);
322
- return promise;
323
- }
324
- setup(model, info) {
325
- this.mName = info.name || "";
326
- this.mModel = model;
327
- this.mControls.forEach(ctrl => this.removeControl(ctrl.id));
328
- this.mControls = DynamicFormGroup.createFormControls(this, info.controls);
329
- this.mControls.forEach((ctrl) => this.addControl(ctrl.id, ctrl));
330
- this.mSerializers = DynamicFormGroup.createFormSerializers(this, info.serializers);
331
- this.mFieldSets = info.fieldSets ? info.fieldSets.reduce((result, fs) => {
332
- result[fs.id] = fs;
333
- return result;
334
- }, {}) : getFormFieldSets(Object.getPrototypeOf(model).constructor);
335
- }
336
- updateModel(control) {
337
- this.model[control.id] = control.value;
338
- this.changeTimer.clear();
339
- this.changeTimer.set(() => {
340
- this.check().then(() => this.reloadControlsFrom(control, new Set()).then(() => {
341
- this.form.root.onChange.emit(control);
342
- }));
343
- }, 250);
344
- }
345
- reloadControlsFrom(control, controls) {
346
- const data = control.data;
347
- if (!data || !data.reload)
348
- return Promise.resolve(null);
349
- const reload = ObjectUtils.isArray(data.reload) ? data.reload : [data.reload];
350
- return Promise.all(reload.map(id => {
351
- const nextControl = this.getControl(id);
352
- if (!nextControl || controls.has(nextControl))
353
- return Promise.resolve(null);
354
- controls.add(nextControl);
355
- return new Promise(resolve => {
356
- nextControl.load().then(() => {
357
- this.reloadControlsFrom(nextControl, controls).then(resolve);
358
- });
359
- });
360
- }));
361
- }
362
- }
363
- class DynamicFormControl extends FormControl {
364
- constructor(control, group) {
365
- super(group.model[control.id], { updateOn: control.data.updateOn || group.updateOn });
366
- this.control = control;
367
- this.group = group;
368
- this.group.addControl(control.id, this);
369
- this.helper = new DynamicFormControlHelper(this.form, control);
370
- this.helper.findProvider(this);
371
- this.valueChanges.subscribe(() => this.group.updateModel(this));
372
- this.setAsyncValidators(createValidator(this));
373
- }
374
- get id() {
375
- return this.helper.id;
376
- }
377
- get type() {
378
- return this.helper.type;
379
- }
380
- get data() {
381
- return this.helper.data;
382
- }
383
- get visible() {
384
- return this.helper.visible;
385
- }
386
- get meta() {
387
- return this.helper.meta;
388
- }
389
- get form() {
390
- return this.group.form;
391
- }
392
- get injector() {
393
- return this.form.injector;
394
- }
395
- get label() {
396
- return this.data.label !== "" ? `${this.group.prefix}${this.data.label}` : "";
397
- }
398
- get provider() {
399
- return this.helper.provider;
400
- }
401
- get model() {
402
- return this.group.model;
403
- }
404
- get formId() {
405
- return this.helper.formId;
406
- }
407
- getData() {
408
- return this.data;
409
- }
410
- getControl(id) {
411
- return null;
412
- }
413
- load() {
414
- return this.helper.load(this);
415
- }
416
- check() {
417
- const check = this.helper.check(this);
418
- check.then(readonly => {
419
- if (readonly || this.group.disabled)
420
- this.disable({ emitEvent: false });
421
- else
422
- this.enable({ emitEvent: false });
423
- });
424
- return check;
425
- }
426
- shouldSerialize() {
427
- return this.helper.shouldSerialize(this);
428
- }
429
- shouldValidate() {
430
- return this.helper.shouldValidate(this);
431
- }
432
- serialize() {
433
- return Promise.resolve(this.value);
434
- }
435
- onFocus() {
436
- this.markAsUntouched({ onlySelf: true });
437
- }
438
- onBlur() {
439
- this.markAsTouched({ onlySelf: true });
440
- }
441
- showErrors() {
442
- this.markAsTouched({ onlySelf: true });
443
- }
444
- }
445
- // --- Decorator functions ---
446
- const emptyArray = [];
447
- const emptyTester = () => {
448
- return Promise.resolve(false);
449
- };
450
- const ɵ0 = emptyTester;
451
- function defaultSerializer(id, parent) {
452
- const control = parent.getControl(id);
453
- return !control ? Promise.resolve(parent.model[id]) : control.serialize();
454
- }
455
- function FormSerializable(serializer) {
456
- return (target, propertyKey) => {
457
- ReflectUtils.defineMetadata("dynamicFormSerializer", serializer || defaultSerializer, target, propertyKey);
458
- };
459
- }
460
- function FormInput(data) {
461
- return (target, propertyKey) => {
462
- const meta = ReflectUtils.getOwnMetadata("design:type", target, propertyKey);
463
- const type = meta ? meta.name : "";
464
- let inputType = propertyKey.indexOf("password") < 0 ? "text" : "password";
465
- switch (type) {
466
- case "Number":
467
- inputType = "number";
468
- break;
469
- case "Boolean":
470
- inputType = "checkbox";
471
- break;
472
- }
473
- defineFormControl(target, propertyKey, createFormInput(propertyKey, data, inputType));
474
- };
475
- }
476
- function FormSelect(data) {
477
- return (target, propertyKey) => {
478
- defineFormControl(target, propertyKey, createFormSelect(propertyKey, data));
479
- };
480
- }
481
- function FormStatic(data) {
482
- return (target, propertyKey) => {
483
- defineFormControl(target, propertyKey, createFormStatic(propertyKey, data));
484
- };
485
- }
486
- function FormModel(data) {
487
- return (target, propertyKey) => {
488
- defineFormControl(target, propertyKey, createFormModel(propertyKey, data));
489
- };
490
- }
491
- function FormFile(data) {
492
- return (target, propertyKey) => {
493
- defineFormControl(target, propertyKey, createFormFile(propertyKey, data));
494
- };
495
- }
496
- function FormFieldSet(data) {
497
- return (target) => {
498
- const sets = getFormFieldSets(target);
499
- data.classes = data.classes || "";
500
- sets[data.id] = data;
501
- ReflectUtils.defineMetadata("dynamicFormFieldSets", sets, target);
502
- };
503
- }
504
- function provideFormGroup(component) {
505
- return {
506
- provide: FORM_GROUP_TYPE,
507
- useValue: component
508
- };
509
- }
510
- function provideFormControl(component, acceptor, loader, priority = 0) {
511
- return {
512
- provide: FORM_CONTROL_PROVIDER,
513
- multi: true,
514
- useValue: {
515
- component: component,
516
- priority: priority,
517
- acceptor: acceptor,
518
- loader: loader
519
- }
520
- };
521
- }
522
- function defineFormControl(target, propertyKey, control) {
523
- ReflectUtils.defineMetadata("dynamicFormControl", control, target, propertyKey);
524
- }
525
- function getFormFieldSets(target) {
526
- return ReflectUtils.getMetadata("dynamicFormFieldSets", target) || {};
527
- }
528
- function getFormControl(target, propertyKey) {
529
- return ReflectUtils.getMetadata("dynamicFormControl", target, propertyKey);
530
- }
531
- function getFormSerializer(target, propertyKey) {
532
- return ReflectUtils.getMetadata("dynamicFormSerializer", target, propertyKey);
533
- }
534
- function createFormControl(id, type, data) {
535
- data = data || {};
536
- data.label = ObjectUtils.isNullOrUndefined(data.label) ? id : data.label;
537
- data.labelAlign = data.labelAlign || "left";
538
- data.fieldSet = data.fieldSet || UniqueUtils.uuid();
539
- data.classes = data.classes || "";
540
- data.readonly = data.readonly || emptyTester;
541
- data.hidden = data.hidden || emptyTester;
542
- data.validators = data.validators || emptyArray;
543
- return {
544
- id: id,
545
- type: type,
546
- data: data
547
- };
548
- }
549
- function createFormInput(id, data, type = "text") {
550
- const control = createFormControl(id, "input", data);
551
- data = control.data;
552
- data.type = data.type || type;
553
- data.classes = !data.classes ? `form-group-${data.type}` : `${data.classes} form-group-${data.type}`;
554
- data.placeholder = data.placeholder || "";
555
- data.step = data.step || 1;
556
- return control;
557
- }
558
- function createFormSelect(id, data) {
559
- const control = createFormControl(id, "select", data);
560
- data = control.data;
561
- data.options = data.options || (() => Promise.resolve([]));
562
- data.type = data.type || "select";
563
- const classType = data.type == "select" ? "select" : `select-${data.type}`;
564
- data.classes = !data.classes ? `form-group-${classType}` : `${data.classes} form-group-${classType}`;
565
- return control;
566
- }
567
- function createFormStatic(id, data) {
568
- const control = createFormControl(id, "static", data);
569
- data = control.data;
570
- data.style = data.style || "table";
571
- return control;
572
- }
573
- function createFormModel(id, data) {
574
- const control = createFormControl(id, "model", data);
575
- data = control.data;
576
- data.name = data.name || "";
577
- return control;
578
- }
579
- function createFormFile(id, data) {
580
- const control = createFormControl(id, "file", data);
581
- data = control.data;
582
- data.accept = data.accept || ".jpg,.jpeg,.png";
583
- data.multi = data.multi || false;
584
- data.baseUrl = ObjectUtils.isString(data.baseUrl) ? data.baseUrl : "assets/";
585
- data.uploadUrl = ObjectUtils.isString(data.uploadUrl) ? data.uploadUrl : "assets";
586
- data.createUploadData = data.createUploadData || ((file) => {
587
- const form = new FormData();
588
- form.append("file", file);
589
- return form;
590
- });
591
- return control;
592
- }
593
-
594
- class DynamicFormService {
595
- constructor(components, groupType, resolver, injector) {
596
- this.components = components;
597
- this.groupType = groupType;
598
- this.resolver = resolver;
599
- this.injector = injector;
600
- }
601
- findProvider(control) {
602
- if (!control)
603
- return null;
604
- const providers = this.components.filter(p => p.acceptor(control));
605
- if (providers.length == 0) {
606
- throw new Error(`No component provider for control: ${JSON.stringify({
607
- id: control.id,
608
- type: control.type,
609
- data: control.data
610
- })}`);
611
- }
612
- // Sort providers
613
- providers.sort((a, b) => ObjectUtils.compare(a.priority, b.priority));
614
- return providers[0];
615
- }
616
- createComponent(vcr, provider) {
617
- vcr.clear();
618
- if (!provider)
619
- return null;
620
- const factory = this.resolver.resolveComponentFactory(provider.component);
621
- return vcr.createComponent(factory).instance;
622
- }
623
- createGroup(vcr) {
624
- vcr.clear();
625
- const factory = this.resolver.resolveComponentFactory(this.groupType);
626
- return vcr.createComponent(factory).instance;
627
- }
628
- }
629
- DynamicFormService.decorators = [
630
- { type: Injectable }
631
- ];
632
- DynamicFormService.ctorParameters = () => [
633
- { type: Array, decorators: [{ type: Inject, args: [FORM_CONTROL_PROVIDER,] }] },
634
- { type: Type, decorators: [{ type: Inject, args: [FORM_GROUP_TYPE,] }] },
635
- { type: ComponentFactoryResolver },
636
- { type: Injector }
637
- ];
638
-
639
- class FormUtilities {
640
- static checkField(expression = `true`) {
641
- // @dynamic
642
- const lambda = (control) => {
643
- return Promise.resolve(ObjectUtils.evaluate(expression, { control: control }));
644
- };
645
- return lambda;
646
- }
647
- static checkReadonly(control) {
648
- return Promise.resolve(control.visible && !control.disabled);
649
- }
650
- static readonly() {
651
- return Promise.resolve(true);
652
- }
653
- static validateJSON(control) {
654
- const value = control.value;
655
- if (!value)
656
- return Promise.resolve(null);
657
- try {
658
- JSON.parse(value);
659
- return Promise.resolve(null);
660
- }
661
- catch (e) {
662
- return Promise.resolve("error.not-valid-json");
663
- }
664
- }
665
- static validateRequired(control) {
666
- const value = control.value;
667
- return Promise.resolve(!ObjectUtils.isNumber(value) && !value ? "error.required" : null);
668
- }
669
- static validateMinLength(length) {
670
- // @dynamic
671
- const lambda = (control) => {
672
- const value = control.value;
673
- if (!ObjectUtils.isString(value) || value.length < length) {
674
- return Promise.resolve({ "error.min-length": { length: length } });
675
- }
676
- return Promise.resolve(null);
677
- };
678
- return lambda;
679
- }
680
- static validateMaxLength(length) {
681
- // @dynamic
682
- const lambda = (control) => {
683
- const value = control.value;
684
- if (!ObjectUtils.isString(value) || value.length > length) {
685
- return Promise.resolve({ "error.max-length": { length: length } });
686
- }
687
- return Promise.resolve(null);
688
- };
689
- return lambda;
690
- }
691
- static validateRequiredTranslation(control) {
692
- const value = control.value;
693
- if (!value || value.length == 0)
694
- return Promise.resolve("error.required");
695
- return Promise.resolve(value.findIndex(t => (t.lang == "de" || t.lang == "en") && !t.translation) < 0 ? null : "error.required");
696
- }
697
- static validateEmail(control) {
698
- const value = control.value;
699
- if (!value)
700
- return Promise.resolve(null);
701
- const emailRegexp = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
702
- return Promise.resolve(emailRegexp.test(value) ? null : "error.invalid-email");
703
- }
704
- static validatePhone(control) {
705
- const value = control.value;
706
- if (!value)
707
- return Promise.resolve(null);
708
- const phoneRegexp = /^(?:\d){10,12}$/;
709
- return Promise.resolve(phoneRegexp.test(value) ? null : "error.invalid-phone");
710
- }
711
- static serializeLogo(id, parent) {
712
- const value = parent.model[id];
713
- return Promise.resolve(!value || value.length == 0 ? null : value);
714
- }
715
- static serializeFile(id, parent) {
716
- const value = parent.model[id];
717
- if (ObjectUtils.isBlob(value))
718
- return Promise.resolve(value);
719
- return Promise.resolve(!ObjectUtils.isString(value) || !value.startsWith("data:") ? null : FileUtils.dataToBlob(value));
720
- }
721
- static serializeNumber(id, parent) {
722
- const value = parent.model[id];
723
- return Promise.resolve(!value || value.length == 0 ? 0 : parseFloat(value));
724
- }
725
- static serializeJSON(id, parent) {
726
- const value = parent.model[id];
727
- return Promise.resolve(!value ? {} : JSON.parse(value));
728
- }
729
- static serializeDate(date, format = "yyyy-MM-dd", defaultValue = "") {
730
- // @dynamic
731
- const lambda = (id, parent) => {
732
- const value = parent.model[id];
733
- if (!ObjectUtils.isDate(value))
734
- return Promise.resolve(value || defaultValue);
735
- return Promise.resolve(!format ? value : date.transform(value, format));
736
- };
737
- return lambda;
738
- }
739
- }
740
- __decorate([
741
- FactoryDependencies(DatePipe)
742
- ], FormUtilities, "serializeDate", null);
743
-
744
- class OpenApiService {
745
- constructor(api) {
746
- this.api = api;
747
- const baseUrl = this.api.url("").replace("api/", "api-docs");
748
- this.schemas = {};
749
- this.schemasPromise = new Promise((resolve => {
750
- this.api.client.get(baseUrl).subscribe((res) => {
751
- this.schemas = res.definitions || {};
752
- resolve(this.schemas);
753
- }, () => {
754
- resolve({});
755
- });
756
- }));
757
- }
758
- getFormInputsForSchema(name) {
759
- this.api.cache = {};
760
- return this.schemasPromise.then(schemas => {
761
- const schema = schemas[name];
762
- const inputs = this.getFormInputsForSchemaDef(schema);
763
- return inputs;
764
- });
765
- }
766
- getFormInputsForSchemaDef(schema) {
767
- const inputs = {};
768
- if (!schema)
769
- return inputs;
770
- inputs.schema = schema;
771
- inputs.serializers = {};
772
- inputs.controls = Object.keys(schema.properties || {}).map(p => {
773
- const property = schema.properties[p];
774
- property.id = p;
775
- inputs.serializers[p] = (id, parent) => {
776
- return Promise.resolve(parent.model[id]);
777
- };
778
- return this.getFormControlForProperty(property, schema);
779
- }).filter(t => null !== t);
780
- return inputs;
781
- }
782
- getFormControlForProperty(property, schema) {
783
- if (Array.isArray(property.enum)) {
784
- return createFormSelect(property.id, this.getFormSelectData(property, schema));
785
- }
786
- switch (property.type) {
787
- case "string":
788
- case "number":
789
- case "boolean":
790
- case "textarea":
791
- return createFormInput(property.id, this.getFormInputData(property, schema));
792
- case "list":
793
- return createFormSelect(property.id, this.getFormSelectData(property, schema));
794
- case "file":
795
- return createFormFile(property.id, this.getFormFileData(property, schema));
796
- }
797
- return null;
798
- }
799
- getBaseFormData(property, schema) {
800
- return {
801
- readonly: property.readonly ? FormUtilities.readonly : null,
802
- shouldSerialize: FormUtilities.checkReadonly,
803
- validators: this.getValidators(property, schema)
804
- };
805
- }
806
- getFormInputData(property, schema) {
807
- let type = StringUtils.has(property.id, "password", "Password") ? "password" : property.type;
808
- switch (property.type) {
809
- case "boolean":
810
- type = "checkbox";
811
- break;
812
- case "textarea":
813
- type = "textarea";
814
- break;
815
- }
816
- return Object.assign(Object.assign({}, this.getBaseFormData(property, schema)), { type });
817
- }
818
- getFormSelectData(property, schema) {
819
- const options = Array.isArray(property.enum)
820
- ? () => {
821
- return Promise.resolve(property.enum.map(id => ({ id, label: `${property.id}.${id}` })));
822
- }
823
- : () => {
824
- this.api.cache[property.endpoint] = this.api.cache[property.endpoint] || this.api.list(property.endpoint, this.api.makeListParams(1, -1)).then(result => {
825
- return result.items.map(i => {
826
- return { id: i._id, label: i.name };
827
- });
828
- });
829
- return this.api.cache[property.endpoint];
830
- };
831
- return Object.assign(Object.assign({}, this.getBaseFormData(property, schema)), { options });
832
- }
833
- getFormFileData(property, schema) {
834
- return Object.assign(Object.assign({}, this.getBaseFormData(property, schema)), { multi: property.multi });
835
- }
836
- getValidators(property, schema) {
837
- const validators = [];
838
- if (schema.required.indexOf(property.id) >= 0) {
839
- validators.push(FormUtilities.validateRequired);
840
- }
841
- if (property.minLength) {
842
- validators.push({
843
- type: FormUtilities,
844
- func: FormUtilities.validateMinLength,
845
- params: [property.minLength]
846
- });
847
- }
848
- if (property.maxLength) {
849
- validators.push({
850
- type: FormUtilities,
851
- func: FormUtilities.validateMaxLength,
852
- params: [property.maxLength]
853
- });
854
- }
855
- switch (property.format) {
856
- case "email":
857
- validators.push(FormUtilities.validateEmail);
858
- break;
859
- }
860
- return validators;
861
- }
862
- }
863
- OpenApiService.decorators = [
864
- { type: Injectable }
865
- ];
866
- OpenApiService.ctorParameters = () => [
867
- { type: ApiService }
868
- ];
869
-
870
- class AsyncSubmitDirective {
871
- constructor(toaster, cdr, elem, renderer) {
872
- this.toaster = toaster;
873
- this.cdr = cdr;
874
- this.onSuccess = new EventEmitter();
875
- this.onError = new EventEmitter();
876
- if (elem.nativeElement.tagName !== "BUTTON")
877
- return;
878
- renderer.setAttribute(elem.nativeElement, "type", "button");
879
- }
880
- get isDisabled() {
881
- return this.disabled;
882
- }
883
- get isLoading() {
884
- return this.loading;
885
- }
886
- ngOnInit() {
887
- if (!this.form)
888
- return;
889
- this.disabled = this.form.status !== "VALID";
890
- this.cdr.detectChanges();
891
- this.onStatusChange = this.form.onStatusChange.subscribe(form => {
892
- this.disabled = form.status !== "VALID";
893
- this.cdr.detectChanges();
894
- if (!this.callback || form.status == "PENDING")
895
- return;
896
- if (!this.disabled) {
897
- this.callback();
898
- }
899
- this.callback = null;
900
- });
901
- this.onSubmit = this.form.onSubmit.subscribe(() => this.callMethod());
902
- }
903
- ngOnDestroy() {
904
- if (this.onStatusChange)
905
- this.onStatusChange.unsubscribe();
906
- if (this.onSubmit)
907
- this.onSubmit.unsubscribe();
908
- }
909
- click() {
910
- this.callback = () => this.callMethod();
911
- if (this.form.status !== "VALID" && this.form.status !== "INVALID")
912
- return;
913
- this.callback();
914
- this.callback = null;
915
- }
916
- callMethod() {
917
- if (this.loading)
918
- return;
919
- this.loading = true;
920
- this.method(this.form).then(result => {
921
- this.loading = false;
922
- if (result) {
923
- this.onSuccess.emit(result);
924
- this.toaster.success(result.message, result.context);
925
- }
926
- }, reason => {
927
- if (!reason || !reason.message)
928
- throw new Error("Reason must implement IAsyncMessage interface");
929
- this.loading = false;
930
- this.onError.emit(reason);
931
- this.toaster.error(reason.message, reason.context);
932
- });
933
- }
934
- }
935
- AsyncSubmitDirective.decorators = [
936
- { type: Directive, args: [{
937
- selector: "[async-submit]",
938
- exportAs: "async-submit"
939
- },] }
940
- ];
941
- AsyncSubmitDirective.ctorParameters = () => [
942
- { type: undefined, decorators: [{ type: Inject, args: [TOASTER_SERVICE,] }] },
943
- { type: ChangeDetectorRef },
944
- { type: ElementRef },
945
- { type: Renderer2 }
946
- ];
947
- AsyncSubmitDirective.propDecorators = {
948
- method: [{ type: Input, args: ["async-submit",] }],
949
- form: [{ type: Input }],
950
- onSuccess: [{ type: Output }],
951
- onError: [{ type: Output }],
952
- isDisabled: [{ type: HostBinding, args: ["class.disabled",] }],
953
- isLoading: [{ type: HostBinding, args: ["class.loading",] }],
954
- click: [{ type: HostListener, args: ["click",] }]
955
- };
956
-
957
- class DynamicFormControlDirective {
958
- constructor(vcr, forms) {
959
- this.vcr = vcr;
960
- this.forms = forms;
961
- }
962
- get component() {
963
- return this.comp;
964
- }
965
- ngOnChanges(changes) {
966
- if (changes.control) {
967
- this.comp = this.forms.createComponent(this.vcr, this.control.provider);
968
- }
969
- if (!this.comp)
970
- return;
971
- this.comp.control = this.control;
972
- }
973
- }
974
- DynamicFormControlDirective.decorators = [
975
- { type: Directive, args: [{
976
- selector: "[form-control]",
977
- },] }
978
- ];
979
- DynamicFormControlDirective.ctorParameters = () => [
980
- { type: ViewContainerRef },
981
- { type: DynamicFormService }
982
- ];
983
- DynamicFormControlDirective.propDecorators = {
984
- control: [{ type: Input, args: ["form-control",] }]
985
- };
986
-
987
- class DynamicFormTemplateDirective {
988
- constructor(template) {
989
- this.template = template;
990
- }
991
- }
992
- DynamicFormTemplateDirective.decorators = [
993
- { type: Directive, args: [{
994
- selector: `ng-template[control],
995
- ng-template[label],
996
- ng-template[input],
997
- ng-template[prefix],
998
- ng-template[suffix],
999
- ng-template[setPrefix],
1000
- ng-template[setSuffix],
1001
- ng-template[formPrefix],
1002
- ng-template[formSuffix],
1003
- ng-template[innerFormPrefix],
1004
- ng-template[innerFormSuffix]`
1005
- },] }
1006
- ];
1007
- DynamicFormTemplateDirective.ctorParameters = () => [
1008
- { type: TemplateRef }
1009
- ];
1010
- DynamicFormTemplateDirective.propDecorators = {
1011
- control: [{ type: Input }],
1012
- label: [{ type: Input }],
1013
- input: [{ type: Input }],
1014
- prefix: [{ type: Input }],
1015
- suffix: [{ type: Input }],
1016
- setPrefix: [{ type: Input }],
1017
- setSuffix: [{ type: Input }],
1018
- formPrefix: [{ type: Input }],
1019
- formSuffix: [{ type: Input }],
1020
- innerFormPrefix: [{ type: Input }],
1021
- innerFormSuffix: [{ type: Input }]
1022
- };
1023
-
1024
- class DynamicFormBaseComponent {
1025
- constructor(cdr, formService) {
1026
- this.formService = formService;
1027
- this.name = "";
1028
- this.controlTemplates = {};
1029
- this.labelTemplates = {};
1030
- this.inputTemplates = {};
1031
- this.prefixTemplates = {};
1032
- this.suffixTemplates = {};
1033
- this.onChange = new EventEmitter();
1034
- this.onStatusChange = new EventEmitter();
1035
- this.onInit = new EventEmitter();
1036
- this.onSubmit = new EventEmitter();
1037
- this.injector = formService.injector;
1038
- this.cdr = cdr;
1039
- }
1040
- get root() {
1041
- let form = this;
1042
- while (ObjectUtils.isDefined(form.parent)) {
1043
- form = form.parent;
1044
- }
1045
- return form;
1046
- }
1047
- findProvider(control) {
1048
- return this.formService.findProvider(control);
1049
- }
1050
- // --- Lifecycle hooks
1051
- ngAfterContentInit() {
1052
- this.wrapperTemplate = this.wrapperTemplate || this.cWrapperTemplate;
1053
- this.fieldSetTemplate = this.fieldSetTemplate || this.cFieldSetTemplate;
1054
- this.controlTemplate = this.controlTemplate || this.cControlTemplate;
1055
- this.controlTemplates = this.filterTemplates(this.controlTemplates, "control");
1056
- this.labelTemplates = this.filterTemplates(this.labelTemplates, "label");
1057
- this.inputTemplates = this.filterTemplates(this.inputTemplates, "input");
1058
- this.prefixTemplates = this.filterTemplates(this.prefixTemplates, "prefix");
1059
- this.suffixTemplates = this.filterTemplates(this.suffixTemplates, "suffix");
1060
- this.setPrefixTemplates = this.filterTemplates(this.setPrefixTemplates, "setPrefix");
1061
- this.setSuffixTemplates = this.filterTemplates(this.setSuffixTemplates, "setSuffix");
1062
- }
1063
- filterTemplates(templates, type) {
1064
- if (ObjectUtils.isObject(templates) && Object.keys(templates).length > 0)
1065
- return templates;
1066
- return this.templates.filter(t => !!t[type]).reduce((result, directive) => {
1067
- result[directive[type]] = directive.template;
1068
- return result;
1069
- }, {});
1070
- }
1071
- }
1072
- DynamicFormBaseComponent.decorators = [
1073
- { type: Directive }
1074
- ];
1075
- DynamicFormBaseComponent.ctorParameters = () => [
1076
- { type: ChangeDetectorRef },
1077
- { type: DynamicFormService }
1078
- ];
1079
- DynamicFormBaseComponent.propDecorators = {
1080
- name: [{ type: Input }],
1081
- readonly: [{ type: Input }],
1082
- updateOn: [{ type: Input }],
1083
- classes: [{ type: Input }],
1084
- parent: [{ type: Input }],
1085
- wrapperTemplate: [{ type: Input }],
1086
- fieldSetTemplate: [{ type: Input }],
1087
- controlTemplate: [{ type: Input }],
1088
- controlTemplates: [{ type: Input }],
1089
- labelTemplates: [{ type: Input }],
1090
- inputTemplates: [{ type: Input }],
1091
- prefixTemplates: [{ type: Input }],
1092
- suffixTemplates: [{ type: Input }],
1093
- setPrefixTemplates: [{ type: Input }],
1094
- setSuffixTemplates: [{ type: Input }],
1095
- onChange: [{ type: Output }],
1096
- onStatusChange: [{ type: Output }],
1097
- onInit: [{ type: Output }],
1098
- onSubmit: [{ type: Output }],
1099
- prefixTemplate: [{ type: ContentChild, args: ["prefixTemplate",] }],
1100
- suffixTemplate: [{ type: ContentChild, args: ["suffixTemplate",] }],
1101
- templates: [{ type: ContentChildren, args: [DynamicFormTemplateDirective,] }],
1102
- cWrapperTemplate: [{ type: ContentChild, args: ["wrapperTemplate",] }],
1103
- cFieldSetTemplate: [{ type: ContentChild, args: ["fieldSetTemplate",] }],
1104
- cControlTemplate: [{ type: ContentChild, args: ["controlTemplate",] }]
1105
- };
1106
-
1107
- class DynamicFormComponent extends DynamicFormBaseComponent {
1108
- constructor(cdr, forms) {
1109
- super(cdr, forms);
1110
- this.group = new DynamicFormGroup(this);
1111
- this.defaultFieldSet = {
1112
- id: "",
1113
- title: "",
1114
- classes: ""
1115
- };
1116
- }
1117
- get status() {
1118
- return this.group.state;
1119
- }
1120
- get formControls() {
1121
- return this.group.formControls;
1122
- }
1123
- // --- Lifecycle hooks
1124
- ngOnChanges(changes) {
1125
- if (!this.data)
1126
- return;
1127
- if (changes.data || changes.controls || changes.serializers || changes.formGroup) {
1128
- if (this.group.id)
1129
- return;
1130
- this.group.setup(this.data, this);
1131
- this.group.reloadControls();
1132
- }
1133
- }
1134
- // --- Custom ---
1135
- onFormSubmit() {
1136
- const root = this.root;
1137
- root.validate().then(() => root.onSubmit.emit(this), () => { });
1138
- }
1139
- // --- IDynamicForm ---
1140
- validate(showErrors = true) {
1141
- return new Promise((resolve, reject) => {
1142
- this.group.statusChanges.pipe(first(status => status == "VALID" || status == "INVALID")).subscribe(status => {
1143
- if (showErrors)
1144
- this.group.showErrors();
1145
- if (status == "VALID") {
1146
- resolve(null);
1147
- return;
1148
- }
1149
- reject(null);
1150
- });
1151
- this.group.updateValueAndValidity();
1152
- });
1153
- }
1154
- serialize(validate) {
1155
- return new Promise((resolve, reject) => {
1156
- const serialize = () => {
1157
- this.group.serialize().then(resolve);
1158
- };
1159
- if (validate) {
1160
- this.validate().then(serialize, reject);
1161
- return;
1162
- }
1163
- serialize();
1164
- });
1165
- }
1166
- check() {
1167
- return this.group.check();
1168
- }
1169
- getControl(id) {
1170
- return this.group.getControl(id);
1171
- }
1172
- }
1173
- DynamicFormComponent.decorators = [
1174
- { type: Component, args: [{
1175
- moduleId: module.id,
1176
- selector: "dynamic-form, [dynamic-form]",
1177
- template: "<ng-template #defaultFieldSetTemplate let-id=\"id\" let-controls=\"controls\" let-fieldSet=\"fieldSet\">\r\n <div [ngClass]=\"['form-fields', 'form-fields-' + id, fieldSet.classes]\">\r\n <ng-container [ngxTemplateOutlet]=\"setPrefixTemplates[fieldSet.id]\" [context]=\"fieldSet\"></ng-container>\r\n <div *ngIf=\"fieldSet.title\" [ngClass]=\"['form-title', fieldSet.titleClasses || '']\">\r\n {{ group.prefix + fieldSet.title | translate }}\r\n </div>\r\n <ng-template #subControls>\r\n <ng-container *ngFor=\"let control of controls\" [form-group]=\"control\" [visible]=\"control.visible\" [form]=\"this\">\r\n\r\n </ng-container>\r\n </ng-template>\r\n <div *ngIf=\"fieldSet.setClasses; else subControls\" [ngClass]=\"fieldSet.setClasses\">\r\n <div *ngIf=\"fieldSet.controlClasses; else subControls\" [ngClass]=\"fieldSet.controlClasses\">\r\n <ng-container [ngTemplateOutlet]=\"subControls\"></ng-container>\r\n </div>\r\n </div>\r\n <ng-container [ngxTemplateOutlet]=\"setSuffixTemplates[fieldSet.id]\" [context]=\"fieldSet\"></ng-container>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #fieldSetsTemplate>\r\n <ng-container *ngFor=\"let fs of formControls | groupBy:'data.fieldSet'\"\r\n [ngxTemplateOutlet]=\"fieldSetTemplate || defaultFieldSetTemplate\"\r\n [context]=\"{form: this, id: fs.group, controls: fs.items, fieldSet: group.formFields[fs.group] || defaultFieldSet}\">\r\n </ng-container>\r\n</ng-template>\r\n<ng-template #defaultWrapperTemplate let-form=\"form\" let-fieldSetsTemplate=\"fieldSetsTemplate\">\r\n <ng-container [ngTemplateOutlet]=\"prefixTemplate\"\r\n [ngTemplateOutletContext]=\"{form: form, fieldSetsTemplate: fieldSetsTemplate}\"></ng-container>\r\n <form class=\"dynamic-form\" [ngClass]=\"form.classes || ''\" [formGroup]=\"group\" (submit)=\"onFormSubmit()\">\r\n <ng-container [ngTemplateOutlet]=\"fieldSetsTemplate\"></ng-container>\r\n <ng-content></ng-content>\r\n <div *ngIf=\"form.status == 'PENDING'\" class=\"dynamic-form-validator\">\r\n {{ group.prefix + 'message.pending' | translate }}\r\n </div>\r\n <button [ngStyle]=\"{display: 'none'}\">Submit</button>\r\n </form>\r\n <ng-container [ngTemplateOutlet]=\"suffixTemplate\"\r\n [ngTemplateOutletContext]=\"{form: form, fieldSetsTemplate: fieldSetsTemplate}\"></ng-container>\r\n</ng-template>\r\n<ng-template #loadingTemplate>\r\n <div *ngIf=\"status == 'LOADING'\" class=\"dynamic-form-loader\">\r\n {{ group.prefix + 'message.loading' | translate }}\r\n </div>\r\n</ng-template>\r\n<ng-container [ngTemplateOutlet]=\"wrapperTemplate || defaultWrapperTemplate\"\r\n [ngTemplateOutletContext]=\"{form: this, fieldSetsTemplate: fieldSetsTemplate}\"\r\n *ngIf=\"status !== 'LOADING'; else loadingTemplate\">\r\n</ng-container>\r\n",
1178
- providers: [{ provide: DynamicFormBaseComponent, useExisting: DynamicFormComponent }]
1179
- },] }
1180
- ];
1181
- DynamicFormComponent.ctorParameters = () => [
1182
- { type: ChangeDetectorRef },
1183
- { type: DynamicFormService }
1184
- ];
1185
- DynamicFormComponent.propDecorators = {
1186
- group: [{ type: Input }],
1187
- controls: [{ type: Input }],
1188
- serializers: [{ type: Input }],
1189
- fieldSets: [{ type: Input }],
1190
- data: [{ type: Input }]
1191
- };
1192
-
1193
- const statusPriority = ["LOADING", "PENDING", "DISABLED", "INVALID"];
1194
- class DynamicFormsComponent extends DynamicFormBaseComponent {
1195
- constructor(cdr, formService) {
1196
- super(cdr, formService);
1197
- this.formPrefixTemplates = {};
1198
- this.formSuffixTemplates = {};
1199
- this.innerFormPrefixTemplates = {};
1200
- this.innerFormSuffixTemplates = {};
1201
- }
1202
- get status() {
1203
- for (let i = 0; i < statusPriority.length; i++) {
1204
- const status = statusPriority[i];
1205
- if (this.checkForms(f => f.status == status))
1206
- return status;
1207
- }
1208
- return "VALID";
1209
- }
1210
- // --- Lifecycle hooks
1211
- ngAfterContentInit() {
1212
- super.ngAfterContentInit();
1213
- this.containerTemplate = this.containerTemplate || this.cContainerTemplate;
1214
- this.formPrefixTemplates = this.filterTemplates(this.formPrefixTemplates, "formPrefix");
1215
- this.formSuffixTemplates = this.filterTemplates(this.formSuffixTemplates, "formSuffix");
1216
- this.innerFormPrefixTemplates = this.filterTemplates(this.innerFormPrefixTemplates, "innerFormPrefix");
1217
- this.innerFormSuffixTemplates = this.filterTemplates(this.innerFormSuffixTemplates, "innerFormSuffix");
1218
- }
1219
- ngOnChanges(changes) {
1220
- this.configs = this.createFormGroups(this.data);
1221
- }
1222
- // --- IDynamicFormBase ---
1223
- validate(showErrors = true) {
1224
- if (!this.forms)
1225
- return Promise.reject(null);
1226
- return Promise.all(this.forms.map(f => f.validate(showErrors)));
1227
- }
1228
- serialize(validate) {
1229
- if (!this.forms)
1230
- return validate ? Promise.reject(null) : Promise.resolve({});
1231
- return new Promise((resolve, reject) => {
1232
- const promises = this.forms.map(f => f.serialize(validate));
1233
- Promise.all(promises).then(results => {
1234
- let result = {};
1235
- results.forEach((data, ix) => {
1236
- const config = this.data[ix];
1237
- let path = null;
1238
- if (ObjectUtils.isArray(config.path) && config.path.length > 0) {
1239
- path = config.path;
1240
- }
1241
- else if (ObjectUtils.isString(config.path) && config.path.length > 0) {
1242
- path = config.path.split(".");
1243
- }
1244
- else if (ObjectUtils.isNumber(config.path)) {
1245
- path = [config.path];
1246
- }
1247
- if (!path) {
1248
- result = ObjectUtils.assign(result, data);
1249
- return;
1250
- }
1251
- result = ObjectUtils.mapToPath(result, data, path.map(p => `${p}`));
1252
- });
1253
- resolve(result);
1254
- }, reject);
1255
- });
1256
- }
1257
- check() {
1258
- if (!this.forms)
1259
- return Promise.resolve(null);
1260
- return Promise.all(this.forms.map(t => t.check()));
1261
- }
1262
- getControl(id) {
1263
- return this.getFromValue(f => f.getControl(id));
1264
- }
1265
- checkForms(check) {
1266
- this.cdr.detectChanges();
1267
- if (!this.forms)
1268
- return false;
1269
- return ObjectUtils.isDefined(this.forms.find(check));
1270
- }
1271
- getFromValue(check) {
1272
- if (!this.forms)
1273
- return null;
1274
- let value = null;
1275
- this.forms.find(f => {
1276
- value = check(f);
1277
- return ObjectUtils.isDefined(value);
1278
- });
1279
- return value;
1280
- }
1281
- createFormGroups(configs) {
1282
- return (configs || []).map((c) => {
1283
- if (c.multi)
1284
- return c;
1285
- const config = c;
1286
- const group = new DynamicFormGroup(this, {
1287
- id: config.id || UniqueUtils.uuid(),
1288
- type: "model",
1289
- data: config.controlData
1290
- });
1291
- config.group = group;
1292
- config.name = config.name || this.name;
1293
- group.setup(config.data, config);
1294
- group.reloadControls();
1295
- return config;
1296
- });
1297
- }
1298
- }
1299
- DynamicFormsComponent.decorators = [
1300
- { type: Component, args: [{
1301
- moduleId: module.id,
1302
- selector: "dynamic-forms, [dynamic-forms]",
1303
- template: "<ng-template #configTemplate let-formTemplate=\"formTemplate\" let-form=\"form\" let-config=\"config\" let-configTemplate>\r\n <div [ngClass]=\"config.classes || ''\">\r\n <ng-container [ngTemplateOutlet]=\"formPrefixTemplates[config.id]\"\r\n [ngTemplateOutletContext]=\"{config: config, form: form}\"></ng-container>\r\n <ng-template #singleFormTemplate>\r\n <div dynamic-form\r\n [hidden]=\"!config.group?.visible\"\r\n [ngClass]=\"config.formClasses || ''\"\r\n [name]=\"config.name || form.name\"\r\n [readonly]=\"form.readonly\"\r\n [updateOn]=\"form.updateOn\"\r\n [classes]=\"config.innerFormClasses\"\r\n [parent]=\"form\"\r\n\r\n [wrapperTemplate]=\"form.wrapperTemplate\"\r\n [fieldSetTemplate]=\"form.fieldSetTemplate\"\r\n [controlTemplates]=\"form.controlTemplates\"\r\n\r\n [controlTemplate]=\"form.controlTemplate\"\r\n [labelTemplates]=\"form.labelTemplates\"\r\n [inputTemplates]=\"form.inputTemplates\"\r\n [prefixTemplates]=\"form.prefixTemplates\"\r\n [suffixTemplates]=\"form.suffixTemplates\"\r\n [setPrefixTemplates]=\"form.setPrefixTemplates\"\r\n [setSuffixTemplates]=\"form.setSuffixTemplates\"\r\n\r\n [group]=\"config.group\"\r\n [fieldSets]=\"config.fieldSets\">\r\n <ng-template #prefixTemplate let-subForm=\"form\">\r\n <ng-container [ngTemplateOutlet]=\"form.innerFormPrefixTemplates[config.id]\"\r\n [ngTemplateOutletContext]=\"{config: config, form: subForm}\"></ng-container>\r\n </ng-template>\r\n <ng-template #suffixTemplate let-subForm=\"form\">\r\n <ng-container [ngTemplateOutlet]=\"form.innerFormSuffixTemplates[config.id]\"\r\n [ngTemplateOutletContext]=\"{config: config, form: subForm}\"></ng-container>\r\n </ng-template>\r\n </div>\r\n </ng-template>\r\n <div dynamic-forms\r\n [ngClass]=\"config.formClasses || ''\"\r\n [name]=\"config.name || name\"\r\n [readonly]=\"form.readonly\"\r\n [updateOn]=\"form.updateOn\"\r\n [classes]=\"config.innerFormClasses\"\r\n [parent]=\"form\"\r\n\r\n [wrapperTemplate]=\"form.wrapperTemplate\"\r\n [fieldSetTemplate]=\"form.fieldSetTemplate\"\r\n [controlTemplates]=\"form.controlTemplates\"\r\n\r\n [controlTemplate]=\"form.controlTemplate\"\r\n [labelTemplates]=\"form.labelTemplates\"\r\n [inputTemplates]=\"form.inputTemplates\"\r\n [prefixTemplates]=\"form.prefixTemplates\"\r\n [suffixTemplates]=\"form.suffixTemplates\"\r\n [setPrefixTemplates]=\"form.setPrefixTemplates\"\r\n [setSuffixTemplates]=\"form.setSuffixTemplates\"\r\n\r\n [data]=\"config.data\"\r\n [containerTemplate]=\"form.containerTemplate\"\r\n [formPrefixTemplates]=\"form.formPrefixTemplates\"\r\n [formSuffixTemplates]=\"form.formSuffixTemplates\"\r\n [innerFormPrefixTemplates]=\"form.innerFormPrefixTemplates\"\r\n [innerFormSuffixTemplates]=\"form.innerFormSuffixTemplates\"\r\n\r\n *ngIf=\"config.multi; else singleFormTemplate\">\r\n <ng-template #prefixTemplate let-subForm=\"form\">\r\n <ng-container [ngTemplateOutlet]=\"form.innerFormPrefixTemplates[config.id]\"\r\n [ngTemplateOutletContext]=\"{config: config, form: subForm}\"></ng-container>\r\n </ng-template>\r\n <ng-template #suffixTemplate let-subForm=\"form\">\r\n <ng-container [ngTemplateOutlet]=\"form.innerFormSuffixTemplates[config.id]\"\r\n [ngTemplateOutletContext]=\"{config: config, form: subForm}\"></ng-container>\r\n </ng-template>\r\n </div>\r\n <ng-container [ngTemplateOutlet]=\"formSuffixTemplates[config.id]\"\r\n [ngTemplateOutletContext]=\"{config: config, form: form}\"></ng-container>\r\n </div>\r\n</ng-template>\r\n<ng-template let-form=\"form\" let-configTemplate=\"configTemplate\" #defaultContainerTemplate>\r\n <div class=\"dynamic-forms\" [ngClass]=\"classes || ''\">\r\n <ng-container *ngFor=\"let config of form.configs\"\r\n [ngTemplateOutlet]=\"configTemplate\"\r\n [ngTemplateOutletContext]=\"{form: form, config: config}\"></ng-container>\r\n <ng-content></ng-content>\r\n </div>\r\n</ng-template>\r\n<ng-container [ngTemplateOutlet]=\"prefixTemplate\"\r\n [ngTemplateOutletContext]=\"{form: this}\"></ng-container>\r\n<ng-container [ngTemplateOutlet]=\"containerTemplate || defaultContainerTemplate\"\r\n [ngTemplateOutletContext]=\"{form: this, configTemplate: configTemplate, defaultContainerTemplate: defaultContainerTemplate}\">\r\n</ng-container>\r\n<ng-container [ngTemplateOutlet]=\"suffixTemplate\"\r\n [ngTemplateOutletContext]=\"{form: this}\"></ng-container>\r\n",
1304
- providers: [{ provide: DynamicFormBaseComponent, useExisting: DynamicFormsComponent }]
1305
- },] }
1306
- ];
1307
- DynamicFormsComponent.ctorParameters = () => [
1308
- { type: ChangeDetectorRef },
1309
- { type: DynamicFormService }
1310
- ];
1311
- DynamicFormsComponent.propDecorators = {
1312
- data: [{ type: Input }],
1313
- containerTemplate: [{ type: Input }],
1314
- formPrefixTemplates: [{ type: Input }],
1315
- formSuffixTemplates: [{ type: Input }],
1316
- innerFormPrefixTemplates: [{ type: Input }],
1317
- innerFormSuffixTemplates: [{ type: Input }],
1318
- cContainerTemplate: [{ type: ContentChild, args: ["containerTemplate",] }],
1319
- forms: [{ type: ViewChildren, args: [DynamicFormBaseComponent,] }]
1320
- };
1321
-
1322
- class DynamicFormGroupComponent {
1323
- get classes() {
1324
- if (!this.control)
1325
- return "form-group";
1326
- return ["form-group", "form-group-" + this.control.id, this.control.data.classes, this.control.errors && this.control.touched ? "form-group-invalid" : ""].join(" ");
1327
- }
1328
- }
1329
- DynamicFormGroupComponent.decorators = [
1330
- { type: Component, args: [{
1331
- moduleId: module.id,
1332
- selector: "div[dynamic-form-group]",
1333
- template: "<ng-template #labelTemplate>\r\n <label [ngClass]=\"'control-label control-label-' + control.data.labelAlign\" [attr.for]=\"control.formId\">\r\n {{ control.label | translate: control.model }}\r\n </label>\r\n</ng-template>\r\n<ng-template #errorTemplate>\r\n <div class=\"error-message\" *ngIf=\"control.errors && control.touched\">\r\n <span class=\"help-block\" *ngFor=\"let error of control.errors | entries\">\r\n {{ error.key | translate: error.value }}\r\n </span>\r\n </div>\r\n</ng-template>\r\n<ng-template #inputTemplate let-control=\"control\">\r\n <ng-container [form-control]=\"control\"></ng-container>\r\n</ng-template>\r\n<ng-template #defaultControlTemplate\r\n let-context\r\n let-control=\"control\"\r\n let-data=\"control.data\"\r\n let-labelTemplate=\"labelTemplate\"\r\n let-inputTemplate=\"inputTemplate\"\r\n let-prefixTemplate=\"prefixTemplate\"\r\n let-suffixTemplate=\"suffixTemplate\"\r\n let-errorTemplate=\"errorTemplate\">\r\n <ng-container [ngTemplateOutlet]=\"prefixTemplate\"\r\n [ngTemplateOutletContext]=\"context\"></ng-container>\r\n <ng-container *ngIf=\"control.label && data.labelAlign == 'left'\"\r\n [ngTemplateOutlet]=\"labelTemplate\"\r\n [ngTemplateOutletContext]=\"context\">\r\n </ng-container>\r\n <ng-container [ngTemplateOutlet]=\"inputTemplate\"\r\n [ngTemplateOutletContext]=\"context\"></ng-container>\r\n <ng-container *ngIf=\"control.label && data.labelAlign == 'right'\"\r\n [ngTemplateOutlet]=\"labelTemplate\"\r\n [ngTemplateOutletContext]=\"context\">\r\n </ng-container>\r\n <ng-container [ngTemplateOutlet]=\"suffixTemplate\"\r\n [ngTemplateOutletContext]=\"context\"></ng-container>\r\n <ng-container [ngTemplateOutlet]=\"errorTemplate\"\r\n [ngTemplateOutletContext]=\"context\"></ng-container>\r\n</ng-template>\r\n\r\n<ng-container [ngxTemplateOutlet]=\"form.controlTemplates[control.id] || form.controlTemplate || defaultControlTemplate\"\r\n [context]=\"{\r\n control: control,\r\n labelTemplate: form.labelTemplates[control.id] || labelTemplate,\r\n inputTemplate: form.inputTemplates[control.id] || inputTemplate,\r\n prefixTemplate: form.prefixTemplates[control.id],\r\n suffixTemplate: form.suffixTemplates[control.id],\r\n errorTemplate: errorTemplate\r\n }\">\r\n</ng-container>\r\n"
1334
- },] }
1335
- ];
1336
- DynamicFormGroupComponent.propDecorators = {
1337
- classes: [{ type: HostBinding, args: ["class",] }]
1338
- };
1339
-
1340
- class DynamicFormFileComponent extends FormControlComponent {
1341
- constructor(api, toaster) {
1342
- super();
1343
- this.api = api;
1344
- this.toaster = toaster;
1345
- this.fileImageCache = [];
1346
- }
1347
- // Acceptor for provider
1348
- static acceptor(control) {
1349
- return control.type == "file";
1350
- }
1351
- // Loader for provider
1352
- static loader() {
1353
- return Promise.resolve();
1354
- }
1355
- onSelect(input) {
1356
- this.processFiles(input.files);
1357
- input.value = "";
1358
- }
1359
- processFiles(fileList) {
1360
- const files = [];
1361
- const accept = this.data.accept;
1362
- const types = ObjectUtils.isString(accept) && accept.length > 0 ? accept.toLowerCase().split(",") : null;
1363
- if (fileList.length == 0)
1364
- return;
1365
- for (let i = 0; i < fileList.length; i++) {
1366
- const file = fileList.item(i);
1367
- const type = file.type.toLowerCase();
1368
- const ext = FileUtils.getExtension(file);
1369
- if (types && !ArrayUtils.has(types, type, ext))
1370
- continue;
1371
- files.push(file);
1372
- }
1373
- if (files.length == 0) {
1374
- this.toaster.error("message.error.wrong-files");
1375
- return;
1376
- }
1377
- this.upload(files);
1378
- }
1379
- upload(files) {
1380
- const single = !this.data.multi;
1381
- if (single)
1382
- files.length = Math.min(files.length, 1);
1383
- const promises = [];
1384
- files.forEach((file, ix) => {
1385
- if (this.data.asDataUrl) {
1386
- promises.push(FileUtils.readFileAsDataURL(file));
1387
- return;
1388
- }
1389
- if (this.data.asFile) {
1390
- promises.push(Promise.resolve(file));
1391
- return;
1392
- }
1393
- promises.push(this.api.upload(this.data.uploadUrl, this.data.createUploadData(file), console.log, this.data.uploadOptions).then(asset => asset._id || asset, () => null));
1394
- });
1395
- Promise.all(promises).then(assets => {
1396
- if (single) {
1397
- this.control.setValue(assets[0]);
1398
- return;
1399
- }
1400
- const current = this.value || [];
1401
- this.control.setValue(current.concat(assets.filter(t => !!t)));
1402
- });
1403
- }
1404
- delete(index) {
1405
- if (this.data.multi) {
1406
- const current = Array.from(this.value || []);
1407
- current.splice(index, 1);
1408
- this.control.setValue(current);
1409
- return;
1410
- }
1411
- this.control.setValue(null);
1412
- }
1413
- getUrl(image) {
1414
- return `url('${this.getImgUrl(image)}')`;
1415
- }
1416
- getImgUrl(image) {
1417
- if (ObjectUtils.isBlob(image)) {
1418
- let cache = this.fileImageCache.find(t => t.file == image);
1419
- if (!cache) {
1420
- cache = { file: image, url: URL.createObjectURL(image) };
1421
- this.fileImageCache.push(cache);
1422
- }
1423
- return cache.url;
1424
- }
1425
- const url = !image ? null : image.imageUrl || image;
1426
- if (!ObjectUtils.isString(url))
1427
- return null;
1428
- if (url.startsWith("data:"))
1429
- return url;
1430
- if (!this.data.baseUrl) {
1431
- const subUrl = url.startsWith("/") ? url.substr(1) : url;
1432
- return this.api.url(subUrl);
1433
- }
1434
- return this.api.url(`${this.data.baseUrl}${url}`);
1435
- }
1436
- }
1437
- DynamicFormFileComponent.decorators = [
1438
- { type: Component, args: [{
1439
- selector: "dynamic-form-file",
1440
- template: "<div class=\"upload\">\r\n <input type=\"file\" (change)=\"onSelect($event.target)\" [attr.accept]=\"data.accept\" multiple=\"multiple\"/>\r\n <ul class=\"images\" *ngIf=\"!data.multi\">\r\n <li class=\"image\" *ngIf=\"value\" [ngStyle]=\"{backgroundImage: getUrl(value)}\">\r\n <a class=\"btn btn-delete\" (click)=\"delete()\"></a>\r\n </li>\r\n </ul>\r\n <ul class=\"images\" *ngIf=\"data.multi\">\r\n <li class=\"image\" *ngFor=\"let image of value; let i = index\" [ngStyle]=\"{backgroundImage: getUrl(image)}\">\r\n <a class=\"btn btn-delete\" (click)=\"delete(i)\"></a>\r\n </li>\r\n </ul>\r\n</div>\r\n",
1441
- styles: [".upload{display:inline-block}.upload ul{display:inline-flex;list-style:none;margin:10px 0 0;padding:0}.upload ul li{height:100px;width:100px;background:repeating-linear-gradient(45deg,gray,gray 10px,lightgray 10px,lightgray 20px) center center;background-size:cover;border:1px gray solid;margin-right:5px;position:relative}.upload .btn-delete{background:linear-gradient(to bottom,#c8607a,#a64d5a);border-color:#a64d5a;color:#fff;position:absolute;padding:0;right:5px;top:5px;width:20px;height:20px}.upload .btn-delete:before{color:#fff;display:block;position:absolute;top:0;right:6px;content:\"x\"}\n"]
1442
- },] }
1443
- ];
1444
- DynamicFormFileComponent.ctorParameters = () => [
1445
- { type: ApiService },
1446
- { type: undefined, decorators: [{ type: Inject, args: [TOASTER_SERVICE,] }] }
1447
- ];
1448
-
1449
- class DynamicFormInputComponent extends FormControlComponent {
1450
- constructor(language) {
1451
- super();
1452
- this.language = language;
1453
- }
1454
- // Acceptor for provider
1455
- static acceptor(control) {
1456
- return control.type == "input";
1457
- }
1458
- // Loader for provider
1459
- static loader() {
1460
- return Promise.resolve();
1461
- }
1462
- get isChecked() {
1463
- return this.data.type == "checkbox" && this.value;
1464
- }
1465
- onDateChange(value) {
1466
- const date = new Date(value);
1467
- const dateValue = date.valueOf();
1468
- if (isNaN(dateValue) || dateValue < -30610224000000)
1469
- return;
1470
- this.control.setValue(date);
1471
- }
1472
- onTextChange(value) {
1473
- if (!this.data.useLanguage) {
1474
- this.control.setValue(value);
1475
- return;
1476
- }
1477
- const translations = ObjectUtils.isArray(this.value) ? Array.from(this.value) : [];
1478
- const translation = translations.find(t => t.lang == this.language.editLanguage);
1479
- if (translation) {
1480
- translation.translation = value;
1481
- }
1482
- else {
1483
- translations.push({
1484
- lang: this.language.editLanguage,
1485
- translation: value
1486
- });
1487
- }
1488
- this.control.setValue(translations);
1489
- }
1490
- onNumberBlur() {
1491
- const value = this.value;
1492
- if (ObjectUtils.isNumber(this.data.max) && this.data.max < value) {
1493
- this.control.setValue(this.data.max);
1494
- }
1495
- else if (ObjectUtils.isNumber(this.data.min) && this.data.min > value) {
1496
- this.control.setValue(this.data.min);
1497
- }
1498
- this.control.onBlur();
1499
- }
1500
- }
1501
- DynamicFormInputComponent.decorators = [
1502
- { type: Component, args: [{
1503
- moduleId: module.id,
1504
- selector: "dynamic-form-input",
1505
- template: "<ng-container [ngSwitch]=\"data.type\">\r\n <ng-container *ngSwitchCase=\"'textarea'\">\r\n <textarea class=\"form-control\"\r\n rows=\"5\"\r\n [attr.autocomplete]=\"data.autocomplete\"\r\n [id]=\"control.formId\"\r\n [name]=\"control.formId\"\r\n [ngClass]=\"{disabled: control.disabled}\"\r\n [disabled]=\"control.disabled\"\r\n [ngModel]=\"value\"\r\n (ngModelChange)=\"control.setValue($event)\"\r\n (blur)=\"control.onBlur()\"\r\n (focus)=\"control.onFocus()\">{{ data.placeholder | translate }}</textarea>\r\n </ng-container>\r\n <ng-container *ngSwitchCase=\"'date'\">\r\n <input class=\"form-control\"\r\n type=\"date\"\r\n [attr.autocomplete]=\"data.autocomplete\"\r\n [id]=\"control.formId\"\r\n [name]=\"control.formId\"\r\n [ngClass]=\"{disabled: control.disabled}\"\r\n [disabled]=\"control.disabled\"\r\n [ngModel]=\"value | date: 'y-MM-dd'\"\r\n (ngModelChange)=\"onDateChange($event)\"\r\n (blur)=\"control.onBlur()\"\r\n (focus)=\"control.onFocus()\"/>\r\n </ng-container>\r\n <ng-container *ngSwitchCase=\"'number'\">\r\n <input class=\"form-control\"\r\n type=\"number\"\r\n [attr.autocomplete]=\"data.autocomplete\"\r\n [min]=\"data.min\"\r\n [max]=\"data.max\"\r\n [step]=\"data.step\"\r\n [id]=\"control.formId\"\r\n [name]=\"control.formId\"\r\n [ngClass]=\"{disabled: control.disabled}\"\r\n [disabled]=\"control.disabled\"\r\n [ngModel]=\"value\"\r\n (ngModelChange)=\"control.setValue($event)\"\r\n (blur)=\"onNumberBlur()\"\r\n (focus)=\"control.onFocus()\"/>\r\n </ng-container>\r\n <ng-container *ngSwitchCase=\"'checkbox'\">\r\n <input class=\"form-control\"\r\n type=\"checkbox\"\r\n [id]=\"control.formId\"\r\n [name]=\"control.formId\"\r\n [ngClass]=\"{disabled: control.disabled}\"\r\n [disabled]=\"control.disabled\"\r\n [ngModel]=\"value\"\r\n (ngModelChange)=\"control.setValue($event)\"\r\n (blur)=\"control.onBlur()\"\r\n (focus)=\"control.onFocus()\"/>\r\n </ng-container>\r\n <ng-container *ngSwitchCase=\"'text'\">\r\n <input class=\"form-control\"\r\n type=\"text\"\r\n [attr.autocomplete]=\"data.autocomplete\"\r\n [minlength]=\"data.min\"\r\n [maxlength]=\"data.max\"\r\n [placeholder]=\"data.placeholder | translate\"\r\n [id]=\"control.formId\"\r\n [name]=\"control.formId\"\r\n [ngClass]=\"{disabled: control.disabled}\"\r\n [disabled]=\"control.disabled\"\r\n [ngModel]=\"data.useLanguage ? (value | translate) : value\"\r\n (ngModelChange)=\"onTextChange($event)\"\r\n (blur)=\"control.onBlur()\"\r\n (focus)=\"control.onFocus()\"/>\r\n </ng-container>\r\n <ng-container *ngSwitchDefault>\r\n <input class=\"form-control\"\r\n [attr.autocomplete]=\"data.autocomplete\"\r\n [minlength]=\"data.min\"\r\n [maxlength]=\"data.max\"\r\n [placeholder]=\"data.placeholder | translate\"\r\n [type]=\"data.type\"\r\n [id]=\"control.formId\"\r\n [name]=\"control.formId\"\r\n [ngClass]=\"{disabled: control.disabled}\"\r\n [disabled]=\"control.disabled\"\r\n [ngModel]=\"value\"\r\n (ngModelChange)=\"control.setValue($event)\"\r\n (blur)=\"control.onBlur()\"\r\n (focus)=\"control.onFocus()\"/>\r\n </ng-container>\r\n</ng-container>\r\n"
1506
- },] }
1507
- ];
1508
- DynamicFormInputComponent.ctorParameters = () => [
1509
- { type: undefined, decorators: [{ type: Inject, args: [LANGUAGE_SERVICE,] }] }
1510
- ];
1511
- DynamicFormInputComponent.propDecorators = {
1512
- isChecked: [{ type: HostBinding, args: ["class.checked",] }]
1513
- };
1514
-
1515
- class DynamicFormSelectComponent extends FormControlComponent {
1516
- // Acceptor for provider
1517
- static acceptor(control) {
1518
- return control.type == "select";
1519
- }
1520
- // Loader for provider
1521
- static loader(control) {
1522
- const data = control.getData();
1523
- if (data.type == "radio" && data.multi) {
1524
- return Promise.reject("Radio group doesn't support multi select!");
1525
- }
1526
- return new Promise(resolve => {
1527
- const getOptions = ReflectUtils.resolve(data.options, control.form.injector);
1528
- getOptions(control).then(options => {
1529
- if (data.emptyOption)
1530
- options.unshift({ id: null, label: "" });
1531
- control.meta.options = options;
1532
- DynamicFormSelectComponent.fillOptions(control, options);
1533
- resolve(options);
1534
- });
1535
- });
1536
- }
1537
- static fillOptions(control, options) {
1538
- const data = control.getData();
1539
- const selected = control.value;
1540
- if (data.multi || options.length == 0 || options.findIndex(t => t.id == selected) >= 0)
1541
- return;
1542
- control.setValue(options[0].id);
1543
- }
1544
- onSelectChange(value) {
1545
- const isArray = ObjectUtils.isArray(value);
1546
- const current = this.value;
1547
- if (this.data.multi) {
1548
- if (isArray) {
1549
- this.control.setValue(value);
1550
- return;
1551
- }
1552
- if (ObjectUtils.isArray(current)) {
1553
- this.control.setValue(current.indexOf(value) < 0
1554
- ? current.concat([value])
1555
- : current.filter(c => c !== value));
1556
- return;
1557
- }
1558
- this.control.setValue([value]);
1559
- return;
1560
- }
1561
- if (isArray)
1562
- value = value[0];
1563
- if (current == value) {
1564
- const option = this.meta.options.find(o => o.id !== value);
1565
- value = option ? option.id : null;
1566
- }
1567
- this.control.setValue(value);
1568
- }
1569
- checkValue(option) {
1570
- const value = this.value;
1571
- return ObjectUtils.isArray(value) ? value.indexOf(option.id) >= 0 : option.id == value;
1572
- }
1573
- findOption(option, index, id) {
1574
- return option.id == id;
1575
- }
1576
- }
1577
- DynamicFormSelectComponent.decorators = [
1578
- { type: Component, args: [{
1579
- moduleId: module.id,
1580
- selector: "dynamic-form-select",
1581
- template: "<ng-template #selectTemplate let-selected=\"selected\">\r\n <select class=\"form-control\"\r\n [multiple]=\"data.multi\"\r\n [id]=\"control.formId\"\r\n [name]=\"control.formId\"\r\n [ngClass]=\"{disabled: control.disabled}\"\r\n [disabled]=\"control.disabled\"\r\n [ngModel]=\"data.multi ? value : [value]\"\r\n (ngModelChange)=\"onSelectChange($event)\"\r\n (blur)=\"control.onBlur()\"\r\n (focus)=\"control.onFocus()\">\r\n <option *ngFor=\"let option of meta.options\" [value]=\"option.id\" [disabled]=\"option.selectable == false\">\r\n {{ option.label | translate }}\r\n </option>\r\n </select>\r\n <label class=\"form-control-description\" [attr.for]=\"control.formId\" *ngIf=\"!data.multi && selected?.description\">\r\n {{ selected?.description | translate }}\r\n </label>\r\n</ng-template>\r\n<ng-container [ngSwitch]=\"data.type\">\r\n <ng-container *ngSwitchCase=\"'radio'\">\r\n <ul class=\"radio-group\">\r\n <li *ngFor=\"let option of meta.options\" class=\"radio\">\r\n <label [ngClass]=\"{checked: value == option.id}\">\r\n <input type=\"radio\"\r\n [id]=\"control.formId + '-' + option.id\"\r\n [name]=\"control.formId + '-' + option.id\"\r\n [ngClass]=\"{disabled: control.disabled}\"\r\n [disabled]=\"control.disabled || option.selectable == false\"\r\n [value]=\"option.id\"\r\n [ngModel]=\"value\"\r\n (ngModelChange)=\"onSelectChange(option.id)\"\r\n (blur)=\"control.onBlur()\"\r\n (focus)=\"control.onFocus()\">\r\n {{ option.label | translate }}\r\n </label>\r\n </li>\r\n </ul>\r\n </ng-container>\r\n <ng-container *ngSwitchCase=\"'checkbox'\">\r\n <ul class=\"checkbox-group\">\r\n <li *ngFor=\"let option of meta.options\" class=\"checkbox\">\r\n <label [ngClass]=\"{checked: checkValue(option)}\">\r\n <input type=\"checkbox\"\r\n [id]=\"control.formId + '-' + option.id\"\r\n [name]=\"control.formId + '-' + option.id\"\r\n [ngClass]=\"{disabled: control.disabled}\"\r\n [disabled]=\"control.disabled || option.selectable == false\"\r\n [ngModel]=\"checkValue(option)\"\r\n (ngModelChange)=\"onSelectChange(option.id)\"\r\n (blur)=\"control.onBlur()\"\r\n (focus)=\"control.onFocus()\">\r\n {{ option.label | translate }}\r\n </label>\r\n </li>\r\n </ul>\r\n </ng-container>\r\n <ng-container *ngSwitchDefault [ngTemplateOutlet]=\"selectTemplate\" [ngTemplateOutletContext]=\"{selected: meta?.options | find:findOption:value}\">\r\n\r\n </ng-container>\r\n</ng-container>\r\n"
1582
- },] }
1583
- ];
1584
-
1585
- class DynamicFormStaticComponent extends FormControlComponent {
1586
- // Acceptor for provider
1587
- static acceptor(control) {
1588
- return control.type == "static";
1589
- }
1590
- // Loader for provider
1591
- static loader() {
1592
- return Promise.resolve();
1593
- }
1594
- }
1595
- DynamicFormStaticComponent.decorators = [
1596
- { type: Component, args: [{
1597
- moduleId: module.id,
1598
- selector: "dynamic-form-static",
1599
- template: "<unordered-list [listStyle]=\"data.style\" [ngClass]=\"{disabled: control.disabled}\"\r\n [data]=\"!data.properties ? {value: value} : data.properties | remap: value\">\r\n <ng-template [type]=\"!data.properties ? 'key' : null\" selector=\"level == 0\" let-item=\"item\"></ng-template>\r\n <ng-template type=\"value\" selector=\"valueType == 'date'\" let-item=\"item\">\r\n {{ item.value | date }}\r\n </ng-template>\r\n</unordered-list>\r\n"
1600
- },] }
1601
- ];
1602
-
1603
- class DynamicFormModelComponent extends FormControlComponent {
1604
- // Acceptor for provider
1605
- static acceptor(control) {
1606
- return control.type == "model";
1607
- }
1608
- // Loader for provider
1609
- static loader() {
1610
- return Promise.resolve();
1611
- }
1612
- }
1613
- DynamicFormModelComponent.decorators = [
1614
- { type: Component, args: [{
1615
- moduleId: module.id,
1616
- selector: "dynamic-form-model",
1617
- template: "<dynamic-form [name]=\"data.name || form.name\"\r\n [group]=\"control\"\r\n [data]=\"value\"\r\n [updateOn]=\"control.updateOn\"\r\n [parent]=\"form\"\r\n\r\n [fieldSetTemplate]=\"form.fieldSetTemplate\"\r\n [controlTemplates]=\"form.controlTemplates\"\r\n\r\n [controlTemplate]=\"form.controlTemplate\"\r\n [labelTemplates]=\"form.labelTemplates\"\r\n [inputTemplates]=\"form.inputTemplates\"\r\n [prefixTemplates]=\"form.prefixTemplates\"\r\n [suffixTemplates]=\"form.suffixTemplates\"\r\n [setPrefixTemplates]=\"form.setPrefixTemplates\"\r\n [setSuffixTemplates]=\"form.setSuffixTemplates\"\r\n\r\n #subForm>\r\n <ng-template #wrapperTemplate let-form=\"form\" let-fieldSetsTemplate=\"fieldSetsTemplate\">\r\n <ng-container [ngTemplateOutlet]=\"fieldSetsTemplate\"></ng-container>\r\n </ng-template>\r\n</dynamic-form>\r\n"
1618
- },] }
1619
- ];
1620
- DynamicFormModelComponent.propDecorators = {
1621
- subForm: [{ type: ViewChild, args: ["subForm",] }]
1622
- };
1623
-
1624
- class DynamicFormGroupDirective {
1625
- constructor(vcr, forms) {
1626
- this.vcr = vcr;
1627
- this.forms = forms;
1628
- }
1629
- get component() {
1630
- return this.comp;
1631
- }
1632
- ngOnChanges(changes) {
1633
- if (changes.control || changes.form || changes.visible) {
1634
- if (!this.visible) {
1635
- this.vcr.clear();
1636
- this.comp = null;
1637
- return;
1638
- }
1639
- this.comp = this.forms.createGroup(this.vcr);
1640
- }
1641
- if (!this.comp)
1642
- return;
1643
- this.comp.form = this.form;
1644
- this.comp.control = this.control;
1645
- }
1646
- }
1647
- DynamicFormGroupDirective.decorators = [
1648
- { type: Directive, args: [{
1649
- selector: "[form-group]",
1650
- },] }
1651
- ];
1652
- DynamicFormGroupDirective.ctorParameters = () => [
1653
- { type: ViewContainerRef },
1654
- { type: DynamicFormService }
1655
- ];
1656
- DynamicFormGroupDirective.propDecorators = {
1657
- control: [{ type: Input, args: ["form-group",] }],
1658
- form: [{ type: Input }],
1659
- visible: [{ type: Input }]
1660
- };
1661
-
1662
- // --- Components ---
1663
- const components = [
1664
- DynamicFormsComponent,
1665
- DynamicFormComponent,
1666
- DynamicFormGroupComponent,
1667
- DynamicFormFileComponent,
1668
- DynamicFormInputComponent,
1669
- DynamicFormSelectComponent,
1670
- DynamicFormStaticComponent,
1671
- DynamicFormModelComponent
1672
- ];
1673
- // --- Directives ---
1674
- const directives = [
1675
- AsyncSubmitDirective,
1676
- DynamicFormControlDirective,
1677
- DynamicFormGroupDirective,
1678
- DynamicFormTemplateDirective
1679
- ];
1680
- // --- Pipes ---
1681
- const pipes = [];
1682
- class NgxDynamicFormModule {
1683
- static forRoot(controlProviders, groupProvider) {
1684
- return {
1685
- ngModule: NgxDynamicFormModule,
1686
- providers: [
1687
- DynamicFormService,
1688
- OpenApiService,
1689
- provideFormControl(DynamicFormFileComponent, DynamicFormFileComponent.acceptor, DynamicFormFileComponent.loader),
1690
- provideFormControl(DynamicFormInputComponent, DynamicFormInputComponent.acceptor, DynamicFormInputComponent.loader),
1691
- provideFormControl(DynamicFormSelectComponent, DynamicFormSelectComponent.acceptor, DynamicFormSelectComponent.loader),
1692
- provideFormControl(DynamicFormStaticComponent, DynamicFormStaticComponent.acceptor, DynamicFormStaticComponent.loader),
1693
- provideFormControl(DynamicFormModelComponent, DynamicFormModelComponent.acceptor, DynamicFormModelComponent.loader),
1694
- ...(controlProviders || []),
1695
- groupProvider || provideFormGroup(DynamicFormGroupComponent)
1696
- ]
1697
- };
1698
- }
1699
- }
1700
- NgxDynamicFormModule.decorators = [
1701
- { type: NgModule, args: [{
1702
- declarations: [
1703
- ...components,
1704
- ...directives,
1705
- ...pipes
1706
- ],
1707
- imports: [
1708
- CommonModule,
1709
- FormsModule,
1710
- ReactiveFormsModule,
1711
- NgxUtilsModule
1712
- ],
1713
- exports: [
1714
- ...components,
1715
- ...directives,
1716
- ...pipes,
1717
- FormsModule,
1718
- ReactiveFormsModule,
1719
- NgxUtilsModule
1720
- ],
1721
- entryComponents: components,
1722
- providers: pipes
1723
- },] }
1724
- ];
1725
-
1726
- /**
1727
- * Generated bundle index. Do not edit.
1728
- */
1729
-
1730
- export { AsyncSubmitDirective, DynamicFormBaseComponent, DynamicFormComponent, DynamicFormControl, DynamicFormControlDirective, DynamicFormFileComponent, DynamicFormGroup, DynamicFormGroupComponent, DynamicFormInputComponent, DynamicFormModelComponent, DynamicFormSelectComponent, DynamicFormService, DynamicFormStaticComponent, DynamicFormTemplateDirective, DynamicFormsComponent, FORM_CONTROL_PROVIDER, FormControlComponent, FormFieldSet, FormFile, FormInput, FormModel, FormSelect, FormSerializable, FormStatic, FormUtilities, NgxDynamicFormModule, OpenApiService, createFormControl, createFormInput, createFormModel, createFormSelect, createFormStatic, defaultSerializer, defineFormControl, getFormControl, getFormFieldSets, getFormSerializer, provideFormControl, provideFormGroup, FORM_GROUP_TYPE as ɵa, components as ɵb, directives as ɵc, pipes as ɵd, DynamicFormGroupDirective as ɵe };
1731
- //# sourceMappingURL=stemy-ngx-dynamic-form.js.map