@sumaris-net/ngx-components 2.7.6-rc2 → 2.7.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.
@@ -12324,7 +12324,7 @@ class AppFormField {
12324
12324
  }
12325
12325
  }
12326
12326
  filterAlphanumericalInput(event) {
12327
- if (event.keyCode === 13 /*=Enter*/ && this.onKeyupEnter.observers.length > 0) {
12327
+ if (event.code === 'Enter' && this.onKeyupEnter.observed) {
12328
12328
  this.onKeyupEnter.emit(event);
12329
12329
  return;
12330
12330
  }
@@ -20557,7 +20557,7 @@ class ModalToolbarComponent {
20557
20557
  this.hotkeys = hotkeys;
20558
20558
  }
20559
20559
  ngOnInit() {
20560
- this.canValidate = toBoolean(this.canValidate, this.validate.observers.length > 0);
20560
+ this.canValidate = toBoolean(this.canValidate, this.validate.observed);
20561
20561
  // Ctrl+S
20562
20562
  this._subscription.add(this.hotkeys
20563
20563
  .addShortcut({ keys: 'control.s', description: 'COMMON.BTN_VALIDATE', elementName: this.modalName })
@@ -22885,7 +22885,7 @@ class AppImageGalleryComponent {
22885
22885
  }
22886
22886
  async canDeleteRows(rows, opts) {
22887
22887
  // Check using emitter
22888
- if (this.onBeforeDeleteRows.observers.length > 0) {
22888
+ if (this.onBeforeDeleteRows.observed) {
22889
22889
  try {
22890
22890
  const canDelete = await emitPromiseEvent(this.onBeforeDeleteRows, 'canDelete', {
22891
22891
  detail: { rows },
@@ -28923,7 +28923,7 @@ class AppTable {
28923
28923
  }
28924
28924
  cancel(event, opts) {
28925
28925
  // Check confirmation
28926
- if ((!opts || opts.interactive !== false) && this.dirty && (this.confirmBeforeCancel || this.onBeforeCancelRows.observers.length > 0)) {
28926
+ if ((!opts || opts.interactive !== false) && this.dirty && (this.confirmBeforeCancel || this.onBeforeCancelRows.observed)) {
28927
28927
  event?.stopPropagation();
28928
28928
  this.canCancelRows().then((confirm) => {
28929
28929
  // If confirmed, loop
@@ -28980,7 +28980,7 @@ class AppTable {
28980
28980
  }
28981
28981
  else {
28982
28982
  const rows = this._dataSource.getRows();
28983
- rows.forEach((row) => this.selection.select(row));
28983
+ this.selection.setSelection(...rows);
28984
28984
  }
28985
28985
  }
28986
28986
  async deleteSelection(event, opts) {
@@ -29329,7 +29329,7 @@ class AppTable {
29329
29329
  }
29330
29330
  async canDeleteRows(rows, opts) {
29331
29331
  // Check using emitter
29332
- if (this.onBeforeDeleteRows.observers.length > 0) {
29332
+ if (this.onBeforeDeleteRows.observed) {
29333
29333
  try {
29334
29334
  const canDelete = await emitPromiseEvent(this.onBeforeDeleteRows, 'canDelete', {
29335
29335
  detail: { rows },
@@ -29356,7 +29356,7 @@ class AppTable {
29356
29356
  if (isEmptyArray(rows))
29357
29357
  return true; // No dirty: OK
29358
29358
  // Check using emitter
29359
- if (this.onBeforeCancelRows.observers.length > 0) {
29359
+ if (this.onBeforeCancelRows.observed) {
29360
29360
  try {
29361
29361
  const isCancel = await emitPromiseEvent(this.onBeforeCancelRows, 'canCancel', {
29362
29362
  detail: { rows },
@@ -29399,7 +29399,7 @@ class AppTable {
29399
29399
  // Default behavior
29400
29400
  let confirmed = true;
29401
29401
  if (save) {
29402
- if (this.onBeforeSave.observers.length > 0) {
29402
+ if (this.onBeforeSave.observed) {
29403
29403
  // Ask confirmation
29404
29404
  try {
29405
29405
  const res = await emitPromiseEvent(this.onBeforeSave, 'beforeSave', {
@@ -29440,7 +29440,7 @@ class AppTable {
29440
29440
  if (this.debug && this.dirty) {
29441
29441
  console.warn('[table] Opening row details, but table has unsaved changes!');
29442
29442
  }
29443
- if (this.onOpenRow.observers.length) {
29443
+ if (this.onOpenRow.observed) {
29444
29444
  this.onOpenRow.emit(row);
29445
29445
  return true;
29446
29446
  }
@@ -29458,7 +29458,7 @@ class AppTable {
29458
29458
  async openNewRowDetail(event) {
29459
29459
  if (!this.allowRowDetail)
29460
29460
  return false;
29461
- if (this.onNewRow.observers.length > 0) {
29461
+ if (this.onNewRow.observed) {
29462
29462
  this.onNewRow.emit(event);
29463
29463
  return true;
29464
29464
  }
@@ -29803,7 +29803,7 @@ class AppTable {
29803
29803
  throw new Error('Row cannot be canceling, but only deleting');
29804
29804
  const confirmed = !opts || opts.interactive !== false;
29805
29805
  // Ask user confirmation, if cancel
29806
- if (!confirmed && row.dirty && (this.confirmBeforeCancel || this.onBeforeCancelRows.observers.length > 0)) {
29806
+ if (!confirmed && row.dirty && (this.confirmBeforeCancel || this.onBeforeCancelRows.observed)) {
29807
29807
  event.stopPropagation();
29808
29808
  this.canCancelRows([row], opts).then((confirm) => {
29809
29809
  // If confirmed, loop
@@ -30101,12 +30101,12 @@ class ActionsColumnComponent {
30101
30101
  ngOnInit() {
30102
30102
  this.cd.detectChanges();
30103
30103
  this.table.addColumnDef(this.columnDef);
30104
- this.canCancel = toBoolean(this.canCancel, this.cancelOrDeleteClick.observers.length > 0);
30105
- this.canConfirm = toBoolean(this.canConfirm, this.confirmEditCreateClick.observers.length > 0);
30106
- this.canDelete = toBoolean(this.canDelete, this.cancelOrDeleteClick.observers.length > 0);
30107
- this.canConfirmAndAdd = toBoolean(this.canConfirmAndAdd, this.confirmAndAddClick.observers.length > 0);
30108
- this.canBackward = toBoolean(this.canBackward, this.backward.observers.length > 0);
30109
- this.canForward = toBoolean(this.canForward, this.forward.observers.length > 0);
30104
+ this.canCancel = toBoolean(this.canCancel, this.cancelOrDeleteClick.observed);
30105
+ this.canConfirm = toBoolean(this.canConfirm, this.confirmEditCreateClick.observed);
30106
+ this.canDelete = toBoolean(this.canDelete, this.cancelOrDeleteClick.observed);
30107
+ this.canConfirmAndAdd = toBoolean(this.canConfirmAndAdd, this.confirmAndAddClick.observed);
30108
+ this.canBackward = toBoolean(this.canBackward, this.backward.observed);
30109
+ this.canForward = toBoolean(this.canForward, this.forward.observed);
30110
30110
  if (isNil(this.dirtyIcon)) {
30111
30111
  this.dirtyIcon = 'star';
30112
30112
  }
@@ -30594,7 +30594,7 @@ class AppListForm extends AppForm {
30594
30594
  }
30595
30595
  }
30596
30596
  async onItemClick(event, item, opts) {
30597
- if (!item || event.defaultPrevented || !this.selectionChanges.observers.length)
30597
+ if (!item || event.defaultPrevented || !this.selectionChanges.observed)
30598
30598
  return;
30599
30599
  // Multiple selection (if ctrl+click)
30600
30600
  if (event.ctrlKey && this.options.allowMultipleSelection) {
@@ -30658,11 +30658,11 @@ class AppListForm extends AppForm {
30658
30658
  this.cd.markForCheck();
30659
30659
  }
30660
30660
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: AppListForm, deps: [{ token: i0.Injector }, { token: i1$2.UntypedFormBuilder }, { token: i2.DateAdapter }, { token: LocalSettingsService }, { token: i0.ChangeDetectorRef }, { token: i1$2.FormGroupDirective, optional: true }], target: i0.ɵɵFactoryTarget.Component });
30661
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.2.4", type: AppListForm, selector: "app-list-form", inputs: { formArrayName: "formArrayName", formArray: "formArray", options: "options", displayWithFn: ["displayWith", "displayWithFn"], equalsFn: ["equals", "equalsFn"] }, outputs: { onNewItem: "onNewItem", selectionChanges: "selectionChanges" }, usesInheritance: true, ngImport: i0, template: "<ng-container *ngIf=\"!loading; else listSkeleton\">\n <!-- List -->\n <ion-list class=\"ion-no-padding\">\n <ng-container *ngFor=\"let itemControl of itemControls; index as i; last as last\">\n <ion-item\n *ngIf=\"itemControl.value; let item\"\n [class.disabled]=\"disabled\"\n tappable\n (click)=\"onItemClick($event, item)\"\n [color]=\"selection.isSelected(item) ? 'secondary100' : undefined\"\n [button]=\"selectionChanges.observers | isNotEmptyArray\"\n >\n <ion-label>{{ displayWith(item) }}</ion-label>\n\n <!-- buttons -->\n <ion-buttons slot=\"end\" *ngIf=\"enabled\" class=\"action-buttons\">\n <ion-button fill=\"clear\" (click)=\"removeAt(i)\">\n <ion-icon slot=\"icon-only\" name=\"trash\"></ion-icon>\n </ion-button>\n\n <ion-button\n *ngFor=\"let button of options.buttons\"\n fill=\"clear\"\n [color]=\"button.color\"\n [class.cdk-visually-hidden]=\"button.disabled | async\"\n (click)=\"onItemButtonClick(button, $event, item, i)\"\n [title]=\"button.title || '' | translate\"\n >\n <ion-icon slot=\"icon-only\" [name]=\"button.icon\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-item>\n </ng-container>\n </ion-list>\n\n <!-- Add button -->\n <ion-button\n color=\"tertiary\"\n fill=\"clear\"\n *ngIf=\"enabled && onNewItem.observers.length; else emptyText\"\n [title]=\"'COMMON.BTN_ADD' | translate\"\n (click)=\"onNewClick($event)\"\n >\n <ion-icon slot=\"start\" name=\"add\"></ion-icon>\n <ion-label translate>COMMON.BTN_ADD</ion-label>\n </ion-button>\n\n <!-- Empty (if readonly) -->\n <ng-template #emptyText>\n <ion-text *ngIf=\"!length\" color=\"medium\"><i translate>COMMON.EMPTY_OPTION</i></ion-text>\n </ng-template>\n</ng-container>\n\n<ng-template #listSkeleton>\n <ion-list>\n <ng-container *ngTemplateOutlet=\"itemSkeleton\"></ng-container>\n <ng-container *ngTemplateOutlet=\"itemSkeleton\"></ng-container>\n <ng-container *ngTemplateOutlet=\"itemSkeleton\"></ng-container>\n </ion-list>\n</ng-template>\n\n<ng-template #itemSkeleton>\n <ion-item>\n <ion-label>\n <ion-skeleton-text animated style=\"width: 60%\"></ion-skeleton-text>\n </ion-label>\n </ion-item>\n</ng-template>\n", styles: [":host{--ion-item-background-selected: var(--ion-color-secondary100);--ion-item-color-selected: var(--ion-color-secondary100-contrast)}ion-item.disabled ion-label{color:var(--ion-color-medium-shade, grey)}ion-item{--min-height: 48px;background-color:var(--ion-item-background)}ion-item ion-text,ion-item ion-label{color:var(--ion-item-color)}ion-item .action-buttons{visibility:hidden;display:none}ion-item:hover{height:var(--min-height);--ion-item-background-color: var(--ion-color-light);--ion-item-color: var(--ion-color-light-contrast)}ion-item:hover .action-buttons{margin-top:-1px;visibility:visible;display:block}ion-item.selected{--ion-item-background-color-hover: var(--ion-item-background-selected) !important;--ion-item-color-hover: var(--ion-item-color-selected) !important}\n"], dependencies: [{ kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i2$1.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i2$1.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i2$1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i2$1.IonItem, selector: "ion-item", inputs: ["button", "color", "counter", "counterFormatter", "detail", "detailIcon", "disabled", "download", "fill", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "shape", "target", "type"] }, { kind: "component", type: i2$1.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i2$1.IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: i2$1.IonSkeletonText, selector: "ion-skeleton-text", inputs: ["animated"] }, { kind: "component", type: i2$1.IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "directive", type: i1$1.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }, { kind: "pipe", type: NotEmptyArrayPipe, name: "isNotEmptyArray" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
30661
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.2.4", type: AppListForm, selector: "app-list-form", inputs: { formArrayName: "formArrayName", formArray: "formArray", options: "options", displayWithFn: ["displayWith", "displayWithFn"], equalsFn: ["equals", "equalsFn"] }, outputs: { onNewItem: "onNewItem", selectionChanges: "selectionChanges" }, usesInheritance: true, ngImport: i0, template: "<ng-container *ngIf=\"!loading; else listSkeleton\">\n <!-- List -->\n <ion-list class=\"ion-no-padding\">\n <ng-container *ngFor=\"let itemControl of itemControls; index as i; last as last\">\n <ion-item\n *ngIf=\"itemControl.value; let item\"\n [class.disabled]=\"disabled\"\n tappable\n (click)=\"onItemClick($event, item)\"\n [color]=\"selection.isSelected(item) ? 'secondary100' : undefined\"\n [button]=\"selectionChanges.observers | isNotEmptyArray\"\n >\n <ion-label>{{ displayWith(item) }}</ion-label>\n\n <!-- buttons -->\n <ion-buttons slot=\"end\" *ngIf=\"enabled\" class=\"action-buttons\">\n <ion-button fill=\"clear\" (click)=\"removeAt(i)\">\n <ion-icon slot=\"icon-only\" name=\"trash\"></ion-icon>\n </ion-button>\n\n <ion-button\n *ngFor=\"let button of options.buttons\"\n fill=\"clear\"\n [color]=\"button.color\"\n [class.cdk-visually-hidden]=\"button.disabled | async\"\n (click)=\"onItemButtonClick(button, $event, item, i)\"\n [title]=\"button.title || '' | translate\"\n >\n <ion-icon slot=\"icon-only\" [name]=\"button.icon\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-item>\n </ng-container>\n </ion-list>\n\n <!-- Add button -->\n <ion-button\n color=\"tertiary\"\n fill=\"clear\"\n *ngIf=\"enabled && onNewItem.observed; else emptyText\"\n [title]=\"'COMMON.BTN_ADD' | translate\"\n (click)=\"onNewClick($event)\"\n >\n <ion-icon slot=\"start\" name=\"add\"></ion-icon>\n <ion-label translate>COMMON.BTN_ADD</ion-label>\n </ion-button>\n\n <!-- Empty (if readonly) -->\n <ng-template #emptyText>\n <ion-text *ngIf=\"!length\" color=\"medium\"><i translate>COMMON.EMPTY_OPTION</i></ion-text>\n </ng-template>\n</ng-container>\n\n<ng-template #listSkeleton>\n <ion-list>\n <ng-container *ngTemplateOutlet=\"itemSkeleton\"></ng-container>\n <ng-container *ngTemplateOutlet=\"itemSkeleton\"></ng-container>\n <ng-container *ngTemplateOutlet=\"itemSkeleton\"></ng-container>\n </ion-list>\n</ng-template>\n\n<ng-template #itemSkeleton>\n <ion-item>\n <ion-label>\n <ion-skeleton-text animated style=\"width: 60%\"></ion-skeleton-text>\n </ion-label>\n </ion-item>\n</ng-template>\n", styles: [":host{--ion-item-background-selected: var(--ion-color-secondary100);--ion-item-color-selected: var(--ion-color-secondary100-contrast)}ion-item.disabled ion-label{color:var(--ion-color-medium-shade, grey)}ion-item{--min-height: 48px;background-color:var(--ion-item-background)}ion-item ion-text,ion-item ion-label{color:var(--ion-item-color)}ion-item .action-buttons{visibility:hidden;display:none}ion-item:hover{height:var(--min-height);--ion-item-background-color: var(--ion-color-light);--ion-item-color: var(--ion-color-light-contrast)}ion-item:hover .action-buttons{margin-top:-1px;visibility:visible;display:block}ion-item.selected{--ion-item-background-color-hover: var(--ion-item-background-selected) !important;--ion-item-color-hover: var(--ion-item-color-selected) !important}\n"], dependencies: [{ kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i2$1.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i2$1.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i2$1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i2$1.IonItem, selector: "ion-item", inputs: ["button", "color", "counter", "counterFormatter", "detail", "detailIcon", "disabled", "download", "fill", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "shape", "target", "type"] }, { kind: "component", type: i2$1.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i2$1.IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: i2$1.IonSkeletonText, selector: "ion-skeleton-text", inputs: ["animated"] }, { kind: "component", type: i2$1.IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "directive", type: i1$1.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }, { kind: "pipe", type: NotEmptyArrayPipe, name: "isNotEmptyArray" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
30662
30662
  }
30663
30663
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: AppListForm, decorators: [{
30664
30664
  type: Component,
30665
- args: [{ selector: 'app-list-form', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *ngIf=\"!loading; else listSkeleton\">\n <!-- List -->\n <ion-list class=\"ion-no-padding\">\n <ng-container *ngFor=\"let itemControl of itemControls; index as i; last as last\">\n <ion-item\n *ngIf=\"itemControl.value; let item\"\n [class.disabled]=\"disabled\"\n tappable\n (click)=\"onItemClick($event, item)\"\n [color]=\"selection.isSelected(item) ? 'secondary100' : undefined\"\n [button]=\"selectionChanges.observers | isNotEmptyArray\"\n >\n <ion-label>{{ displayWith(item) }}</ion-label>\n\n <!-- buttons -->\n <ion-buttons slot=\"end\" *ngIf=\"enabled\" class=\"action-buttons\">\n <ion-button fill=\"clear\" (click)=\"removeAt(i)\">\n <ion-icon slot=\"icon-only\" name=\"trash\"></ion-icon>\n </ion-button>\n\n <ion-button\n *ngFor=\"let button of options.buttons\"\n fill=\"clear\"\n [color]=\"button.color\"\n [class.cdk-visually-hidden]=\"button.disabled | async\"\n (click)=\"onItemButtonClick(button, $event, item, i)\"\n [title]=\"button.title || '' | translate\"\n >\n <ion-icon slot=\"icon-only\" [name]=\"button.icon\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-item>\n </ng-container>\n </ion-list>\n\n <!-- Add button -->\n <ion-button\n color=\"tertiary\"\n fill=\"clear\"\n *ngIf=\"enabled && onNewItem.observers.length; else emptyText\"\n [title]=\"'COMMON.BTN_ADD' | translate\"\n (click)=\"onNewClick($event)\"\n >\n <ion-icon slot=\"start\" name=\"add\"></ion-icon>\n <ion-label translate>COMMON.BTN_ADD</ion-label>\n </ion-button>\n\n <!-- Empty (if readonly) -->\n <ng-template #emptyText>\n <ion-text *ngIf=\"!length\" color=\"medium\"><i translate>COMMON.EMPTY_OPTION</i></ion-text>\n </ng-template>\n</ng-container>\n\n<ng-template #listSkeleton>\n <ion-list>\n <ng-container *ngTemplateOutlet=\"itemSkeleton\"></ng-container>\n <ng-container *ngTemplateOutlet=\"itemSkeleton\"></ng-container>\n <ng-container *ngTemplateOutlet=\"itemSkeleton\"></ng-container>\n </ion-list>\n</ng-template>\n\n<ng-template #itemSkeleton>\n <ion-item>\n <ion-label>\n <ion-skeleton-text animated style=\"width: 60%\"></ion-skeleton-text>\n </ion-label>\n </ion-item>\n</ng-template>\n", styles: [":host{--ion-item-background-selected: var(--ion-color-secondary100);--ion-item-color-selected: var(--ion-color-secondary100-contrast)}ion-item.disabled ion-label{color:var(--ion-color-medium-shade, grey)}ion-item{--min-height: 48px;background-color:var(--ion-item-background)}ion-item ion-text,ion-item ion-label{color:var(--ion-item-color)}ion-item .action-buttons{visibility:hidden;display:none}ion-item:hover{height:var(--min-height);--ion-item-background-color: var(--ion-color-light);--ion-item-color: var(--ion-color-light-contrast)}ion-item:hover .action-buttons{margin-top:-1px;visibility:visible;display:block}ion-item.selected{--ion-item-background-color-hover: var(--ion-item-background-selected) !important;--ion-item-color-hover: var(--ion-item-color-selected) !important}\n"] }]
30665
+ args: [{ selector: 'app-list-form', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *ngIf=\"!loading; else listSkeleton\">\n <!-- List -->\n <ion-list class=\"ion-no-padding\">\n <ng-container *ngFor=\"let itemControl of itemControls; index as i; last as last\">\n <ion-item\n *ngIf=\"itemControl.value; let item\"\n [class.disabled]=\"disabled\"\n tappable\n (click)=\"onItemClick($event, item)\"\n [color]=\"selection.isSelected(item) ? 'secondary100' : undefined\"\n [button]=\"selectionChanges.observers | isNotEmptyArray\"\n >\n <ion-label>{{ displayWith(item) }}</ion-label>\n\n <!-- buttons -->\n <ion-buttons slot=\"end\" *ngIf=\"enabled\" class=\"action-buttons\">\n <ion-button fill=\"clear\" (click)=\"removeAt(i)\">\n <ion-icon slot=\"icon-only\" name=\"trash\"></ion-icon>\n </ion-button>\n\n <ion-button\n *ngFor=\"let button of options.buttons\"\n fill=\"clear\"\n [color]=\"button.color\"\n [class.cdk-visually-hidden]=\"button.disabled | async\"\n (click)=\"onItemButtonClick(button, $event, item, i)\"\n [title]=\"button.title || '' | translate\"\n >\n <ion-icon slot=\"icon-only\" [name]=\"button.icon\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-item>\n </ng-container>\n </ion-list>\n\n <!-- Add button -->\n <ion-button\n color=\"tertiary\"\n fill=\"clear\"\n *ngIf=\"enabled && onNewItem.observed; else emptyText\"\n [title]=\"'COMMON.BTN_ADD' | translate\"\n (click)=\"onNewClick($event)\"\n >\n <ion-icon slot=\"start\" name=\"add\"></ion-icon>\n <ion-label translate>COMMON.BTN_ADD</ion-label>\n </ion-button>\n\n <!-- Empty (if readonly) -->\n <ng-template #emptyText>\n <ion-text *ngIf=\"!length\" color=\"medium\"><i translate>COMMON.EMPTY_OPTION</i></ion-text>\n </ng-template>\n</ng-container>\n\n<ng-template #listSkeleton>\n <ion-list>\n <ng-container *ngTemplateOutlet=\"itemSkeleton\"></ng-container>\n <ng-container *ngTemplateOutlet=\"itemSkeleton\"></ng-container>\n <ng-container *ngTemplateOutlet=\"itemSkeleton\"></ng-container>\n </ion-list>\n</ng-template>\n\n<ng-template #itemSkeleton>\n <ion-item>\n <ion-label>\n <ion-skeleton-text animated style=\"width: 60%\"></ion-skeleton-text>\n </ion-label>\n </ion-item>\n</ng-template>\n", styles: [":host{--ion-item-background-selected: var(--ion-color-secondary100);--ion-item-color-selected: var(--ion-color-secondary100-contrast)}ion-item.disabled ion-label{color:var(--ion-color-medium-shade, grey)}ion-item{--min-height: 48px;background-color:var(--ion-item-background)}ion-item ion-text,ion-item ion-label{color:var(--ion-item-color)}ion-item .action-buttons{visibility:hidden;display:none}ion-item:hover{height:var(--min-height);--ion-item-background-color: var(--ion-color-light);--ion-item-color: var(--ion-color-light-contrast)}ion-item:hover .action-buttons{margin-top:-1px;visibility:visible;display:block}ion-item.selected{--ion-item-background-color-hover: var(--ion-item-background-selected) !important;--ion-item-color-hover: var(--ion-item-color-selected) !important}\n"] }]
30666
30666
  }], ctorParameters: () => [{ type: i0.Injector }, { type: i1$2.UntypedFormBuilder }, { type: i2.DateAdapter }, { type: LocalSettingsService }, { type: i0.ChangeDetectorRef }, { type: i1$2.FormGroupDirective, decorators: [{
30667
30667
  type: Optional
30668
30668
  }] }], propDecorators: { formArrayName: [{
@@ -34670,7 +34670,7 @@ class AppAsyncTable {
34670
34670
  }
34671
34671
  async cancel(event, opts) {
34672
34672
  // Check confirmation
34673
- if ((!opts || opts.interactive !== false) && this.dirty && (this.confirmBeforeCancel || this.onBeforeCancelRows.observers.length > 0)) {
34673
+ if ((!opts || opts.interactive !== false) && this.dirty && (this.confirmBeforeCancel || this.onBeforeCancelRows.observed)) {
34674
34674
  event?.stopPropagation();
34675
34675
  if (!(await this.canCancelRows())) {
34676
34676
  return;
@@ -35056,7 +35056,7 @@ class AppAsyncTable {
35056
35056
  }
35057
35057
  async canDeleteRows(rows, opts) {
35058
35058
  // Check using emitter
35059
- if (this.onBeforeDeleteRows.observers.length > 0) {
35059
+ if (this.onBeforeDeleteRows.observed) {
35060
35060
  try {
35061
35061
  const canDelete = await emitPromiseEvent(this.onBeforeDeleteRows, 'canDelete', {
35062
35062
  detail: { rows },
@@ -35083,7 +35083,7 @@ class AppAsyncTable {
35083
35083
  if (isEmptyArray(rows))
35084
35084
  return true; // No dirty: OK
35085
35085
  // Check using emitter
35086
- if (this.onBeforeCancelRows.observers.length > 0) {
35086
+ if (this.onBeforeCancelRows.observed) {
35087
35087
  try {
35088
35088
  const isCancel = await emitPromiseEvent(this.onBeforeCancelRows, 'canCancel', {
35089
35089
  detail: { rows },
@@ -35126,7 +35126,7 @@ class AppAsyncTable {
35126
35126
  // Default behavior
35127
35127
  let confirmed = true;
35128
35128
  if (save) {
35129
- if (this.onBeforeSave.observers.length > 0) {
35129
+ if (this.onBeforeSave.observed) {
35130
35130
  // Ask confirmation
35131
35131
  try {
35132
35132
  const res = await emitPromiseEvent(this.onBeforeSave, 'beforeSave', {
@@ -35167,7 +35167,7 @@ class AppAsyncTable {
35167
35167
  if (this.debug && this.dirty) {
35168
35168
  console.warn('[table] Opening row details, but table has unsaved changes!');
35169
35169
  }
35170
- if (this.onOpenRow.observers.length) {
35170
+ if (this.onOpenRow.observed) {
35171
35171
  this.onOpenRow.emit(row);
35172
35172
  return true;
35173
35173
  }
@@ -35186,7 +35186,7 @@ class AppAsyncTable {
35186
35186
  async openNewRowDetail(event) {
35187
35187
  if (!this.allowRowDetail)
35188
35188
  return false;
35189
- if (this.onNewRow.observers.length > 0) {
35189
+ if (this.onNewRow.observed) {
35190
35190
  this.onNewRow.emit(event);
35191
35191
  return true;
35192
35192
  }
@@ -35489,7 +35489,7 @@ class AppAsyncTable {
35489
35489
  throw new Error('Row cannot be canceling, but only deleting');
35490
35490
  const confirmed = !opts || opts.interactive !== false;
35491
35491
  // Ask user confirmation, if cancel
35492
- if (!confirmed && row.dirty && (this.confirmBeforeCancel || this.onBeforeCancelRows.observers.length > 0)) {
35492
+ if (!confirmed && row.dirty && (this.confirmBeforeCancel || this.onBeforeCancelRows.observed)) {
35493
35493
  event?.stopPropagation();
35494
35494
  if (!(await this.canCancelRows([row], opts))) {
35495
35495
  return;