@stemy/ngx-dynamic-form 13.1.3 → 13.1.5

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 (26) 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 +68 -63
  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 +2 -2
  11. package/esm2020/public_api.mjs +2 -2
  12. package/fesm2015/stemy-ngx-dynamic-form.mjs +370 -206
  13. package/fesm2015/stemy-ngx-dynamic-form.mjs.map +1 -1
  14. package/fesm2020/stemy-ngx-dynamic-form.mjs +362 -200
  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 +9 -10
  24. package/ngx-dynamic-form/utils/dynamic-form-array.model.d.ts +47 -4
  25. package/package.json +1 -1
  26. package/public_api.d.ts +2 -2
@@ -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
+ 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, 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';
5
6
  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';
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 = [];
@@ -205,12 +205,31 @@ function validateItemsMaxValue(max) {
205
205
  };
206
206
  }
207
207
 
208
+ class DynamicFormArrayGroupModel extends DynamicFormArrayGroupModel$1 {
209
+ constructor(context, group, index = -1) {
210
+ super(context, group, index);
211
+ this.context = context;
212
+ this.isHidden = false;
213
+ }
214
+ get hidden() {
215
+ return this.isHidden;
216
+ }
217
+ set hidden(value) {
218
+ if (this.isHidden == value)
219
+ return;
220
+ this.isHidden = value || false;
221
+ this.context?.filterGroups();
222
+ }
223
+ }
208
224
  class DynamicFormArrayModel extends DynamicFormArrayModel$1 {
209
225
  constructor(config, layout) {
210
226
  super(config, layout);
227
+ this.config = config;
228
+ this.filteredGroups = new BehaviorSubject([]);
229
+ this.sortable = config.sortable || false;
211
230
  this.useTabs = config.useTabs || false;
212
- this.saveTab = ObjectUtils.isFunction(config.saveTab) ? config.saveTab : ((index, model) => {
213
- model.tabIndex = index;
231
+ this.saveTab = ObjectUtils.isFunction(config.saveTab) ? config.saveTab : ((index, model, arrayModel) => {
232
+ arrayModel.tabIndex = index;
214
233
  });
215
234
  this.restoreTab = ObjectUtils.isFunction(config.restoreTab) ? config.restoreTab : ((model) => {
216
235
  return model.tabIndex;
@@ -219,6 +238,95 @@ class DynamicFormArrayModel extends DynamicFormArrayModel$1 {
219
238
  return `${index + 1}`;
220
239
  });
221
240
  this.additional = config.additional || {};
241
+ this.tabIndex = 0;
242
+ this._sortBy = null;
243
+ this._sortDescending = false;
244
+ this._formArray = null;
245
+ }
246
+ get addItem() {
247
+ return this.config.addItem !== false;
248
+ }
249
+ get insertItem() {
250
+ return !this._sortBy && this.config.insertItem !== false;
251
+ }
252
+ get cloneItem() {
253
+ return this.config.cloneItem !== false;
254
+ }
255
+ get moveItem() {
256
+ return !this._sortBy && this.config.moveItem !== false;
257
+ }
258
+ get removeItem() {
259
+ return this.config.removeItem !== false;
260
+ }
261
+ get clearItems() {
262
+ return this.config.clearItems !== false;
263
+ }
264
+ get sortBy() {
265
+ return this._sortBy;
266
+ }
267
+ set sortBy(value) {
268
+ if (!this.sortable)
269
+ return;
270
+ value = value || null;
271
+ if (this._sortBy !== value) {
272
+ this._sortBy = value;
273
+ this._sortDescending = false;
274
+ }
275
+ else if (this._sortDescending) {
276
+ this._sortBy = null;
277
+ this._sortDescending = false;
278
+ }
279
+ else {
280
+ this._sortDescending = true;
281
+ }
282
+ this.filterGroups();
283
+ }
284
+ get sortDescending() {
285
+ return this._sortDescending;
286
+ }
287
+ get sortOrder() {
288
+ return this.sortDescending ? "desc" : "asc";
289
+ }
290
+ initialize(array) {
291
+ this._formArray = array || this._formArray;
292
+ this.filterGroups();
293
+ }
294
+ filterGroups() {
295
+ this._filterTimer = this._filterTimer || TimerUtils.createTimeout();
296
+ this._filterTimer.set(() => {
297
+ const filtered = this.groups.filter(g => !g.hidden);
298
+ if (this._sortBy && this._formArray) {
299
+ const compare = this._sortDescending
300
+ ? (a, b) => this.compareModels(b, a)
301
+ : (a, b) => this.compareModels(a, b);
302
+ filtered.sort(compare);
303
+ }
304
+ this._filteredGroups = filtered;
305
+ this.filteredGroups.next(filtered);
306
+ }, 100);
307
+ }
308
+ getFiltered(index) {
309
+ return !this._filteredGroups ? null : this._filteredGroups[index];
310
+ }
311
+ insertGroup(index) {
312
+ const group = new DynamicFormArrayGroupModel(this, this.groupFactory());
313
+ this.groups.splice(index, 0, group);
314
+ this.groups.forEach((g, index) => g.index = index);
315
+ this.filterGroups();
316
+ return group;
317
+ }
318
+ moveGroup(index, step) {
319
+ super.moveGroup(index, step);
320
+ this.filterGroups();
321
+ }
322
+ removeGroup(index) {
323
+ super.removeGroup(index);
324
+ this.filterGroups();
325
+ }
326
+ compareModels(a, b) {
327
+ const aGroup = this._formArray.at(a.index).get(this._sortBy)?.value || null;
328
+ const bGroup = this._formArray.at(b.index).get(this._sortBy)?.value || null;
329
+ return ObjectUtils.compare(aGroup, bGroup);
222
330
  }
223
331
  }
224
332
 
@@ -307,21 +415,24 @@ class FormSubject extends Subject {
307
415
  class FormSelectSubject extends FormSubject {
308
416
  handleNotifiedValue(controlModel, control, val) {
309
417
  val.then(options => {
310
- this.next(options);
311
- if (options.length == 0)
418
+ if (options.length == 0) {
419
+ this.next(options);
312
420
  return;
421
+ }
313
422
  const currentVal = control.value;
314
423
  if (controlModel.multiple) {
315
424
  const correctVal = (currentVal || []).filter(t => options.findIndex(o => o.value == t) >= 0);
316
425
  if (correctVal.length !== currentVal?.length) {
317
426
  control.setValue(correctVal, { onlySelf: true, emitEvent: false });
318
427
  }
319
- return;
320
428
  }
321
- const option = options.find(t => t.value == currentVal);
322
- if (!option) {
323
- control.setValue(options[0]?.value ?? null, { onlySelf: true, emitEvent: false });
429
+ else {
430
+ const option = options.find(t => t.value == currentVal);
431
+ if (!option) {
432
+ control.setValue(options[0]?.value ?? null, { onlySelf: true, emitEvent: false });
433
+ }
324
434
  }
435
+ this.next(options);
325
436
  });
326
437
  }
327
438
  }
@@ -331,7 +442,6 @@ class DynamicFormService extends DynamicFormService$1 {
331
442
  super(cs, vs);
332
443
  this.openApi = openApi;
333
444
  this.injector = injector;
334
- this.onDetectChanges = new EventEmitter();
335
445
  }
336
446
  get api() {
337
447
  return this.openApi.api;
@@ -341,43 +451,24 @@ class DynamicFormService extends DynamicFormService$1 {
341
451
  }
342
452
  patchGroup(value, formModel, formGroup) {
343
453
  this.patchValueRecursive(value, formModel, formGroup);
344
- this.detectChanges();
345
454
  formGroup.patchValue(ObjectUtils.copy(value));
455
+ this.detectChanges();
346
456
  }
347
457
  patchForm(value, component) {
348
458
  this.patchValueRecursive(value, component.model, component.group);
349
- this.detectChanges(component);
350
459
  component.group.patchValue(value);
460
+ this.detectChanges(component);
351
461
  }
352
462
  serialize(formModel, formGroup) {
353
463
  return this.serializeRecursive(formModel, formGroup);
354
464
  }
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
- }
465
+ notifyChanges(formModel, formGroup) {
466
+ this.notifyChangesRecursive(formModel, formGroup, formModel);
372
467
  }
373
468
  showErrors(form) {
374
469
  this.showErrorsForGroup(form.group);
375
470
  this.detectChanges(form);
376
471
  }
377
- detectChanges(formComponent) {
378
- super.detectChanges(formComponent);
379
- this.onDetectChanges.emit(formComponent);
380
- }
381
472
  patchValueRecursive(value, formModel, formGroup) {
382
473
  Object.keys(value).forEach(key => {
383
474
  const subModel = this.findModelById(key, formModel);
@@ -389,7 +480,7 @@ class DynamicFormService extends DynamicFormService$1 {
389
480
  value[key] = subValue.id || subValue._id || subValue;
390
481
  return;
391
482
  }
392
- if (subModel instanceof DynamicFormArrayModel$1) {
483
+ if (subModel instanceof DynamicFormArrayModel) {
393
484
  const length = Array.isArray(subValue) ? subValue.length : 0;
394
485
  const subArray = subControl;
395
486
  while (subModel.size > length) {
@@ -421,7 +512,7 @@ class DynamicFormService extends DynamicFormService$1 {
421
512
  result[subModel.id] = await serializer(subModel, subControl);
422
513
  continue;
423
514
  }
424
- if (subModel instanceof DynamicFormArrayModel$1) {
515
+ if (subModel instanceof DynamicFormArrayModel) {
425
516
  const length = Array.isArray(subControl.value) ? subControl.value.length : 0;
426
517
  const subArray = subControl;
427
518
  const resArray = [];
@@ -452,7 +543,7 @@ class DynamicFormService extends DynamicFormService$1 {
452
543
  for (const i in formModel) {
453
544
  const subModel = formModel[i];
454
545
  const subControl = this.findControlByModel(subModel, formGroup);
455
- if (subModel instanceof DynamicFormArrayModel$1) {
546
+ if (subModel instanceof DynamicFormArrayModel) {
456
547
  const length = Array.isArray(subControl.value) ? subControl.value.length : 0;
457
548
  const subArray = subControl;
458
549
  for (let i = 0; i < length; i++) {
@@ -468,6 +559,21 @@ class DynamicFormService extends DynamicFormService$1 {
468
559
  this.updateSelectOptions(subModel, subControl, root);
469
560
  }
470
561
  }
562
+ updateSelectOptions(formControlModel, formControl, root) {
563
+ if (formControlModel instanceof DynamicSelectModel) {
564
+ let options = formControlModel.options$;
565
+ if (options instanceof FormSubject) {
566
+ options.notify(formControlModel, formControl, root);
567
+ return;
568
+ }
569
+ while (options instanceof Subject && options.source) {
570
+ options = options.source;
571
+ if (options instanceof FormSubject) {
572
+ options.notify(formControlModel, formControl, root);
573
+ }
574
+ }
575
+ }
576
+ }
471
577
  showErrorsForGroup(formGroup) {
472
578
  if (!formGroup)
473
579
  return;
@@ -534,7 +640,7 @@ class DynamicFormService extends DynamicFormService$1 {
534
640
  case "file":
535
641
  return customizeModels(property, schema, DynamicFileUploadModel, this.getFormUploadConfig(property, schema));
536
642
  }
537
- if (property.$ref) {
643
+ if (findRefs(property).length > 0) {
538
644
  return customizeModels(property, schema, DynamicFormGroupModel, this.getFormGroupConfig(property, schema, customizeModels));
539
645
  }
540
646
  return [];
@@ -546,7 +652,7 @@ class DynamicFormService extends DynamicFormService$1 {
546
652
  if (Array.isArray(parent)) {
547
653
  return this.findModelByPath(parent.find(t => t.id == next), path);
548
654
  }
549
- if (parent instanceof DynamicFormGroupModel) {
655
+ if (parent instanceof DynamicFormGroupModel || parent instanceof DynamicFormArrayGroupModel) {
550
656
  return this.findModelByPath(parent.group.find(t => t.id == next), path);
551
657
  }
552
658
  if (parent instanceof DynamicFormArrayModel) {
@@ -574,7 +680,14 @@ class DynamicFormService extends DynamicFormService$1 {
574
680
  const subSchemas = findRefs(property).map(ref => this.schemas[ref]);
575
681
  return Object.assign(this.getFormControlConfig(property, schema), {
576
682
  groupFactory: () => mergeFormModels(subSchemas.map(s => this.getFormModelForSchemaDef(s, customizeModels))),
577
- useTabs: property.useTabs || false
683
+ sortable: property.sortable || false,
684
+ useTabs: property.useTabs || false,
685
+ addItem: property.addItem !== false,
686
+ insertItem: property.insertItem !== false,
687
+ cloneItem: property.cloneItem !== false,
688
+ moveItem: property.moveItem !== false,
689
+ removeItem: property.removeItem !== false,
690
+ clearItems: property.clearItems !== false
578
691
  });
579
692
  }
580
693
  getFormGroupConfig(property, schema, customizeModels) {
@@ -621,32 +734,6 @@ class DynamicFormService extends DynamicFormService$1 {
621
734
  multiple: property.type == "array"
622
735
  });
623
736
  }
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
737
  getFormSelectOptions(property, schema) {
651
738
  const $enum = property.items?.enum || property.enum;
652
739
  if (Array.isArray($enum)) {
@@ -659,7 +746,7 @@ class DynamicFormService extends DynamicFormService$1 {
659
746
  });
660
747
  }
661
748
  if (isStringWithVal(property.optionsPath)) {
662
- return new FormSelectSubject((selectModel, control, root, indexes) => {
749
+ return new FormSelectSubject(async (selectModel, control, root, indexes) => {
663
750
  let path = property.optionsPath;
664
751
  let target = control;
665
752
  let model = selectModel;
@@ -681,7 +768,9 @@ class DynamicFormService extends DynamicFormService$1 {
681
768
  path = path.replace(key, indexes[key]);
682
769
  });
683
770
  model = this.findModelByPath(model, path.split("."));
684
- const modelOptions = (model instanceof DynamicSelectModel ? model.options : []);
771
+ const modelOptions = model instanceof DynamicSelectModel
772
+ ? await firstValueFrom(model.options$) :
773
+ [];
685
774
  const value = ObjectUtils.getValue(target.value, path);
686
775
  const options = (!ObjectUtils.isArray(value) ? [] : value).map(value => {
687
776
  const modelOption = modelOptions.find(t => t.value == value);
@@ -703,6 +792,14 @@ class DynamicFormService extends DynamicFormService$1 {
703
792
  return this.fixSelectOptions(selectModel, control, options);
704
793
  });
705
794
  }
795
+ getFormSelectConfig(property, schema) {
796
+ return Object.assign(this.getFormControlConfig(property, schema), {
797
+ options: this.getFormSelectOptions(property, schema),
798
+ multiple: property.type == "array",
799
+ groupBy: property.groupBy,
800
+ inline: property.inline
801
+ });
802
+ }
706
803
  getFormUploadConfig(property, schema) {
707
804
  const url = this.api.url(property.url || "assets");
708
805
  const { accept, autoUpload, maxSize, minSize, removeUrl, showFileList } = property;
@@ -716,6 +813,25 @@ class DynamicFormService extends DynamicFormService$1 {
716
813
  showFileList
717
814
  });
718
815
  }
816
+ getFormCheckboxConfig(property, schema) {
817
+ return Object.assign(this.getFormControlConfig(property, schema), {
818
+ indeterminate: property.indeterminate || false
819
+ });
820
+ }
821
+ cloneFormArrayGroup(index, formArray, formArrayModel) {
822
+ this.insertFormArrayGroup(index, formArray, formArrayModel);
823
+ this.patchGroup(formArray.at(index + 1).value, formArrayModel.groups[index].group, formArray.at(index));
824
+ formArrayModel.filterGroups();
825
+ }
826
+ async fixSelectOptions(model, control, options) {
827
+ if (!options)
828
+ return [];
829
+ for (const option of options) {
830
+ option.classes = [option.classes, model.getClasses(option, model, control, this.injector)].filter(isStringWithVal).join(" ");
831
+ option.label = await this.language.getTranslation(option.label);
832
+ }
833
+ return options;
834
+ }
719
835
  getValidators(property, schema) {
720
836
  const validators = {};
721
837
  if (ObjectUtils.isArray(schema.required) && schema.required.indexOf(property.id) >= 0) {
@@ -894,6 +1010,7 @@ class DynamicBaseFormComponent extends DynamicFormComponent {
894
1010
  this.onValueChange = new EventEmitter();
895
1011
  this.onStatusChange = new EventEmitter();
896
1012
  this.onSubmit = new EventEmitter();
1013
+ this.onDetectChanges = new EventEmitter();
897
1014
  this.templates = new QueryList();
898
1015
  this.subscription = new Subscription();
899
1016
  this.groupSubscription = new Subscription();
@@ -907,9 +1024,11 @@ class DynamicBaseFormComponent extends DynamicFormComponent {
907
1024
  if (this.group) {
908
1025
  this.groupSubscription = ObservableUtils.multiSubscription(this.group.statusChanges.subscribe(() => {
909
1026
  this.onStatusChange.emit(this);
910
- }), this.group.valueChanges.subscribe(() => {
911
- this.formService.notifyChanges(this.model, this.group, this.model);
912
- }), this.change.subscribe(ev => {
1027
+ }), this.group.valueChanges.pipe(debounceTime(500)).subscribe(() => {
1028
+ this.formService.notifyChanges(this.model, this.group);
1029
+ }), this.change.pipe(groupBy(ev => ev.model))
1030
+ .pipe(mergeMap(t => t.pipe(debounceTime(500))))
1031
+ .subscribe(ev => {
913
1032
  this.onValueChange.emit({ ...ev, form: this });
914
1033
  }));
915
1034
  }
@@ -922,6 +1041,7 @@ class DynamicBaseFormComponent extends DynamicFormComponent {
922
1041
  this.templates.reset(templates);
923
1042
  }
924
1043
  }), this.events.languageChanged.subscribe(() => {
1044
+ this.formService.notifyChanges(this.model, this.group);
925
1045
  this.formService.detectChanges(this);
926
1046
  }), this.ngForm.ngSubmit.subscribe(() => {
927
1047
  this.onSubmit.emit(this);
@@ -932,25 +1052,29 @@ class DynamicBaseFormComponent extends DynamicFormComponent {
932
1052
  this.subscription.unsubscribe();
933
1053
  this.groupSubscription.unsubscribe();
934
1054
  }
1055
+ detectChanges() {
1056
+ super.detectChanges();
1057
+ this.onDetectChanges.emit(this);
1058
+ }
935
1059
  insertFormArrayGroup(index, formArray, formArrayModel) {
936
1060
  this.formService.insertFormArrayGroup(index, formArray, formArrayModel);
937
- this.changeDetectorRef.detectChanges();
1061
+ this.detectChanges();
938
1062
  }
939
1063
  cloneFormArrayGroup(index, formArray, formArrayModel) {
940
1064
  this.formService.cloneFormArrayGroup(index, formArray, formArrayModel);
941
- this.changeDetectorRef.detectChanges();
1065
+ this.detectChanges();
942
1066
  }
943
1067
  removeFormArrayGroup(index, formArray, formArrayModel) {
944
1068
  this.formService.removeFormArrayGroup(index, formArray, formArrayModel);
945
- this.changeDetectorRef.detectChanges();
1069
+ this.detectChanges();
946
1070
  }
947
1071
  moveFormArrayGroup(index, step, formArray, formArrayModel) {
948
1072
  this.formService.moveFormArrayGroup(index, step, formArray, formArrayModel);
949
- this.changeDetectorRef.detectChanges();
1073
+ this.detectChanges();
950
1074
  }
951
1075
  clearFormArray(formArray, formArrayModel) {
952
1076
  this.formService.clearFormArray(formArray, formArrayModel);
953
- this.changeDetectorRef.detectChanges();
1077
+ this.detectChanges();
954
1078
  }
955
1079
  getClass(model) {
956
1080
  const parts = collectPathAble(model, p => p.id);
@@ -988,7 +1112,7 @@ class DynamicBaseFormComponent extends DynamicFormComponent {
988
1112
  }
989
1113
  }
990
1114
  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 });
1115
+ 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
1116
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.8", ngImport: i0, type: DynamicBaseFormComponent, decorators: [{
993
1117
  type: Component,
994
1118
  args: [{
@@ -1028,17 +1152,139 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.8", ngImpor
1028
1152
  type: Output
1029
1153
  }], onSubmit: [{
1030
1154
  type: Output
1155
+ }], onDetectChanges: [{
1156
+ type: Output
1031
1157
  }], ngForm: [{
1032
1158
  type: ViewChild,
1033
1159
  args: [NgForm]
1034
1160
  }] } });
1035
1161
 
1162
+ class DynamicBaseFormControlContainerComponent extends DynamicFormControlContainerComponent {
1163
+ constructor(form, cdr, cfr, layoutService, validationService, componentService, relationService) {
1164
+ super(cdr, cfr, layoutService, validationService, componentService, relationService);
1165
+ this.form = form;
1166
+ this.cdr = cdr;
1167
+ this.context = null;
1168
+ this.blur = new EventEmitter();
1169
+ this.change = new EventEmitter();
1170
+ this.focus = new EventEmitter();
1171
+ }
1172
+ get componentType() {
1173
+ return this.componentService.getCustomComponentType(this.model) ?? this.getComponentType(this.model);
1174
+ }
1175
+ get startTemplate() {
1176
+ return (this.model.type == DYNAMIC_FORM_CONTROL_TYPE_ARRAY)
1177
+ ? this.layoutService.getAlignedTemplate(this.model, this.templates, "ARRAY_START")
1178
+ : this.layoutService.getStartTemplate(this.model, this.templates);
1179
+ }
1180
+ get endTemplate() {
1181
+ return (this.model.type == DYNAMIC_FORM_CONTROL_TYPE_ARRAY)
1182
+ ? this.layoutService.getAlignedTemplate(this.model, this.templates, "ARRAY_END")
1183
+ : this.layoutService.getEndTemplate(this.model, this.templates);
1184
+ }
1185
+ get formService() {
1186
+ return this.form.formService;
1187
+ }
1188
+ ngOnInit() {
1189
+ super.ngOnInit();
1190
+ this.onDetectChanges = this.form.onDetectChanges.subscribe(() => {
1191
+ this.changeDetectorRef.detectChanges();
1192
+ });
1193
+ }
1194
+ ngOnDestroy() {
1195
+ super.ngOnDestroy();
1196
+ this.onDetectChanges.unsubscribe();
1197
+ }
1198
+ getLabel() {
1199
+ const label = collectPathAble(this.model, p => p.label);
1200
+ if (label.length == 0)
1201
+ return "";
1202
+ if (this.form?.labelPrefix) {
1203
+ label.unshift(this.form.labelPrefix);
1204
+ }
1205
+ return label.join(".");
1206
+ }
1207
+ getLabelIcon() {
1208
+ if (this.context instanceof DynamicFormArrayGroupModel) {
1209
+ const arrayModel = this.context.context;
1210
+ if (arrayModel && arrayModel.sortBy == this.model.id) {
1211
+ return arrayModel.sortOrder;
1212
+ }
1213
+ }
1214
+ return null;
1215
+ }
1216
+ clickLabel() {
1217
+ if (this.context instanceof DynamicFormArrayGroupModel) {
1218
+ const arrayModel = this.context.context;
1219
+ if (arrayModel) {
1220
+ arrayModel.sortBy = this.model.id;
1221
+ }
1222
+ }
1223
+ }
1224
+ createFormControlComponent() {
1225
+ super.createFormControlComponent();
1226
+ const component = this.componentRef?.instance;
1227
+ if (!component || !ObjectUtils.isFunction(component.initialize))
1228
+ return;
1229
+ component.initialize(this.changeDetectorRef);
1230
+ }
1231
+ getComponentType(model) {
1232
+ return null;
1233
+ }
1234
+ }
1235
+ 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 });
1236
+ 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: [
1237
+ { provide: DynamicFormControlContainerComponent, useExisting: DynamicBaseFormControlContainerComponent }
1238
+ ], 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 });
1239
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.8", ngImport: i0, type: DynamicBaseFormControlContainerComponent, decorators: [{
1240
+ type: Component,
1241
+ args: [{
1242
+ selector: "dynamic-base-form-control",
1243
+ template: "",
1244
+ changeDetection: ChangeDetectionStrategy.OnPush,
1245
+ providers: [
1246
+ { provide: DynamicFormControlContainerComponent, useExisting: DynamicBaseFormControlContainerComponent }
1247
+ ]
1248
+ }]
1249
+ }], 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: [{
1250
+ type: ContentChildren,
1251
+ args: [DynamicTemplateDirective]
1252
+ }], klass: [{
1253
+ type: HostBinding,
1254
+ args: ["class"]
1255
+ }], context: [{
1256
+ type: Input
1257
+ }], group: [{
1258
+ type: Input
1259
+ }], hostClass: [{
1260
+ type: Input
1261
+ }], inputTemplateList: [{
1262
+ type: Input,
1263
+ args: ["templates"]
1264
+ }], layout: [{
1265
+ type: Input
1266
+ }], model: [{
1267
+ type: Input
1268
+ }], blur: [{
1269
+ type: Output
1270
+ }], change: [{
1271
+ type: Output
1272
+ }], focus: [{
1273
+ type: Output
1274
+ }], componentViewContainerRef: [{
1275
+ type: ViewChild,
1276
+ args: ["componentViewContainer", {
1277
+ read: ViewContainerRef,
1278
+ static: true
1279
+ }]
1280
+ }] } });
1281
+
1036
1282
  class DynamicBaseFormArrayComponent extends DynamicFormArrayComponent {
1037
- constructor(layoutService, validationService, injector) {
1283
+ constructor(layoutService, validationService, form, injector, cdr) {
1038
1284
  super(layoutService, validationService);
1039
- this.layoutService = layoutService;
1040
- this.validationService = validationService;
1285
+ this.form = form;
1041
1286
  this.injector = injector;
1287
+ this.cdr = cdr;
1042
1288
  this.blur = new EventEmitter();
1043
1289
  this.change = new EventEmitter();
1044
1290
  this.customEvent = new EventEmitter();
@@ -1047,14 +1293,24 @@ class DynamicBaseFormArrayComponent extends DynamicFormArrayComponent {
1047
1293
  get useTabs() {
1048
1294
  return this.model?.useTabs;
1049
1295
  }
1296
+ initialize(cdr) {
1297
+ this.subscription = this.model.filteredGroups.subscribe(filteredGroups => {
1298
+ this.updateGroups(filteredGroups);
1299
+ });
1300
+ this.model.initialize(this.array);
1301
+ }
1302
+ ngOnDestroy() {
1303
+ if (this.subscription)
1304
+ this.subscription.unsubscribe();
1305
+ }
1050
1306
  saveTab(index) {
1051
- this.model.saveTab(index, this.model, this.injector);
1307
+ this.model.saveTab(index, this.model.getFiltered(index), this.model, this.injector);
1052
1308
  }
1053
1309
  restoreTab() {
1054
1310
  return this.model.restoreTab(this.model, this.injector);
1055
1311
  }
1056
- getTabLabel(index) {
1057
- return this.model.getTabLabel(index, this.model, this.array, this.injector);
1312
+ getTabLabel(index, model) {
1313
+ return this.model.getTabLabel(index, model, this.model, this.array, this.injector);
1058
1314
  }
1059
1315
  getClass(context, place, model) {
1060
1316
  return [
@@ -1082,9 +1338,13 @@ class DynamicBaseFormArrayComponent extends DynamicFormArrayComponent {
1082
1338
  }
1083
1339
  return null;
1084
1340
  }
1341
+ updateGroups(filteredGroups) {
1342
+ this.cdr.detectChanges();
1343
+ this.components.forEach(t => t.cdr.detectChanges());
1344
+ }
1085
1345
  }
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 });
1346
+ 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 });
1347
+ 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
1348
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.8", ngImport: i0, type: DynamicBaseFormArrayComponent, decorators: [{
1089
1349
  type: Component,
1090
1350
  args: [{
@@ -1092,7 +1352,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.8", ngImpor
1092
1352
  template: "",
1093
1353
  changeDetection: ChangeDetectionStrategy.OnPush
1094
1354
  }]
1095
- }], ctorParameters: function () { return [{ type: i1.DynamicFormLayoutService }, { type: i1.DynamicFormValidationService }, { type: i0.Injector }]; }, propDecorators: { formLayout: [{
1355
+ }], ctorParameters: function () { return [{ type: i1.DynamicFormLayoutService }, { type: i1.DynamicFormValidationService }, { type: DynamicBaseFormComponent }, { type: i0.Injector }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { formLayout: [{
1096
1356
  type: Input
1097
1357
  }], group: [{
1098
1358
  type: Input
@@ -1112,18 +1372,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.8", ngImpor
1112
1372
  type: Output
1113
1373
  }], components: [{
1114
1374
  type: ViewChildren,
1115
- args: [forwardRef(() => DynamicFormControlContainerComponent)]
1375
+ args: [forwardRef(() => DynamicBaseFormControlContainerComponent)]
1116
1376
  }] } });
1117
1377
 
1118
1378
  class DynamicBaseFormControlComponent extends DynamicFormControlComponent {
1119
- constructor(layoutService, validationService) {
1379
+ constructor(cdr, layoutService, validationService) {
1120
1380
  super(layoutService, validationService);
1381
+ this.cdr = cdr;
1121
1382
  this.blur = new EventEmitter();
1122
1383
  this.change = new EventEmitter();
1123
1384
  this.focus = new EventEmitter();
1124
1385
  }
1125
1386
  }
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 });
1387
+ 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
1388
  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
1389
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.8", ngImport: i0, type: DynamicBaseFormControlComponent, decorators: [{
1129
1390
  type: Component,
@@ -1132,7 +1393,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.8", ngImpor
1132
1393
  template: "",
1133
1394
  changeDetection: ChangeDetectionStrategy.OnPush
1134
1395
  }]
1135
- }], ctorParameters: function () { return [{ type: i1.DynamicFormLayoutService }, { type: i1.DynamicFormValidationService }]; }, propDecorators: { formLayout: [{
1396
+ }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }, { type: i1.DynamicFormLayoutService }, { type: i1.DynamicFormValidationService }]; }, propDecorators: { formLayout: [{
1136
1397
  type: Input
1137
1398
  }], group: [{
1138
1399
  type: Input
@@ -1148,108 +1409,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.8", ngImpor
1148
1409
  type: Output
1149
1410
  }] } });
1150
1411
 
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
1412
  class DynamicBaseFormGroupComponent extends DynamicFormGroupComponent {
1254
1413
  constructor(layoutService, validationService) {
1255
1414
  super(layoutService, validationService);
@@ -1323,18 +1482,21 @@ class DynamicBaseSelectComponent extends DynamicBaseFormControlComponent {
1323
1482
  this.groups$ = new BehaviorSubject([]);
1324
1483
  this.subscription = this.model.options$.subscribe(options => {
1325
1484
  const groupBy = this.model.inline || !this.model.multiple ? this.model.groupBy : null;
1326
- const groups = options.reduce((res, option) => {
1485
+ const grouped = options.reduce((res, option) => {
1327
1486
  const key = replaceSpecialChars(groupBy ? option.props[this.model.groupBy] || "default" : "default", "-");
1328
1487
  res[key] = res[key] || [];
1329
1488
  res[key].push(option);
1330
1489
  return res;
1331
1490
  }, {});
1332
- this.groups$.next(Object.keys(groups).map(group => {
1491
+ const groups = Object.keys(grouped).map(group => {
1333
1492
  return {
1334
1493
  group,
1335
- options: groups[group]
1494
+ options: grouped[group]
1336
1495
  };
1337
- }));
1496
+ });
1497
+ this.hasOptions = groups.length > 0;
1498
+ this.groups$.next(groups);
1499
+ this.cdr.detectChanges();
1338
1500
  });
1339
1501
  }
1340
1502
  ngOnDestroy() {
@@ -1500,5 +1662,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.8", ngImpor
1500
1662
  * Generated bundle index. Do not edit.
1501
1663
  */
1502
1664
 
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 };
1665
+ export { AsyncSubmitDirective, DynamicBaseFormArrayComponent, DynamicBaseFormComponent, DynamicBaseFormControlComponent, DynamicBaseFormControlContainerComponent, DynamicBaseFormGroupComponent, DynamicBaseSelectComponent, DynamicFormArrayGroupModel, 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 };
1504
1666
  //# sourceMappingURL=stemy-ngx-dynamic-form.mjs.map