@stemy/ngx-dynamic-form 13.1.2 → 13.1.6

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 (27) hide show
  1. package/esm2020/ngx-dynamic-form/common-types.mjs +1 -1
  2. package/esm2020/ngx-dynamic-form/components/base/dynamic-base-form-array.component.mjs +28 -12
  3. package/esm2020/ngx-dynamic-form/components/base/dynamic-base-form-control-container.component.mjs +37 -18
  4. package/esm2020/ngx-dynamic-form/components/base/dynamic-base-form-control.component.mjs +5 -4
  5. package/esm2020/ngx-dynamic-form/components/base/dynamic-base-form.component.mjs +21 -11
  6. package/esm2020/ngx-dynamic-form/components/base/dynamic-base-select.component.mjs +8 -5
  7. package/esm2020/ngx-dynamic-form/services/dynamic-form.service.mjs +97 -67
  8. package/esm2020/ngx-dynamic-form/utils/dynamic-form-array.model.mjs +114 -5
  9. package/esm2020/ngx-dynamic-form/utils/form-select-subject.mjs +10 -7
  10. package/esm2020/ngx-dynamic-form/utils/misc.mjs +5 -4
  11. package/esm2020/public_api.mjs +4 -4
  12. package/fesm2015/stemy-ngx-dynamic-form.mjs +402 -212
  13. package/fesm2015/stemy-ngx-dynamic-form.mjs.map +1 -1
  14. package/fesm2020/stemy-ngx-dynamic-form.mjs +394 -206
  15. package/fesm2020/stemy-ngx-dynamic-form.mjs.map +1 -1
  16. package/ngx-dynamic-form/common-types.d.ts +3 -33
  17. package/ngx-dynamic-form/components/base/dynamic-base-form-array.component.d.ts +18 -10
  18. package/ngx-dynamic-form/components/base/dynamic-base-form-control-container.component.d.ts +10 -12
  19. package/ngx-dynamic-form/components/base/dynamic-base-form-control.component.d.ts +3 -2
  20. package/ngx-dynamic-form/components/base/dynamic-base-form.component.d.ts +3 -1
  21. package/ngx-dynamic-form/components/base/dynamic-base-select.component.d.ts +1 -0
  22. package/ngx-dynamic-form/ngx-dynamic-form.imports.d.ts +1 -1
  23. package/ngx-dynamic-form/services/dynamic-form.service.d.ts +11 -10
  24. package/ngx-dynamic-form/utils/dynamic-form-array.model.d.ts +47 -4
  25. package/ngx-dynamic-form/utils/misc.d.ts +3 -2
  26. package/package.json +1 -1
  27. package/public_api.d.ts +4 -4
@@ -1,11 +1,11 @@
1
1
  import * as i2 from '@stemy/ngx-utils';
2
- import { ReflectUtils, ObjectUtils, StringUtils, OpenApiService, TOASTER_SERVICE, ObservableUtils, EventsService, NgxUtilsModule } from '@stemy/ngx-utils';
2
+ import { ReflectUtils, ObjectUtils, TimerUtils, StringUtils, OpenApiService, TOASTER_SERVICE, ObservableUtils, EventsService, NgxUtilsModule } from '@stemy/ngx-utils';
3
+ import { BehaviorSubject, of, isObservable, map, Subject, firstValueFrom, Subscription, debounceTime, groupBy, mergeMap } from 'rxjs';
3
4
  import * as i1 from '@ng-dynamic-forms/core';
4
- import { DynamicFormArrayModel as DynamicFormArrayModel$1, DynamicFormOption as DynamicFormOption$1, DynamicSelectModel as DynamicSelectModel$1, DynamicFormService as DynamicFormService$1, DynamicFormGroupModel, DynamicInputModel, DynamicFileUploadModel, DynamicCheckboxModel, DynamicTextAreaModel, DynamicFormComponent, DynamicTemplateDirective, DynamicFormArrayComponent, DynamicFormValueControlModel, DynamicFormControlContainerComponent, DynamicFormControlComponent, DYNAMIC_FORM_CONTROL_TYPE_ARRAY, DynamicFormGroupComponent, DYNAMIC_FORM_CONTROL_MAP_FN, DYNAMIC_VALIDATORS } from '@ng-dynamic-forms/core';
5
- export { DYNAMIC_FORM_CONTROL_TYPE_ARRAY, DYNAMIC_FORM_CONTROL_TYPE_CHECKBOX, DYNAMIC_FORM_CONTROL_TYPE_CHECKBOX_GROUP, 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, DynamicFileUploadModel, DynamicFormGroupModel, DynamicFormsCoreModule, DynamicInputModel, DynamicListDirective, DynamicRadioGroupModel, DynamicTemplateDirective, DynamicTextAreaModel } from '@ng-dynamic-forms/core';
6
- import { of, isObservable, map, Subject, Subscription, BehaviorSubject } from 'rxjs';
5
+ import { DynamicFormArrayGroupModel as DynamicFormArrayGroupModel$1, DynamicFormArrayModel as DynamicFormArrayModel$1, DynamicFormOption as DynamicFormOption$1, DynamicSelectModel as DynamicSelectModel$1, DynamicFormService as DynamicFormService$1, DynamicFormGroupModel, DynamicInputModel, DynamicFileUploadModel, DynamicCheckboxModel, DynamicEditorModel, DynamicTextAreaModel, DynamicFormComponent, DynamicTemplateDirective, DynamicFormControlContainerComponent, DYNAMIC_FORM_CONTROL_TYPE_ARRAY, DynamicFormArrayComponent, DynamicFormValueControlModel, DynamicFormControlComponent, DynamicFormGroupComponent, DYNAMIC_FORM_CONTROL_MAP_FN, DYNAMIC_VALIDATORS } from '@ng-dynamic-forms/core';
6
+ export { DYNAMIC_FORM_CONTROL_TYPE_ARRAY, DYNAMIC_FORM_CONTROL_TYPE_CHECKBOX, DYNAMIC_FORM_CONTROL_TYPE_CHECKBOX_GROUP, 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, DynamicEditorModel, DynamicFileUploadModel, DynamicFormGroupModel, DynamicFormsCoreModule, DynamicInputModel, DynamicListDirective, DynamicRadioGroupModel, DynamicTemplateDirective, DynamicTextAreaModel } from '@ng-dynamic-forms/core';
7
7
  import * as i0 from '@angular/core';
8
- import { EventEmitter, Injector, Injectable, Inject, Directive, Input, Output, HostBinding, HostListener, QueryList, Component, ChangeDetectionStrategy, ContentChildren, ViewChildren, ViewChild, forwardRef, ViewContainerRef, NgModule } from '@angular/core';
8
+ import { Injector, Injectable, Inject, EventEmitter, Directive, Input, Output, HostBinding, HostListener, QueryList, Component, ChangeDetectionStrategy, ContentChildren, ViewChildren, ViewChild, ViewContainerRef, forwardRef, NgModule } from '@angular/core';
9
9
  import { FormGroup, FormArray, NgForm, FormsModule, ReactiveFormsModule, NG_VALIDATORS } from '@angular/forms';
10
10
  import { first } from 'rxjs/operators';
11
11
  import { CommonModule } from '@angular/common';
@@ -116,7 +116,7 @@ function findRefs(property) {
116
116
  return refs.map(t => t.split("/").pop());
117
117
  }
118
118
  function replaceSpecialChars(str, to = "-") {
119
- return (str || "").replace(/[&\/\\#, +()$~%.@'":*?<>{}]/g, to);
119
+ return `${str}`.replace(/[&\/\\#, +()$~%.@'":*?<>{}]/g, to);
120
120
  }
121
121
  function mergeFormModels(formModels) {
122
122
  const res = [];
@@ -146,8 +146,9 @@ function collectPathAble(start, getter) {
146
146
  }
147
147
  return parts;
148
148
  }
149
- const MIN_INPUT_NUM = -99999999999999;
150
- const MAX_INPUT_NUM = 99999999999999;
149
+ const MIN_INPUT_NUM = -999999999;
150
+ const MAX_INPUT_NUM = 999999999;
151
+ const EDITOR_FORMATS = ["php", "json", "html", "css", "scss"];
151
152
 
152
153
  function validateJSON(control) {
153
154
  const value = control.value;
@@ -205,12 +206,31 @@ function validateItemsMaxValue(max) {
205
206
  };
206
207
  }
207
208
 
209
+ class DynamicFormArrayGroupModel extends DynamicFormArrayGroupModel$1 {
210
+ constructor(context, group, index = -1) {
211
+ super(context, group, index);
212
+ this.context = context;
213
+ this.isHidden = false;
214
+ }
215
+ get hidden() {
216
+ return this.isHidden;
217
+ }
218
+ set hidden(value) {
219
+ if (this.isHidden == value)
220
+ return;
221
+ this.isHidden = value || false;
222
+ this.context?.filterGroups();
223
+ }
224
+ }
208
225
  class DynamicFormArrayModel extends DynamicFormArrayModel$1 {
209
226
  constructor(config, layout) {
210
227
  super(config, layout);
228
+ this.config = config;
229
+ this.filteredGroups = new BehaviorSubject([]);
230
+ this.sortable = config.sortable || false;
211
231
  this.useTabs = config.useTabs || false;
212
- this.saveTab = ObjectUtils.isFunction(config.saveTab) ? config.saveTab : ((index, model) => {
213
- model.tabIndex = index;
232
+ this.saveTab = ObjectUtils.isFunction(config.saveTab) ? config.saveTab : ((index, model, arrayModel) => {
233
+ arrayModel.tabIndex = index;
214
234
  });
215
235
  this.restoreTab = ObjectUtils.isFunction(config.restoreTab) ? config.restoreTab : ((model) => {
216
236
  return model.tabIndex;
@@ -219,6 +239,95 @@ class DynamicFormArrayModel extends DynamicFormArrayModel$1 {
219
239
  return `${index + 1}`;
220
240
  });
221
241
  this.additional = config.additional || {};
242
+ this.tabIndex = 0;
243
+ this._sortBy = null;
244
+ this._sortDescending = false;
245
+ this._formArray = null;
246
+ }
247
+ get addItem() {
248
+ return this.config.addItem !== false;
249
+ }
250
+ get insertItem() {
251
+ return !this._sortBy && this.config.insertItem !== false;
252
+ }
253
+ get cloneItem() {
254
+ return this.config.cloneItem !== false;
255
+ }
256
+ get moveItem() {
257
+ return !this._sortBy && this.config.moveItem !== false;
258
+ }
259
+ get removeItem() {
260
+ return this.config.removeItem !== false;
261
+ }
262
+ get clearItems() {
263
+ return this.config.clearItems !== false;
264
+ }
265
+ get sortBy() {
266
+ return this._sortBy;
267
+ }
268
+ set sortBy(value) {
269
+ if (!this.sortable)
270
+ return;
271
+ value = value || null;
272
+ if (this._sortBy !== value) {
273
+ this._sortBy = value;
274
+ this._sortDescending = false;
275
+ }
276
+ else if (this._sortDescending) {
277
+ this._sortBy = null;
278
+ this._sortDescending = false;
279
+ }
280
+ else {
281
+ this._sortDescending = true;
282
+ }
283
+ this.filterGroups();
284
+ }
285
+ get sortDescending() {
286
+ return this._sortDescending;
287
+ }
288
+ get sortOrder() {
289
+ return this.sortDescending ? "desc" : "asc";
290
+ }
291
+ initialize(array) {
292
+ this._formArray = array || this._formArray;
293
+ this.filterGroups();
294
+ }
295
+ filterGroups() {
296
+ this._filterTimer = this._filterTimer || TimerUtils.createTimeout();
297
+ this._filterTimer.set(() => {
298
+ const filtered = this.groups.filter(g => !g.hidden);
299
+ if (this._sortBy && this._formArray) {
300
+ const compare = this._sortDescending
301
+ ? (a, b) => this.compareModels(b, a)
302
+ : (a, b) => this.compareModels(a, b);
303
+ filtered.sort(compare);
304
+ }
305
+ this._filteredGroups = filtered;
306
+ this.filteredGroups.next(filtered);
307
+ }, 100);
308
+ }
309
+ getFiltered(index) {
310
+ return !this._filteredGroups ? null : this._filteredGroups[index];
311
+ }
312
+ insertGroup(index) {
313
+ const group = new DynamicFormArrayGroupModel(this, this.groupFactory());
314
+ this.groups.splice(index, 0, group);
315
+ this.groups.forEach((g, index) => g.index = index);
316
+ this.filterGroups();
317
+ return group;
318
+ }
319
+ moveGroup(index, step) {
320
+ super.moveGroup(index, step);
321
+ this.filterGroups();
322
+ }
323
+ removeGroup(index) {
324
+ super.removeGroup(index);
325
+ this.filterGroups();
326
+ }
327
+ compareModels(a, b) {
328
+ const aGroup = this._formArray.at(a.index).get(this._sortBy)?.value || null;
329
+ const bGroup = this._formArray.at(b.index).get(this._sortBy)?.value || null;
330
+ return ObjectUtils.compare(aGroup, bGroup);
222
331
  }
223
332
  }
224
333
 
@@ -307,21 +416,24 @@ class FormSubject extends Subject {
307
416
  class FormSelectSubject extends FormSubject {
308
417
  handleNotifiedValue(controlModel, control, val) {
309
418
  val.then(options => {
310
- this.next(options);
311
- if (options.length == 0)
419
+ if (options.length == 0) {
420
+ this.next(options);
312
421
  return;
422
+ }
313
423
  const currentVal = control.value;
314
424
  if (controlModel.multiple) {
315
425
  const correctVal = (currentVal || []).filter(t => options.findIndex(o => o.value == t) >= 0);
316
426
  if (correctVal.length !== currentVal?.length) {
317
427
  control.setValue(correctVal, { onlySelf: true, emitEvent: false });
318
428
  }
319
- return;
320
429
  }
321
- const option = options.find(t => t.value == currentVal);
322
- if (!option) {
323
- control.setValue(options[0]?.value ?? null, { onlySelf: true, emitEvent: false });
430
+ else {
431
+ const option = options.find(t => t.value == currentVal);
432
+ if (!option) {
433
+ control.setValue(options[0]?.value ?? null, { onlySelf: true, emitEvent: false });
434
+ }
324
435
  }
436
+ this.next(options);
325
437
  });
326
438
  }
327
439
  }
@@ -331,7 +443,6 @@ class DynamicFormService extends DynamicFormService$1 {
331
443
  super(cs, vs);
332
444
  this.openApi = openApi;
333
445
  this.injector = injector;
334
- this.onDetectChanges = new EventEmitter();
335
446
  }
336
447
  get api() {
337
448
  return this.openApi.api;
@@ -341,43 +452,24 @@ class DynamicFormService extends DynamicFormService$1 {
341
452
  }
342
453
  patchGroup(value, formModel, formGroup) {
343
454
  this.patchValueRecursive(value, formModel, formGroup);
344
- this.detectChanges();
345
455
  formGroup.patchValue(ObjectUtils.copy(value));
456
+ this.detectChanges();
346
457
  }
347
458
  patchForm(value, component) {
348
459
  this.patchValueRecursive(value, component.model, component.group);
349
- this.detectChanges(component);
350
460
  component.group.patchValue(value);
461
+ this.detectChanges(component);
351
462
  }
352
463
  serialize(formModel, formGroup) {
353
464
  return this.serializeRecursive(formModel, formGroup);
354
465
  }
355
- notifyChanges(formModel, formGroup, root) {
356
- this.notifyChangesRecursive(formModel, formGroup, root);
357
- }
358
- updateSelectOptions(formControlModel, formControl, root) {
359
- if (formControlModel instanceof DynamicSelectModel) {
360
- let options = formControlModel.options$;
361
- if (options instanceof FormSubject) {
362
- options.notify(formControlModel, formControl, root);
363
- return;
364
- }
365
- while (options instanceof Subject && options.source) {
366
- options = options.source;
367
- if (options instanceof FormSubject) {
368
- options.notify(formControlModel, formControl, root);
369
- }
370
- }
371
- }
466
+ notifyChanges(formModel, formGroup) {
467
+ this.notifyChangesRecursive(formModel, formGroup, formModel);
372
468
  }
373
469
  showErrors(form) {
374
470
  this.showErrorsForGroup(form.group);
375
471
  this.detectChanges(form);
376
472
  }
377
- detectChanges(formComponent) {
378
- super.detectChanges(formComponent);
379
- this.onDetectChanges.emit(formComponent);
380
- }
381
473
  patchValueRecursive(value, formModel, formGroup) {
382
474
  Object.keys(value).forEach(key => {
383
475
  const subModel = this.findModelById(key, formModel);
@@ -389,7 +481,7 @@ class DynamicFormService extends DynamicFormService$1 {
389
481
  value[key] = subValue.id || subValue._id || subValue;
390
482
  return;
391
483
  }
392
- if (subModel instanceof DynamicFormArrayModel$1) {
484
+ if (subModel instanceof DynamicFormArrayModel) {
393
485
  const length = Array.isArray(subValue) ? subValue.length : 0;
394
486
  const subArray = subControl;
395
487
  while (subModel.size > length) {
@@ -421,7 +513,7 @@ class DynamicFormService extends DynamicFormService$1 {
421
513
  result[subModel.id] = await serializer(subModel, subControl);
422
514
  continue;
423
515
  }
424
- if (subModel instanceof DynamicFormArrayModel$1) {
516
+ if (subModel instanceof DynamicFormArrayModel) {
425
517
  const length = Array.isArray(subControl.value) ? subControl.value.length : 0;
426
518
  const subArray = subControl;
427
519
  const resArray = [];
@@ -452,7 +544,7 @@ class DynamicFormService extends DynamicFormService$1 {
452
544
  for (const i in formModel) {
453
545
  const subModel = formModel[i];
454
546
  const subControl = this.findControlByModel(subModel, formGroup);
455
- if (subModel instanceof DynamicFormArrayModel$1) {
547
+ if (subModel instanceof DynamicFormArrayModel) {
456
548
  const length = Array.isArray(subControl.value) ? subControl.value.length : 0;
457
549
  const subArray = subControl;
458
550
  for (let i = 0; i < length; i++) {
@@ -468,6 +560,21 @@ class DynamicFormService extends DynamicFormService$1 {
468
560
  this.updateSelectOptions(subModel, subControl, root);
469
561
  }
470
562
  }
563
+ updateSelectOptions(formControlModel, formControl, root) {
564
+ if (formControlModel instanceof DynamicSelectModel) {
565
+ let options = formControlModel.options$;
566
+ if (options instanceof FormSubject) {
567
+ options.notify(formControlModel, formControl, root);
568
+ return;
569
+ }
570
+ while (options instanceof Subject && options.source) {
571
+ options = options.source;
572
+ if (options instanceof FormSubject) {
573
+ options.notify(formControlModel, formControl, root);
574
+ }
575
+ }
576
+ }
577
+ }
471
578
  showErrorsForGroup(formGroup) {
472
579
  if (!formGroup)
473
580
  return;
@@ -510,6 +617,11 @@ class DynamicFormService extends DynamicFormService$1 {
510
617
  }
511
618
  return controls.filter(t => null !== t);
512
619
  }
620
+ checkIsEditorProperty(property) {
621
+ if (!property.format)
622
+ return false;
623
+ return EDITOR_FORMATS.indexOf(property.format) >= 0 || property.format.endsWith("script");
624
+ }
513
625
  getFormControlModels(property, schema, customizeModels) {
514
626
  const $enum = property.items?.enum || property.enum;
515
627
  if (Array.isArray($enum) || isStringWithVal(property.optionsPath) || isStringWithVal(property.endpoint)) {
@@ -519,9 +631,14 @@ class DynamicFormService extends DynamicFormService$1 {
519
631
  case "string":
520
632
  case "number":
521
633
  case "integer":
522
- return customizeModels(property, schema, DynamicInputModel, this.getFormInputConfig(property, schema));
523
634
  case "textarea":
524
- return customizeModels(property, schema, DynamicTextAreaModel, this.getFormTextareaConfig(property, schema));
635
+ if (this.checkIsEditorProperty(property)) {
636
+ return customizeModels(property, schema, DynamicEditorModel, this.getFormEditorConfig(property, schema));
637
+ }
638
+ if (property.format == "textarea") {
639
+ return customizeModels(property, schema, DynamicTextAreaModel, this.getFormTextareaConfig(property, schema));
640
+ }
641
+ return customizeModels(property, schema, DynamicInputModel, this.getFormInputConfig(property, schema));
525
642
  case "boolean":
526
643
  return customizeModels(property, schema, DynamicCheckboxModel, this.getFormCheckboxConfig(property, schema));
527
644
  case "array":
@@ -534,7 +651,7 @@ class DynamicFormService extends DynamicFormService$1 {
534
651
  case "file":
535
652
  return customizeModels(property, schema, DynamicFileUploadModel, this.getFormUploadConfig(property, schema));
536
653
  }
537
- if (property.$ref) {
654
+ if (findRefs(property).length > 0) {
538
655
  return customizeModels(property, schema, DynamicFormGroupModel, this.getFormGroupConfig(property, schema, customizeModels));
539
656
  }
540
657
  return [];
@@ -546,7 +663,7 @@ class DynamicFormService extends DynamicFormService$1 {
546
663
  if (Array.isArray(parent)) {
547
664
  return this.findModelByPath(parent.find(t => t.id == next), path);
548
665
  }
549
- if (parent instanceof DynamicFormGroupModel) {
666
+ if (parent instanceof DynamicFormGroupModel || parent instanceof DynamicFormArrayGroupModel) {
550
667
  return this.findModelByPath(parent.group.find(t => t.id == next), path);
551
668
  }
552
669
  if (parent instanceof DynamicFormArrayModel) {
@@ -574,7 +691,14 @@ class DynamicFormService extends DynamicFormService$1 {
574
691
  const subSchemas = findRefs(property).map(ref => this.schemas[ref]);
575
692
  return Object.assign(this.getFormControlConfig(property, schema), {
576
693
  groupFactory: () => mergeFormModels(subSchemas.map(s => this.getFormModelForSchemaDef(s, customizeModels))),
577
- useTabs: property.useTabs || false
694
+ sortable: property.sortable || false,
695
+ useTabs: property.useTabs || false,
696
+ addItem: property.addItem !== false,
697
+ insertItem: property.insertItem !== false,
698
+ cloneItem: property.cloneItem !== false,
699
+ moveItem: property.moveItem !== false,
700
+ removeItem: property.removeItem !== false,
701
+ clearItems: property.clearItems !== false
578
702
  });
579
703
  }
580
704
  getFormGroupConfig(property, schema, customizeModels) {
@@ -607,7 +731,22 @@ class DynamicFormService extends DynamicFormService$1 {
607
731
  step: isNaN(sub.step) ? (isNaN(property.step) ? 1 : property.step) : sub.step,
608
732
  min: isNaN(sub.minimum) ? MIN_INPUT_NUM : sub.minimum,
609
733
  max: isNaN(sub.maximum) ? MAX_INPUT_NUM : sub.maximum,
610
- minLength: isNaN(sub.minLength) ? MIN_INPUT_NUM : sub.minLength,
734
+ minLength: isNaN(sub.minLength) ? 0 : sub.minLength,
735
+ maxLength: isNaN(sub.maxLength) ? MAX_INPUT_NUM : sub.maxLength,
736
+ placeholder: property.placeholder || ""
737
+ });
738
+ }
739
+ getFormEditorConfig(property, schema) {
740
+ const sub = property.type == "array" ? property.items || property : property;
741
+ return Object.assign(this.getFormControlConfig(property, schema), {
742
+ inputType: property.format,
743
+ autoComplete: property.autoComplete || "off",
744
+ multiple: property.type == "array",
745
+ accept: ObjectUtils.isString(property.accept) ? property.accept : null,
746
+ mask: ObjectUtils.isString(property.mask) ? property.mask : null,
747
+ pattern: ObjectUtils.isString(property.pattern) ? property.pattern : null,
748
+ step: isNaN(sub.step) ? (isNaN(property.step) ? 1 : property.step) : sub.step,
749
+ minLength: isNaN(sub.minLength) ? 0 : sub.minLength,
611
750
  maxLength: isNaN(sub.maxLength) ? MAX_INPUT_NUM : sub.maxLength,
612
751
  placeholder: property.placeholder || ""
613
752
  });
@@ -621,32 +760,6 @@ class DynamicFormService extends DynamicFormService$1 {
621
760
  multiple: property.type == "array"
622
761
  });
623
762
  }
624
- getFormSelectConfig(property, schema) {
625
- return Object.assign(this.getFormControlConfig(property, schema), {
626
- options: this.getFormSelectOptions(property, schema),
627
- multiple: property.type == "array",
628
- groupBy: property.groupBy,
629
- inline: property.inline
630
- });
631
- }
632
- getFormCheckboxConfig(property, schema) {
633
- return Object.assign(this.getFormControlConfig(property, schema), {
634
- indeterminate: property.indeterminate === true
635
- });
636
- }
637
- cloneFormArrayGroup(index, formArray, formArrayModel) {
638
- this.insertFormArrayGroup(index, formArray, formArrayModel);
639
- this.patchGroup(formArray.at(index + 1).value, formArrayModel.groups[index].group, formArray.at(index));
640
- }
641
- async fixSelectOptions(model, control, options) {
642
- if (!options)
643
- return [];
644
- for (const option of options) {
645
- option.classes = [option.classes, model.getClasses(option, model, control, this.injector)].filter(isStringWithVal).join(" ");
646
- option.label = await this.language.getTranslation(option.label);
647
- }
648
- return options;
649
- }
650
763
  getFormSelectOptions(property, schema) {
651
764
  const $enum = property.items?.enum || property.enum;
652
765
  if (Array.isArray($enum)) {
@@ -659,7 +772,7 @@ class DynamicFormService extends DynamicFormService$1 {
659
772
  });
660
773
  }
661
774
  if (isStringWithVal(property.optionsPath)) {
662
- return new FormSelectSubject((selectModel, control, root, indexes) => {
775
+ return new FormSelectSubject(async (selectModel, control, root, indexes) => {
663
776
  let path = property.optionsPath;
664
777
  let target = control;
665
778
  let model = selectModel;
@@ -681,7 +794,9 @@ class DynamicFormService extends DynamicFormService$1 {
681
794
  path = path.replace(key, indexes[key]);
682
795
  });
683
796
  model = this.findModelByPath(model, path.split("."));
684
- const modelOptions = (model instanceof DynamicSelectModel ? model.options : []);
797
+ const modelOptions = model instanceof DynamicSelectModel
798
+ ? await firstValueFrom(model.options$) :
799
+ [];
685
800
  const value = ObjectUtils.getValue(target.value, path);
686
801
  const options = (!ObjectUtils.isArray(value) ? [] : value).map(value => {
687
802
  const modelOption = modelOptions.find(t => t.value == value);
@@ -703,6 +818,14 @@ class DynamicFormService extends DynamicFormService$1 {
703
818
  return this.fixSelectOptions(selectModel, control, options);
704
819
  });
705
820
  }
821
+ getFormSelectConfig(property, schema) {
822
+ return Object.assign(this.getFormControlConfig(property, schema), {
823
+ options: this.getFormSelectOptions(property, schema),
824
+ multiple: property.type == "array",
825
+ groupBy: property.groupBy,
826
+ inline: property.inline
827
+ });
828
+ }
706
829
  getFormUploadConfig(property, schema) {
707
830
  const url = this.api.url(property.url || "assets");
708
831
  const { accept, autoUpload, maxSize, minSize, removeUrl, showFileList } = property;
@@ -716,6 +839,25 @@ class DynamicFormService extends DynamicFormService$1 {
716
839
  showFileList
717
840
  });
718
841
  }
842
+ getFormCheckboxConfig(property, schema) {
843
+ return Object.assign(this.getFormControlConfig(property, schema), {
844
+ indeterminate: property.indeterminate || false
845
+ });
846
+ }
847
+ cloneFormArrayGroup(index, formArray, formArrayModel) {
848
+ this.insertFormArrayGroup(index, formArray, formArrayModel);
849
+ this.patchGroup(formArray.at(index + 1).value, formArrayModel.groups[index].group, formArray.at(index));
850
+ formArrayModel.filterGroups();
851
+ }
852
+ async fixSelectOptions(model, control, options) {
853
+ if (!options)
854
+ return [];
855
+ for (const option of options) {
856
+ option.classes = [option.classes, model.getClasses(option, model, control, this.injector)].filter(isStringWithVal).join(" ");
857
+ option.label = await this.language.getTranslation(option.label);
858
+ }
859
+ return options;
860
+ }
719
861
  getValidators(property, schema) {
720
862
  const validators = {};
721
863
  if (ObjectUtils.isArray(schema.required) && schema.required.indexOf(property.id) >= 0) {
@@ -894,6 +1036,7 @@ class DynamicBaseFormComponent extends DynamicFormComponent {
894
1036
  this.onValueChange = new EventEmitter();
895
1037
  this.onStatusChange = new EventEmitter();
896
1038
  this.onSubmit = new EventEmitter();
1039
+ this.onDetectChanges = new EventEmitter();
897
1040
  this.templates = new QueryList();
898
1041
  this.subscription = new Subscription();
899
1042
  this.groupSubscription = new Subscription();
@@ -907,9 +1050,11 @@ class DynamicBaseFormComponent extends DynamicFormComponent {
907
1050
  if (this.group) {
908
1051
  this.groupSubscription = ObservableUtils.multiSubscription(this.group.statusChanges.subscribe(() => {
909
1052
  this.onStatusChange.emit(this);
910
- }), this.group.valueChanges.subscribe(() => {
911
- this.formService.notifyChanges(this.model, this.group, this.model);
912
- }), this.change.subscribe(ev => {
1053
+ }), this.group.valueChanges.pipe(debounceTime(500)).subscribe(() => {
1054
+ this.formService.notifyChanges(this.model, this.group);
1055
+ }), this.change.pipe(groupBy(ev => ev.model))
1056
+ .pipe(mergeMap(t => t.pipe(debounceTime(500))))
1057
+ .subscribe(ev => {
913
1058
  this.onValueChange.emit({ ...ev, form: this });
914
1059
  }));
915
1060
  }
@@ -922,6 +1067,7 @@ class DynamicBaseFormComponent extends DynamicFormComponent {
922
1067
  this.templates.reset(templates);
923
1068
  }
924
1069
  }), this.events.languageChanged.subscribe(() => {
1070
+ this.formService.notifyChanges(this.model, this.group);
925
1071
  this.formService.detectChanges(this);
926
1072
  }), this.ngForm.ngSubmit.subscribe(() => {
927
1073
  this.onSubmit.emit(this);
@@ -932,25 +1078,29 @@ class DynamicBaseFormComponent extends DynamicFormComponent {
932
1078
  this.subscription.unsubscribe();
933
1079
  this.groupSubscription.unsubscribe();
934
1080
  }
1081
+ detectChanges() {
1082
+ super.detectChanges();
1083
+ this.onDetectChanges.emit(this);
1084
+ }
935
1085
  insertFormArrayGroup(index, formArray, formArrayModel) {
936
1086
  this.formService.insertFormArrayGroup(index, formArray, formArrayModel);
937
- this.changeDetectorRef.detectChanges();
1087
+ this.detectChanges();
938
1088
  }
939
1089
  cloneFormArrayGroup(index, formArray, formArrayModel) {
940
1090
  this.formService.cloneFormArrayGroup(index, formArray, formArrayModel);
941
- this.changeDetectorRef.detectChanges();
1091
+ this.detectChanges();
942
1092
  }
943
1093
  removeFormArrayGroup(index, formArray, formArrayModel) {
944
1094
  this.formService.removeFormArrayGroup(index, formArray, formArrayModel);
945
- this.changeDetectorRef.detectChanges();
1095
+ this.detectChanges();
946
1096
  }
947
1097
  moveFormArrayGroup(index, step, formArray, formArrayModel) {
948
1098
  this.formService.moveFormArrayGroup(index, step, formArray, formArrayModel);
949
- this.changeDetectorRef.detectChanges();
1099
+ this.detectChanges();
950
1100
  }
951
1101
  clearFormArray(formArray, formArrayModel) {
952
1102
  this.formService.clearFormArray(formArray, formArrayModel);
953
- this.changeDetectorRef.detectChanges();
1103
+ this.detectChanges();
954
1104
  }
955
1105
  getClass(model) {
956
1106
  const parts = collectPathAble(model, p => p.id);
@@ -988,7 +1138,7 @@ class DynamicBaseFormComponent extends DynamicFormComponent {
988
1138
  }
989
1139
  }
990
1140
  DynamicBaseFormComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.8", ngImport: i0, type: DynamicBaseFormComponent, deps: [{ token: DynamicFormService }, { token: EventsService }, { token: i0.ChangeDetectorRef }, { token: i1.DynamicFormComponentService }], target: i0.ɵɵFactoryTarget.Component });
991
- DynamicBaseFormComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.8", type: DynamicBaseFormComponent, selector: "dynamic-base-form", inputs: { group: "group", model: "model", layout: "layout", labelPrefix: "labelPrefix" }, outputs: { blur: "blur", change: "change", focus: "focus", onValueChange: "onValueChange", onStatusChange: "onStatusChange", onSubmit: "onSubmit" }, queries: [{ propertyName: "contentTemplates", predicate: DynamicTemplateDirective }], viewQueries: [{ propertyName: "ngForm", first: true, predicate: NgForm, descendants: true }, { propertyName: "viewTemplates", predicate: DynamicTemplateDirective, descendants: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "", isInline: true, changeDetection: i0.ChangeDetectionStrategy.Default });
1141
+ DynamicBaseFormComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.8", type: DynamicBaseFormComponent, selector: "dynamic-base-form", inputs: { group: "group", model: "model", layout: "layout", labelPrefix: "labelPrefix" }, outputs: { blur: "blur", change: "change", focus: "focus", onValueChange: "onValueChange", onStatusChange: "onStatusChange", onSubmit: "onSubmit", onDetectChanges: "onDetectChanges" }, queries: [{ propertyName: "contentTemplates", predicate: DynamicTemplateDirective }], viewQueries: [{ propertyName: "ngForm", first: true, predicate: NgForm, descendants: true }, { propertyName: "viewTemplates", predicate: DynamicTemplateDirective, descendants: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "", isInline: true, changeDetection: i0.ChangeDetectionStrategy.Default });
992
1142
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.8", ngImport: i0, type: DynamicBaseFormComponent, decorators: [{
993
1143
  type: Component,
994
1144
  args: [{
@@ -1028,17 +1178,139 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.8", ngImpor
1028
1178
  type: Output
1029
1179
  }], onSubmit: [{
1030
1180
  type: Output
1181
+ }], onDetectChanges: [{
1182
+ type: Output
1031
1183
  }], ngForm: [{
1032
1184
  type: ViewChild,
1033
1185
  args: [NgForm]
1034
1186
  }] } });
1035
1187
 
1188
+ class DynamicBaseFormControlContainerComponent extends DynamicFormControlContainerComponent {
1189
+ constructor(form, cdr, cfr, layoutService, validationService, componentService, relationService) {
1190
+ super(cdr, cfr, layoutService, validationService, componentService, relationService);
1191
+ this.form = form;
1192
+ this.cdr = cdr;
1193
+ this.context = null;
1194
+ this.blur = new EventEmitter();
1195
+ this.change = new EventEmitter();
1196
+ this.focus = new EventEmitter();
1197
+ }
1198
+ get componentType() {
1199
+ return this.componentService.getCustomComponentType(this.model) ?? this.getComponentType(this.model);
1200
+ }
1201
+ get startTemplate() {
1202
+ return (this.model.type == DYNAMIC_FORM_CONTROL_TYPE_ARRAY)
1203
+ ? this.layoutService.getAlignedTemplate(this.model, this.templates, "ARRAY_START")
1204
+ : this.layoutService.getStartTemplate(this.model, this.templates);
1205
+ }
1206
+ get endTemplate() {
1207
+ return (this.model.type == DYNAMIC_FORM_CONTROL_TYPE_ARRAY)
1208
+ ? this.layoutService.getAlignedTemplate(this.model, this.templates, "ARRAY_END")
1209
+ : this.layoutService.getEndTemplate(this.model, this.templates);
1210
+ }
1211
+ get formService() {
1212
+ return this.form.formService;
1213
+ }
1214
+ ngOnInit() {
1215
+ super.ngOnInit();
1216
+ this.onDetectChanges = this.form.onDetectChanges.subscribe(() => {
1217
+ this.changeDetectorRef.detectChanges();
1218
+ });
1219
+ }
1220
+ ngOnDestroy() {
1221
+ super.ngOnDestroy();
1222
+ this.onDetectChanges.unsubscribe();
1223
+ }
1224
+ getLabel() {
1225
+ const label = collectPathAble(this.model, p => p.label);
1226
+ if (label.length == 0)
1227
+ return "";
1228
+ if (this.form?.labelPrefix) {
1229
+ label.unshift(this.form.labelPrefix);
1230
+ }
1231
+ return label.join(".");
1232
+ }
1233
+ getLabelIcon() {
1234
+ if (this.context instanceof DynamicFormArrayGroupModel) {
1235
+ const arrayModel = this.context.context;
1236
+ if (arrayModel && arrayModel.sortBy == this.model.id) {
1237
+ return arrayModel.sortOrder;
1238
+ }
1239
+ }
1240
+ return null;
1241
+ }
1242
+ clickLabel() {
1243
+ if (this.context instanceof DynamicFormArrayGroupModel) {
1244
+ const arrayModel = this.context.context;
1245
+ if (arrayModel) {
1246
+ arrayModel.sortBy = this.model.id;
1247
+ }
1248
+ }
1249
+ }
1250
+ createFormControlComponent() {
1251
+ super.createFormControlComponent();
1252
+ const component = this.componentRef?.instance;
1253
+ if (!component || !ObjectUtils.isFunction(component.initialize))
1254
+ return;
1255
+ component.initialize(this.changeDetectorRef);
1256
+ }
1257
+ getComponentType(model) {
1258
+ return null;
1259
+ }
1260
+ }
1261
+ DynamicBaseFormControlContainerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.8", ngImport: i0, type: DynamicBaseFormControlContainerComponent, deps: [{ token: DynamicBaseFormComponent }, { token: i0.ChangeDetectorRef }, { token: i0.ComponentFactoryResolver }, { token: i1.DynamicFormLayoutService }, { token: i1.DynamicFormValidationService }, { token: i1.DynamicFormComponentService }, { token: i1.DynamicFormRelationService }], target: i0.ɵɵFactoryTarget.Component });
1262
+ DynamicBaseFormControlContainerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.8", type: DynamicBaseFormControlContainerComponent, 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: [
1263
+ { provide: DynamicFormControlContainerComponent, useExisting: DynamicBaseFormControlContainerComponent }
1264
+ ], 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 });
1265
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.8", ngImport: i0, type: DynamicBaseFormControlContainerComponent, decorators: [{
1266
+ type: Component,
1267
+ args: [{
1268
+ selector: "dynamic-base-form-control",
1269
+ template: "",
1270
+ changeDetection: ChangeDetectionStrategy.OnPush,
1271
+ providers: [
1272
+ { provide: DynamicFormControlContainerComponent, useExisting: DynamicBaseFormControlContainerComponent }
1273
+ ]
1274
+ }]
1275
+ }], ctorParameters: function () { return [{ type: DynamicBaseFormComponent }, { type: i0.ChangeDetectorRef }, { type: i0.ComponentFactoryResolver }, { type: i1.DynamicFormLayoutService }, { type: i1.DynamicFormValidationService }, { type: i1.DynamicFormComponentService }, { type: i1.DynamicFormRelationService }]; }, propDecorators: { contentTemplateList: [{
1276
+ type: ContentChildren,
1277
+ args: [DynamicTemplateDirective]
1278
+ }], klass: [{
1279
+ type: HostBinding,
1280
+ args: ["class"]
1281
+ }], context: [{
1282
+ type: Input
1283
+ }], group: [{
1284
+ type: Input
1285
+ }], hostClass: [{
1286
+ type: Input
1287
+ }], inputTemplateList: [{
1288
+ type: Input,
1289
+ args: ["templates"]
1290
+ }], layout: [{
1291
+ type: Input
1292
+ }], model: [{
1293
+ type: Input
1294
+ }], blur: [{
1295
+ type: Output
1296
+ }], change: [{
1297
+ type: Output
1298
+ }], focus: [{
1299
+ type: Output
1300
+ }], componentViewContainerRef: [{
1301
+ type: ViewChild,
1302
+ args: ["componentViewContainer", {
1303
+ read: ViewContainerRef,
1304
+ static: true
1305
+ }]
1306
+ }] } });
1307
+
1036
1308
  class DynamicBaseFormArrayComponent extends DynamicFormArrayComponent {
1037
- constructor(layoutService, validationService, injector) {
1309
+ constructor(layoutService, validationService, form, injector, cdr) {
1038
1310
  super(layoutService, validationService);
1039
- this.layoutService = layoutService;
1040
- this.validationService = validationService;
1311
+ this.form = form;
1041
1312
  this.injector = injector;
1313
+ this.cdr = cdr;
1042
1314
  this.blur = new EventEmitter();
1043
1315
  this.change = new EventEmitter();
1044
1316
  this.customEvent = new EventEmitter();
@@ -1047,14 +1319,24 @@ class DynamicBaseFormArrayComponent extends DynamicFormArrayComponent {
1047
1319
  get useTabs() {
1048
1320
  return this.model?.useTabs;
1049
1321
  }
1322
+ initialize(cdr) {
1323
+ this.subscription = this.model.filteredGroups.subscribe(filteredGroups => {
1324
+ this.updateGroups(filteredGroups);
1325
+ });
1326
+ this.model.initialize(this.array);
1327
+ }
1328
+ ngOnDestroy() {
1329
+ if (this.subscription)
1330
+ this.subscription.unsubscribe();
1331
+ }
1050
1332
  saveTab(index) {
1051
- this.model.saveTab(index, this.model, this.injector);
1333
+ this.model.saveTab(index, this.model.getFiltered(index), this.model, this.injector);
1052
1334
  }
1053
1335
  restoreTab() {
1054
1336
  return this.model.restoreTab(this.model, this.injector);
1055
1337
  }
1056
- getTabLabel(index) {
1057
- return this.model.getTabLabel(index, this.model, this.array, this.injector);
1338
+ getTabLabel(index, model) {
1339
+ return this.model.getTabLabel(index, model, this.model, this.array, this.injector);
1058
1340
  }
1059
1341
  getClass(context, place, model) {
1060
1342
  return [
@@ -1082,9 +1364,13 @@ class DynamicBaseFormArrayComponent extends DynamicFormArrayComponent {
1082
1364
  }
1083
1365
  return null;
1084
1366
  }
1367
+ updateGroups(filteredGroups) {
1368
+ this.cdr.detectChanges();
1369
+ this.components.forEach(t => t.cdr.detectChanges());
1370
+ }
1085
1371
  }
1086
- DynamicBaseFormArrayComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.8", ngImport: i0, type: DynamicBaseFormArrayComponent, deps: [{ token: i1.DynamicFormLayoutService }, { token: i1.DynamicFormValidationService }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Component });
1087
- DynamicBaseFormArrayComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.8", type: DynamicBaseFormArrayComponent, 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(function () { return DynamicFormControlContainerComponent; }), descendants: true }], usesInheritance: true, ngImport: i0, template: "", isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
1372
+ DynamicBaseFormArrayComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.8", ngImport: i0, type: DynamicBaseFormArrayComponent, deps: [{ token: i1.DynamicFormLayoutService }, { token: i1.DynamicFormValidationService }, { token: DynamicBaseFormComponent }, { token: i0.Injector }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
1373
+ DynamicBaseFormArrayComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.8", type: DynamicBaseFormArrayComponent, 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(function () { return DynamicBaseFormControlContainerComponent; }), descendants: true }], usesInheritance: true, ngImport: i0, template: "", isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
1088
1374
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.8", ngImport: i0, type: DynamicBaseFormArrayComponent, decorators: [{
1089
1375
  type: Component,
1090
1376
  args: [{
@@ -1092,7 +1378,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.8", ngImpor
1092
1378
  template: "",
1093
1379
  changeDetection: ChangeDetectionStrategy.OnPush
1094
1380
  }]
1095
- }], ctorParameters: function () { return [{ type: i1.DynamicFormLayoutService }, { type: i1.DynamicFormValidationService }, { type: i0.Injector }]; }, propDecorators: { formLayout: [{
1381
+ }], ctorParameters: function () { return [{ type: i1.DynamicFormLayoutService }, { type: i1.DynamicFormValidationService }, { type: DynamicBaseFormComponent }, { type: i0.Injector }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { formLayout: [{
1096
1382
  type: Input
1097
1383
  }], group: [{
1098
1384
  type: Input
@@ -1112,18 +1398,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.8", ngImpor
1112
1398
  type: Output
1113
1399
  }], components: [{
1114
1400
  type: ViewChildren,
1115
- args: [forwardRef(() => DynamicFormControlContainerComponent)]
1401
+ args: [forwardRef(() => DynamicBaseFormControlContainerComponent)]
1116
1402
  }] } });
1117
1403
 
1118
1404
  class DynamicBaseFormControlComponent extends DynamicFormControlComponent {
1119
- constructor(layoutService, validationService) {
1405
+ constructor(cdr, layoutService, validationService) {
1120
1406
  super(layoutService, validationService);
1407
+ this.cdr = cdr;
1121
1408
  this.blur = new EventEmitter();
1122
1409
  this.change = new EventEmitter();
1123
1410
  this.focus = new EventEmitter();
1124
1411
  }
1125
1412
  }
1126
- DynamicBaseFormControlComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.8", ngImport: i0, type: DynamicBaseFormControlComponent, deps: [{ token: i1.DynamicFormLayoutService }, { token: i1.DynamicFormValidationService }], target: i0.ɵɵFactoryTarget.Component });
1413
+ DynamicBaseFormControlComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.8", ngImport: i0, type: DynamicBaseFormControlComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i1.DynamicFormLayoutService }, { token: i1.DynamicFormValidationService }], target: i0.ɵɵFactoryTarget.Component });
1127
1414
  DynamicBaseFormControlComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.8", type: DynamicBaseFormControlComponent, 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 });
1128
1415
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.8", ngImport: i0, type: DynamicBaseFormControlComponent, decorators: [{
1129
1416
  type: Component,
@@ -1132,7 +1419,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.8", ngImpor
1132
1419
  template: "",
1133
1420
  changeDetection: ChangeDetectionStrategy.OnPush
1134
1421
  }]
1135
- }], ctorParameters: function () { return [{ type: i1.DynamicFormLayoutService }, { type: i1.DynamicFormValidationService }]; }, propDecorators: { formLayout: [{
1422
+ }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }, { type: i1.DynamicFormLayoutService }, { type: i1.DynamicFormValidationService }]; }, propDecorators: { formLayout: [{
1136
1423
  type: Input
1137
1424
  }], group: [{
1138
1425
  type: Input
@@ -1148,108 +1435,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.8", ngImpor
1148
1435
  type: Output
1149
1436
  }] } });
1150
1437
 
1151
- class DynamicBaseFormControlContainerComponent extends DynamicFormControlContainerComponent {
1152
- constructor(form, changeDetectorRef, componentFactoryResolver, layoutService, validationService, componentService, relationService) {
1153
- super(changeDetectorRef, componentFactoryResolver, layoutService, validationService, componentService, relationService);
1154
- this.form = form;
1155
- this.changeDetectorRef = changeDetectorRef;
1156
- this.componentFactoryResolver = componentFactoryResolver;
1157
- this.layoutService = layoutService;
1158
- this.validationService = validationService;
1159
- this.componentService = componentService;
1160
- this.relationService = relationService;
1161
- this.context = null;
1162
- this.blur = new EventEmitter();
1163
- this.change = new EventEmitter();
1164
- this.focus = new EventEmitter();
1165
- }
1166
- get componentType() {
1167
- return this.componentService.getCustomComponentType(this.model) ?? this.getComponentType(this.model);
1168
- }
1169
- get startTemplate() {
1170
- return (this.model.type == DYNAMIC_FORM_CONTROL_TYPE_ARRAY)
1171
- ? this.layoutService.getAlignedTemplate(this.model, this.templates, "ARRAY_START")
1172
- : this.layoutService.getStartTemplate(this.model, this.templates);
1173
- }
1174
- get endTemplate() {
1175
- return (this.model.type == DYNAMIC_FORM_CONTROL_TYPE_ARRAY)
1176
- ? this.layoutService.getAlignedTemplate(this.model, this.templates, "ARRAY_END")
1177
- : this.layoutService.getEndTemplate(this.model, this.templates);
1178
- }
1179
- get formService() {
1180
- return this.form.formService;
1181
- }
1182
- ngOnInit() {
1183
- this.onDetectChanges = this.formService.onDetectChanges.subscribe(form => {
1184
- if (form !== this.form)
1185
- return;
1186
- this.changeDetectorRef.detectChanges();
1187
- this.formService.updateSelectOptions(this.model, this.control, this.form.model);
1188
- });
1189
- }
1190
- ngOnDestroy() {
1191
- super.ngOnDestroy();
1192
- this.onDetectChanges.unsubscribe();
1193
- }
1194
- getLabel() {
1195
- const label = collectPathAble(this.model, p => p.label);
1196
- if (label.length == 0)
1197
- return "";
1198
- if (this.form?.labelPrefix) {
1199
- label.unshift(this.form.labelPrefix);
1200
- }
1201
- return label.join(".");
1202
- }
1203
- createFormControlComponent() {
1204
- super.createFormControlComponent();
1205
- const component = this.componentRef?.instance;
1206
- if (!component || !ObjectUtils.isFunction(component.onCreated))
1207
- return;
1208
- component.onCreated();
1209
- }
1210
- getComponentType(model) {
1211
- return null;
1212
- }
1213
- }
1214
- DynamicBaseFormControlContainerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.8", ngImport: i0, type: DynamicBaseFormControlContainerComponent, deps: [{ token: DynamicBaseFormComponent }, { token: i0.ChangeDetectorRef }, { token: i0.ComponentFactoryResolver }, { token: i1.DynamicFormLayoutService }, { token: i1.DynamicFormValidationService }, { token: i1.DynamicFormComponentService }, { token: i1.DynamicFormRelationService }], target: i0.ɵɵFactoryTarget.Component });
1215
- DynamicBaseFormControlContainerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.8", type: DynamicBaseFormControlContainerComponent, 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" } }, 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 });
1216
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.8", ngImport: i0, type: DynamicBaseFormControlContainerComponent, decorators: [{
1217
- type: Component,
1218
- args: [{
1219
- selector: "dynamic-base-form-control",
1220
- template: "",
1221
- changeDetection: ChangeDetectionStrategy.OnPush
1222
- }]
1223
- }], ctorParameters: function () { return [{ type: DynamicBaseFormComponent }, { type: i0.ChangeDetectorRef }, { type: i0.ComponentFactoryResolver }, { type: i1.DynamicFormLayoutService }, { type: i1.DynamicFormValidationService }, { type: i1.DynamicFormComponentService }, { type: i1.DynamicFormRelationService }]; }, propDecorators: { contentTemplateList: [{
1224
- type: ContentChildren,
1225
- args: [DynamicTemplateDirective]
1226
- }], klass: [{
1227
- type: HostBinding,
1228
- args: ["class"]
1229
- }], context: [{
1230
- type: Input
1231
- }], group: [{
1232
- type: Input
1233
- }], hostClass: [{
1234
- type: Input
1235
- }], inputTemplateList: [{
1236
- type: Input,
1237
- args: ["templates"]
1238
- }], layout: [{
1239
- type: Input
1240
- }], model: [{
1241
- type: Input
1242
- }], blur: [{
1243
- type: Output
1244
- }], change: [{
1245
- type: Output
1246
- }], focus: [{
1247
- type: Output
1248
- }], componentViewContainerRef: [{
1249
- type: ViewChild,
1250
- args: ["componentViewContainer", { read: ViewContainerRef, static: true }]
1251
- }] } });
1252
-
1253
1438
  class DynamicBaseFormGroupComponent extends DynamicFormGroupComponent {
1254
1439
  constructor(layoutService, validationService) {
1255
1440
  super(layoutService, validationService);
@@ -1323,18 +1508,21 @@ class DynamicBaseSelectComponent extends DynamicBaseFormControlComponent {
1323
1508
  this.groups$ = new BehaviorSubject([]);
1324
1509
  this.subscription = this.model.options$.subscribe(options => {
1325
1510
  const groupBy = this.model.inline || !this.model.multiple ? this.model.groupBy : null;
1326
- const groups = options.reduce((res, option) => {
1511
+ const grouped = options.reduce((res, option) => {
1327
1512
  const key = replaceSpecialChars(groupBy ? option.props[this.model.groupBy] || "default" : "default", "-");
1328
1513
  res[key] = res[key] || [];
1329
1514
  res[key].push(option);
1330
1515
  return res;
1331
1516
  }, {});
1332
- this.groups$.next(Object.keys(groups).map(group => {
1517
+ const groups = Object.keys(grouped).map(group => {
1333
1518
  return {
1334
1519
  group,
1335
- options: groups[group]
1520
+ options: grouped[group]
1336
1521
  };
1337
- }));
1522
+ });
1523
+ this.hasOptions = groups.length > 0;
1524
+ this.groups$.next(groups);
1525
+ this.cdr.detectChanges();
1338
1526
  });
1339
1527
  }
1340
1528
  ngOnDestroy() {
@@ -1500,5 +1688,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.8", ngImpor
1500
1688
  * Generated bundle index. Do not edit.
1501
1689
  */
1502
1690
 
1503
- export { AsyncSubmitDirective, DynamicBaseFormArrayComponent, DynamicBaseFormComponent, DynamicBaseFormControlComponent, DynamicBaseFormControlContainerComponent, DynamicBaseFormGroupComponent, DynamicBaseSelectComponent, DynamicFormArrayModel, DynamicFormOption, DynamicFormService, DynamicSelectModel, FormFile, FormInput, FormModel, FormSelect, FormSelectSubject, FormSerializable, FormStatic, FormSubject, MAX_INPUT_NUM, MIN_INPUT_NUM, NgxDynamicFormModule, createFormControl, createFormInput, createFormModel, createFormSelect, createFormStatic, defaultSerializer, defineFormControl, getFormControl, getFormSerializer, mergeFormModels, replaceSpecialChars, validateItemsMaxLength, validateItemsMaxValue, validateItemsMinLength, validateItemsMinValue, validateJSON, validatePhone, validateRequiredTranslation };
1691
+ export { AsyncSubmitDirective, DynamicBaseFormArrayComponent, DynamicBaseFormComponent, DynamicBaseFormControlComponent, DynamicBaseFormControlContainerComponent, DynamicBaseFormGroupComponent, DynamicBaseSelectComponent, DynamicFormArrayGroupModel, DynamicFormArrayModel, DynamicFormOption, DynamicFormService, DynamicSelectModel, EDITOR_FORMATS, FormFile, FormInput, FormModel, FormSelect, FormSelectSubject, FormSerializable, FormStatic, FormSubject, MAX_INPUT_NUM, MIN_INPUT_NUM, NgxDynamicFormModule, createFormControl, createFormInput, createFormModel, createFormSelect, createFormStatic, defaultSerializer, defineFormControl, getFormControl, getFormSerializer, mergeFormModels, replaceSpecialChars, validateItemsMaxLength, validateItemsMaxValue, validateItemsMinLength, validateItemsMinValue, validateJSON, validatePhone, validateRequiredTranslation };
1504
1692
  //# sourceMappingURL=stemy-ngx-dynamic-form.mjs.map