@decaf-ts/for-angular 0.0.73 → 0.0.76
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/decaf-ts-for-angular.mjs +76 -72
- package/fesm2022/decaf-ts-for-angular.mjs.map +1 -1
- package/index.d.ts +35 -21
- package/package.json +1 -1
|
@@ -12,7 +12,7 @@ import { TranslateModule, TranslatePipe, TranslateParser, provideTranslateServic
|
|
|
12
12
|
import { Logging, LoggedClass } from '@decaf-ts/logging';
|
|
13
13
|
import { Repository, OrderDirection, Condition } from '@decaf-ts/core';
|
|
14
14
|
import { uses, Metadata, apply, metadata } from '@decaf-ts/decoration';
|
|
15
|
-
import { AnimationController, provideIonicAngular, IonIcon, IonButton, IonModal, IonSpinner, IonButtons, IonContent, IonHeader, IonTitle, IonToolbar,
|
|
15
|
+
import { AnimationController, provideIonicAngular, LoadingController, IonIcon, IonButton, IonModal, IonSpinner, IonButtons, IonContent, IonHeader, IonTitle, IonToolbar, IonInput, IonItem, IonCheckbox, IonRadioGroup, IonRadio, IonSelect, IonSelectOption, IonLabel, IonBadge, IonText, IonTextarea, IonCard, IonCardHeader, IonCardContent, IonCardTitle, IonCardSubtitle, IonList, IonReorder, IonReorderGroup, IonSearchbar, IonChip, IonRefresher, IonThumbnail, IonSkeletonText, IonRefresherContent, IonInfiniteScroll, IonInfiniteScrollContent, IonListHeader, IonItemSliding, IonItemOptions, IonItemOption, IonPopover, NavController } from '@ionic/angular/standalone';
|
|
16
16
|
import { faker } from '@faker-js/faker';
|
|
17
17
|
import { Router, NavigationStart, ActivatedRoute, NavigationEnd } from '@angular/router';
|
|
18
18
|
import { forkJoin, Subject, BehaviorSubject, fromEvent, of, merge, Observable, timer, firstValueFrom, debounceTime, takeUntil as takeUntil$1, shareReplay as shareReplay$1 } from 'rxjs';
|
|
@@ -65,6 +65,10 @@ const ActionRoles = {
|
|
|
65
65
|
submit: 'submit',
|
|
66
66
|
clear: 'clear',
|
|
67
67
|
back: 'back',
|
|
68
|
+
[OperationKeys.CREATE]: OperationKeys.CREATE,
|
|
69
|
+
[OperationKeys.READ]: OperationKeys.READ,
|
|
70
|
+
[OperationKeys.UPDATE]: OperationKeys.UPDATE,
|
|
71
|
+
[OperationKeys.DELETE]: OperationKeys.DELETE,
|
|
68
72
|
};
|
|
69
73
|
const WindowColorSchemes = {
|
|
70
74
|
light: 'light',
|
|
@@ -3908,6 +3912,17 @@ class NgxComponentDirective extends DecafComponent {
|
|
|
3908
3912
|
* @type {Location}
|
|
3909
3913
|
*/
|
|
3910
3914
|
this.location = inject(Location);
|
|
3915
|
+
/**
|
|
3916
|
+
* @description Ionic loading overlay manager available to derived components.
|
|
3917
|
+
* @summary Provides convenient access to Ionic's LoadingController, enabling directive
|
|
3918
|
+
* subclasses to create, present, and dismiss loading overlays without wiring the
|
|
3919
|
+
* service themselves. Use this helper to surface async progress indicators tied to
|
|
3920
|
+
* CRUD operations, navigation, or any long-running UI task.
|
|
3921
|
+
* @type {LoadingController}
|
|
3922
|
+
* @returns {OverlayBaseController<LoadingOptions, HTMLIonLoadingElement>}
|
|
3923
|
+
* @memberOf module:lib/engine/NgxComponentDirective
|
|
3924
|
+
*/
|
|
3925
|
+
this.loadingController = inject(LoadingController);
|
|
3911
3926
|
/**
|
|
3912
3927
|
* @description Flag indicating if the component is rendered as a child of a modal dialog.
|
|
3913
3928
|
* @summary Determines whether this component instance is being displayed within a modal
|
|
@@ -4122,9 +4137,9 @@ class NgxComponentDirective extends DecafComponent {
|
|
|
4122
4137
|
* @memberOf ListComponent
|
|
4123
4138
|
*/
|
|
4124
4139
|
async handleRepositoryRefresh(...args) {
|
|
4125
|
-
const [
|
|
4126
|
-
if (
|
|
4127
|
-
return this.handleObserveEvent(
|
|
4140
|
+
const [modelInstance, event, uid] = args;
|
|
4141
|
+
if ([OperationKeys.CREATE].includes(event))
|
|
4142
|
+
return this.handleObserveEvent(modelInstance, event, uid);
|
|
4128
4143
|
return this.repositoryObserverSubject.next(args);
|
|
4129
4144
|
}
|
|
4130
4145
|
async handleObserveEvent(...args) {
|
|
@@ -5230,6 +5245,9 @@ class ModelRendererComponent extends NgxRenderableComponentDirective {
|
|
|
5230
5245
|
if (this.output?.inputs)
|
|
5231
5246
|
this.rendererId = sf(AngularEngineKeys.RENDERED_ID, this.output.inputs['rendererId']);
|
|
5232
5247
|
this.instance = this.output?.component;
|
|
5248
|
+
const { operation } = this.globals || {};
|
|
5249
|
+
if (operation)
|
|
5250
|
+
this.operation = operation;
|
|
5233
5251
|
this.subscribeEvents();
|
|
5234
5252
|
}
|
|
5235
5253
|
}
|
|
@@ -6091,7 +6109,6 @@ let CrudFieldComponent = class CrudFieldComponent extends NgxFormFieldDirective
|
|
|
6091
6109
|
* @memberOf CrudFieldComponent
|
|
6092
6110
|
*/
|
|
6093
6111
|
this.translatable = true;
|
|
6094
|
-
this.loadingController = inject(LoadingController);
|
|
6095
6112
|
addIcons({ chevronDownOutline, chevronUpOutline });
|
|
6096
6113
|
}
|
|
6097
6114
|
/**
|
|
@@ -6105,7 +6122,6 @@ let CrudFieldComponent = class CrudFieldComponent extends NgxFormFieldDirective
|
|
|
6105
6122
|
* @memberOf CrudFieldComponent
|
|
6106
6123
|
*/
|
|
6107
6124
|
async ngOnInit() {
|
|
6108
|
-
this.options = await this.getOptions();
|
|
6109
6125
|
if (Array.isArray(this.hidden) && !this.hidden.includes(this.operation))
|
|
6110
6126
|
this.hidden = false;
|
|
6111
6127
|
if (this.readonly && typeof this.readonly === Function.name.toLocaleLowerCase())
|
|
@@ -6117,6 +6133,7 @@ let CrudFieldComponent = class CrudFieldComponent extends NgxFormFieldDirective
|
|
|
6117
6133
|
this.formGroup = undefined;
|
|
6118
6134
|
}
|
|
6119
6135
|
else {
|
|
6136
|
+
this.options = await this.getOptions();
|
|
6120
6137
|
if (!this.parentForm && this.formGroup instanceof FormGroup || this.formGroup instanceof FormArray)
|
|
6121
6138
|
this.parentForm = (this.formGroup.root || this.formControl.root);
|
|
6122
6139
|
if (this.multiple) {
|
|
@@ -6147,11 +6164,11 @@ let CrudFieldComponent = class CrudFieldComponent extends NgxFormFieldDirective
|
|
|
6147
6164
|
return [];
|
|
6148
6165
|
if (this.options instanceof Function) {
|
|
6149
6166
|
if (this.options.name === 'options')
|
|
6150
|
-
this.options = this.options();
|
|
6167
|
+
this.options = await this.options();
|
|
6151
6168
|
const fnName = this.options?.name;
|
|
6152
6169
|
if (fnName) {
|
|
6153
6170
|
if (fnName === 'function') {
|
|
6154
|
-
this.options = this.options();
|
|
6171
|
+
this.options = await this.options();
|
|
6155
6172
|
}
|
|
6156
6173
|
else {
|
|
6157
6174
|
const repo = getModelAndRepository(this.options?.['name'], this);
|
|
@@ -6580,14 +6597,8 @@ class NgxFormDirective extends NgxParentComponentDirective {
|
|
|
6580
6597
|
* @returns {void}
|
|
6581
6598
|
*/
|
|
6582
6599
|
handleReset() {
|
|
6583
|
-
if (this.isModalChild)
|
|
6584
|
-
this.
|
|
6585
|
-
data: null,
|
|
6586
|
-
component: this.componentName,
|
|
6587
|
-
name: ActionRoles.cancel,
|
|
6588
|
-
});
|
|
6589
|
-
return;
|
|
6590
|
-
}
|
|
6600
|
+
if (this.isModalChild)
|
|
6601
|
+
return this.submitEventEmit(null, ActionRoles.cancel, this.componentName);
|
|
6591
6602
|
if (![OperationKeys.DELETE, OperationKeys.READ].includes(this.operation) && this.allowClear)
|
|
6592
6603
|
return NgxFormService.reset(this.formGroup);
|
|
6593
6604
|
this.location.back();
|
|
@@ -6605,14 +6616,17 @@ class NgxFormDirective extends NgxParentComponentDirective {
|
|
|
6605
6616
|
return false;
|
|
6606
6617
|
}
|
|
6607
6618
|
const data = NgxFormService.getFormData(this.formGroup);
|
|
6608
|
-
if (Object.keys(data).length > 0)
|
|
6609
|
-
this.
|
|
6610
|
-
|
|
6611
|
-
|
|
6612
|
-
|
|
6613
|
-
|
|
6614
|
-
|
|
6615
|
-
|
|
6619
|
+
if (Object.keys(data).length > 0)
|
|
6620
|
+
return this.submitEventEmit(data, eventName, componentName, this.handlers);
|
|
6621
|
+
}
|
|
6622
|
+
submitEventEmit(data, componentName, eventName, handlers) {
|
|
6623
|
+
this.submitEvent.emit({
|
|
6624
|
+
data,
|
|
6625
|
+
component: componentName || this.componentName,
|
|
6626
|
+
name: eventName || ComponentEventNames.SUBMIT,
|
|
6627
|
+
role: this.operation,
|
|
6628
|
+
handlers: { ...(this.handlers || {}), ...(handlers || {}) },
|
|
6629
|
+
});
|
|
6616
6630
|
}
|
|
6617
6631
|
/**
|
|
6618
6632
|
* @description Updates the active form group and children for the specified page.
|
|
@@ -7110,14 +7124,10 @@ let CrudFormComponent = class CrudFormComponent extends NgxFormDirective {
|
|
|
7110
7124
|
* @memberOf CrudFormComponent
|
|
7111
7125
|
*/
|
|
7112
7126
|
handleDelete() {
|
|
7113
|
-
this.
|
|
7114
|
-
data: this.model,
|
|
7115
|
-
component: 'CrudFormComponent',
|
|
7116
|
-
name: ComponentEventNames.SUBMIT,
|
|
7117
|
-
});
|
|
7127
|
+
super.submitEventEmit(this.model, ComponentEventNames.SUBMIT, 'CrudFormComponent', this.handlers);
|
|
7118
7128
|
}
|
|
7119
7129
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CrudFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
7120
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: CrudFormComponent, isStandalone: true, selector: "ngx-decaf-crud-form", host: { properties: { "attr.id": "uid" } }, usesInheritance: true, ngImport: i0, template: "@if (operation !== 'read' && operation !== 'delete') {\n <form\n [class]=\"'dcf-form-grid ' + operation\" #component\n [id]=\"rendererId\"\n [formGroup]=\"formGroup\"\n (ngSubmit)=\"submit($event)\"\n novalidate\n [target]=\"target\">\n @if (!children?.length) {\n <ng-content #formContent></ng-content>\n } @else {\n <ngx-decaf-layout\n [className]=\"'dcf-crud-form-grid dcf-grid-nested '\"\n [children]=\"children || []\"\n [parentForm]=\"formGroup || parentForm\"\n [operation]=\"operation\"\n [cardType]=\"cardType ?? 'blank'\"\n [match]=\"match ?? false\"\n [gap]=\"'small'\"\n [flexMode]=\"props.flexMode || false\"\n [rows]=\"rows\"\n [borders]=\"borders ?? false\"\n [breakpoint]=\"breakpoint ?? 'large'\"\n [cols]=\"cols\" />\n }\n @if (initialized) {\n <div class=\"dcf-buttons-grid dcf-grid dcf-grid-small dcf-flex dcf-flex-right\">\n @if (!action) {\n <div>\n <ion-button fill=\"clear\" (click)=\"handleReset()\">\n @if (options.buttons.clear?.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.clear?.iconSlot\" [name]=\"options.buttons.clear?.icon\"></ion-icon>\n }\n {{ locale + '.' + (allowClear ? options.buttons.clear?.text : 'back') | translate }}\n </ion-button>\n </div>\n }\n <div>\n <ion-button type=\"submit\" [expand]=\"action ? 'block' : 'default'\">\n @if (options.buttons.submit.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.submit.iconSlot\" [name]=\"options.buttons.submit.icon\"></ion-icon>\n }\n {{ action ? action : (locale + '.' + options.buttons.submit.text) | translate }}\n </ion-button>\n </div>\n\n </div>\n }\n\n </form>\n} @else {\n <section #component [id]=\"uid\">\n <ngx-decaf-layout\n [className]=\"''\"\n [children]=\"children || []\"\n [operation]=\"operation\"\n [cardType]=\"cardType ?? 'blank'\"\n [match]=\"match ?? false\"\n [gap]=\"'small'\"\n [flexMode]=\"props.flexMode || false\"\n [rows]=\"rows\"\n [borders]=\"borders ?? false\"\n [breakpoint]=\"breakpoint ?? 'large'\"\n [cols]=\"cols\" />\n </section>\n\n <section [class]=\"'dcf-buttons-grid dcf-grid dcf-grid-small dcf-flex dcf-flex-left ' + operation\" [id]=\"uid\">\n @if (
|
|
7130
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: CrudFormComponent, isStandalone: true, selector: "ngx-decaf-crud-form", host: { properties: { "attr.id": "uid" } }, usesInheritance: true, ngImport: i0, template: "@if (operation !== 'read' && operation !== 'delete') {\n <form\n [class]=\"'dcf-form-grid ' + operation\" #component\n [id]=\"rendererId\"\n [formGroup]=\"formGroup\"\n (ngSubmit)=\"submit($event)\"\n novalidate\n [target]=\"target\">\n @if (!children?.length) {\n <ng-content #formContent></ng-content>\n } @else {\n <ngx-decaf-layout\n [className]=\"'dcf-crud-form-grid dcf-grid-nested '\"\n [children]=\"children || []\"\n [parentForm]=\"formGroup || parentForm\"\n [operation]=\"operation\"\n [cardType]=\"cardType ?? 'blank'\"\n [match]=\"match ?? false\"\n [gap]=\"'small'\"\n [flexMode]=\"props.flexMode || false\"\n [rows]=\"rows\"\n [borders]=\"borders ?? false\"\n [breakpoint]=\"breakpoint ?? 'large'\"\n [cols]=\"cols\" />\n }\n @if (initialized) {\n <div class=\"dcf-buttons-grid dcf-grid dcf-grid-small dcf-flex dcf-flex-right\">\n @if (!action) {\n <div>\n <ion-button fill=\"clear\" (click)=\"handleReset()\">\n @if (options.buttons.clear?.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.clear?.iconSlot\" [name]=\"options.buttons.clear?.icon\"></ion-icon>\n }\n {{ locale + '.' + (allowClear ? options.buttons.clear?.text : 'back') | translate }}\n </ion-button>\n </div>\n }\n <div>\n <ion-button type=\"submit\" [expand]=\"action ? 'block' : 'default'\">\n @if (options.buttons.submit.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.submit.iconSlot\" [name]=\"options.buttons.submit.icon\"></ion-icon>\n }\n {{ action ? action : (locale + '.' + options.buttons.submit.text) | translate }}\n </ion-button>\n </div>\n\n </div>\n }\n\n </form>\n} @else {\n <section #component [id]=\"uid\">\n <ngx-decaf-layout\n [className]=\"''\"\n [children]=\"children || []\"\n [operation]=\"operation\"\n [cardType]=\"cardType ?? 'blank'\"\n [match]=\"match ?? false\"\n [gap]=\"'small'\"\n [flexMode]=\"props.flexMode || false\"\n [rows]=\"rows\"\n [borders]=\"borders ?? false\"\n [breakpoint]=\"breakpoint ?? 'large'\"\n [cols]=\"cols\" />\n </section>\n\n <section [class]=\"'dcf-buttons-grid dcf-grid dcf-grid-small dcf-flex dcf-flex-left ' + operation\" [id]=\"uid\">\n @if ([OperationKeys.READ, OperationKeys.DELETE].includes(operation) && modelId) {\n <div>\n <ion-button\n (click)=\"handleDelete()\"\n color=\"danger\"\n type=\"button\">\n @if (options.buttons.submit.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.submit.iconSlot\" [name]=\"options.buttons.submit.icon\"></ion-icon>\n }\n {{locale + '.delete' | translate}}\n </ion-button>\n </div>\n }\n @if (operation === OperationKeys.CREATE || operation === OperationKeys.UPDATE) {\n <div>\n <ion-button\n type=\"submit\">\n @if (options.buttons.submit.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.submit.iconSlot\" [name]=\"options.buttons.submit.icon\"></ion-icon>\n }\n {{ action ? action : (locale + '.' + options.buttons.submit.text) | translate }}\n </ion-button>\n </div>\n }\n <div>\n <ion-button fill=\"clear\" (click)=\"handleReset()\">\n @if (options.buttons.clear?.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.clear?.iconSlot\" [name]=\"options.buttons.clear?.icon\"></ion-icon>\n }\n {{ [OperationKeys.DELETE, OperationKeys.READ, OperationKeys.UPDATE].includes(operation) ? (locale + '.back' | translate) : options.buttons.clear?.text}}\n </ion-button>\n </div>\n </section>\n}\n\n", styles: [".dcf-buttons-grid{margin-top:var(--dcf-margin-medium);margin-bottom:var(--dcf-margin)}@media (min-width: 577px){.dcf-buttons-grid.dcf-flex.read,.dcf-buttons-grid.dcf-flex.delete{flex-direction:row-reverse}}@media (max-width: 576px){.dcf-buttons-grid.dcf-flex{flex-direction:column-reverse}.dcf-buttons-grid.dcf-flex>div{width:100%}.dcf-buttons-grid.dcf-flex>div+div{margin-top:1rem}.dcf-buttons-grid.dcf-flex ion-button{width:100%}}.dcf-form-grid.create,.dcf-form-grid.update{margin-top:var(--dcf-margin-small)}.dcf-form-grid .dcf-form-item{margin-top:0!important}.dcf-form-grid.read .dcf-form-item{margin-bottom:var(--dcf-margin-small)}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: LayoutComponent, selector: "ngx-decaf-layout", inputs: ["gap", "grid", "flexMode", "rowCard", "maxColsLength"] }, { kind: "component", type: 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: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
7121
7131
|
};
|
|
7122
7132
|
CrudFormComponent = __decorate([
|
|
7123
7133
|
Dynamic(),
|
|
@@ -7125,7 +7135,7 @@ CrudFormComponent = __decorate([
|
|
|
7125
7135
|
], CrudFormComponent);
|
|
7126
7136
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CrudFormComponent, decorators: [{
|
|
7127
7137
|
type: Component,
|
|
7128
|
-
args: [{ standalone: true, selector: 'ngx-decaf-crud-form', imports: [TranslatePipe, ReactiveFormsModule, LayoutComponent, IonButton, IonIcon], host: { '[attr.id]': 'uid' }, template: "@if (operation !== 'read' && operation !== 'delete') {\n <form\n [class]=\"'dcf-form-grid ' + operation\" #component\n [id]=\"rendererId\"\n [formGroup]=\"formGroup\"\n (ngSubmit)=\"submit($event)\"\n novalidate\n [target]=\"target\">\n @if (!children?.length) {\n <ng-content #formContent></ng-content>\n } @else {\n <ngx-decaf-layout\n [className]=\"'dcf-crud-form-grid dcf-grid-nested '\"\n [children]=\"children || []\"\n [parentForm]=\"formGroup || parentForm\"\n [operation]=\"operation\"\n [cardType]=\"cardType ?? 'blank'\"\n [match]=\"match ?? false\"\n [gap]=\"'small'\"\n [flexMode]=\"props.flexMode || false\"\n [rows]=\"rows\"\n [borders]=\"borders ?? false\"\n [breakpoint]=\"breakpoint ?? 'large'\"\n [cols]=\"cols\" />\n }\n @if (initialized) {\n <div class=\"dcf-buttons-grid dcf-grid dcf-grid-small dcf-flex dcf-flex-right\">\n @if (!action) {\n <div>\n <ion-button fill=\"clear\" (click)=\"handleReset()\">\n @if (options.buttons.clear?.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.clear?.iconSlot\" [name]=\"options.buttons.clear?.icon\"></ion-icon>\n }\n {{ locale + '.' + (allowClear ? options.buttons.clear?.text : 'back') | translate }}\n </ion-button>\n </div>\n }\n <div>\n <ion-button type=\"submit\" [expand]=\"action ? 'block' : 'default'\">\n @if (options.buttons.submit.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.submit.iconSlot\" [name]=\"options.buttons.submit.icon\"></ion-icon>\n }\n {{ action ? action : (locale + '.' + options.buttons.submit.text) | translate }}\n </ion-button>\n </div>\n\n </div>\n }\n\n </form>\n} @else {\n <section #component [id]=\"uid\">\n <ngx-decaf-layout\n [className]=\"''\"\n [children]=\"children || []\"\n [operation]=\"operation\"\n [cardType]=\"cardType ?? 'blank'\"\n [match]=\"match ?? false\"\n [gap]=\"'small'\"\n [flexMode]=\"props.flexMode || false\"\n [rows]=\"rows\"\n [borders]=\"borders ?? false\"\n [breakpoint]=\"breakpoint ?? 'large'\"\n [cols]=\"cols\" />\n </section>\n\n <section [class]=\"'dcf-buttons-grid dcf-grid dcf-grid-small dcf-flex dcf-flex-left ' + operation\" [id]=\"uid\">\n @if (
|
|
7138
|
+
args: [{ standalone: true, selector: 'ngx-decaf-crud-form', imports: [TranslatePipe, ReactiveFormsModule, LayoutComponent, IonButton, IonIcon], host: { '[attr.id]': 'uid' }, template: "@if (operation !== 'read' && operation !== 'delete') {\n <form\n [class]=\"'dcf-form-grid ' + operation\" #component\n [id]=\"rendererId\"\n [formGroup]=\"formGroup\"\n (ngSubmit)=\"submit($event)\"\n novalidate\n [target]=\"target\">\n @if (!children?.length) {\n <ng-content #formContent></ng-content>\n } @else {\n <ngx-decaf-layout\n [className]=\"'dcf-crud-form-grid dcf-grid-nested '\"\n [children]=\"children || []\"\n [parentForm]=\"formGroup || parentForm\"\n [operation]=\"operation\"\n [cardType]=\"cardType ?? 'blank'\"\n [match]=\"match ?? false\"\n [gap]=\"'small'\"\n [flexMode]=\"props.flexMode || false\"\n [rows]=\"rows\"\n [borders]=\"borders ?? false\"\n [breakpoint]=\"breakpoint ?? 'large'\"\n [cols]=\"cols\" />\n }\n @if (initialized) {\n <div class=\"dcf-buttons-grid dcf-grid dcf-grid-small dcf-flex dcf-flex-right\">\n @if (!action) {\n <div>\n <ion-button fill=\"clear\" (click)=\"handleReset()\">\n @if (options.buttons.clear?.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.clear?.iconSlot\" [name]=\"options.buttons.clear?.icon\"></ion-icon>\n }\n {{ locale + '.' + (allowClear ? options.buttons.clear?.text : 'back') | translate }}\n </ion-button>\n </div>\n }\n <div>\n <ion-button type=\"submit\" [expand]=\"action ? 'block' : 'default'\">\n @if (options.buttons.submit.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.submit.iconSlot\" [name]=\"options.buttons.submit.icon\"></ion-icon>\n }\n {{ action ? action : (locale + '.' + options.buttons.submit.text) | translate }}\n </ion-button>\n </div>\n\n </div>\n }\n\n </form>\n} @else {\n <section #component [id]=\"uid\">\n <ngx-decaf-layout\n [className]=\"''\"\n [children]=\"children || []\"\n [operation]=\"operation\"\n [cardType]=\"cardType ?? 'blank'\"\n [match]=\"match ?? false\"\n [gap]=\"'small'\"\n [flexMode]=\"props.flexMode || false\"\n [rows]=\"rows\"\n [borders]=\"borders ?? false\"\n [breakpoint]=\"breakpoint ?? 'large'\"\n [cols]=\"cols\" />\n </section>\n\n <section [class]=\"'dcf-buttons-grid dcf-grid dcf-grid-small dcf-flex dcf-flex-left ' + operation\" [id]=\"uid\">\n @if ([OperationKeys.READ, OperationKeys.DELETE].includes(operation) && modelId) {\n <div>\n <ion-button\n (click)=\"handleDelete()\"\n color=\"danger\"\n type=\"button\">\n @if (options.buttons.submit.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.submit.iconSlot\" [name]=\"options.buttons.submit.icon\"></ion-icon>\n }\n {{locale + '.delete' | translate}}\n </ion-button>\n </div>\n }\n @if (operation === OperationKeys.CREATE || operation === OperationKeys.UPDATE) {\n <div>\n <ion-button\n type=\"submit\">\n @if (options.buttons.submit.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.submit.iconSlot\" [name]=\"options.buttons.submit.icon\"></ion-icon>\n }\n {{ action ? action : (locale + '.' + options.buttons.submit.text) | translate }}\n </ion-button>\n </div>\n }\n <div>\n <ion-button fill=\"clear\" (click)=\"handleReset()\">\n @if (options.buttons.clear?.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.clear?.iconSlot\" [name]=\"options.buttons.clear?.icon\"></ion-icon>\n }\n {{ [OperationKeys.DELETE, OperationKeys.READ, OperationKeys.UPDATE].includes(operation) ? (locale + '.back' | translate) : options.buttons.clear?.text}}\n </ion-button>\n </div>\n </section>\n}\n\n", styles: [".dcf-buttons-grid{margin-top:var(--dcf-margin-medium);margin-bottom:var(--dcf-margin)}@media (min-width: 577px){.dcf-buttons-grid.dcf-flex.read,.dcf-buttons-grid.dcf-flex.delete{flex-direction:row-reverse}}@media (max-width: 576px){.dcf-buttons-grid.dcf-flex{flex-direction:column-reverse}.dcf-buttons-grid.dcf-flex>div{width:100%}.dcf-buttons-grid.dcf-flex>div+div{margin-top:1rem}.dcf-buttons-grid.dcf-flex ion-button{width:100%}}.dcf-form-grid.create,.dcf-form-grid.update{margin-top:var(--dcf-margin-small)}.dcf-form-grid .dcf-form-item{margin-top:0!important}.dcf-form-grid.read .dcf-form-item{margin-bottom:var(--dcf-margin-small)}\n"] }]
|
|
7129
7139
|
}], ctorParameters: () => [] });
|
|
7130
7140
|
|
|
7131
7141
|
/**
|
|
@@ -10073,7 +10083,7 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
|
|
|
10073
10083
|
.subscribe((event) => this.clickEventEmit(event));
|
|
10074
10084
|
this.repositoryObserverSubject
|
|
10075
10085
|
.pipe(debounceTime(100), shareReplay$1(1), takeUntil$1(this.destroySubscriptions$))
|
|
10076
|
-
.subscribe(([
|
|
10086
|
+
.subscribe(([modelInstance, event, uid]) => this.handleObserveEvent(modelInstance, event, uid));
|
|
10077
10087
|
this.limit = Number(this.limit);
|
|
10078
10088
|
this.start = Number(this.start);
|
|
10079
10089
|
this.enableFilter = stringToBoolean(this.enableFilter);
|
|
@@ -10143,14 +10153,23 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
|
|
|
10143
10153
|
* @returns {KeyValue} A mapper object that contains string values mapped to the
|
|
10144
10154
|
* component's public keys.
|
|
10145
10155
|
*/
|
|
10146
|
-
|
|
10156
|
+
async getMapper() {
|
|
10147
10157
|
this.mapper = { ...this.mapper, ...{ uid: this.pk } };
|
|
10148
|
-
|
|
10149
|
-
|
|
10150
|
-
if (typeof
|
|
10151
|
-
|
|
10152
|
-
|
|
10153
|
-
|
|
10158
|
+
const mapper = {};
|
|
10159
|
+
for (const [key, value] of Object.entries(this.mapper)) {
|
|
10160
|
+
if (typeof value === Primitives.STRING) {
|
|
10161
|
+
mapper[key] = value;
|
|
10162
|
+
continue;
|
|
10163
|
+
}
|
|
10164
|
+
const mapperFn = value?.['valueParserFn'] || undefined;
|
|
10165
|
+
if (typeof mapperFn === 'function') {
|
|
10166
|
+
const value = await mapperFn(key, this);
|
|
10167
|
+
if (typeof value === Primitives.STRING) {
|
|
10168
|
+
mapper[value] = key;
|
|
10169
|
+
}
|
|
10170
|
+
}
|
|
10171
|
+
}
|
|
10172
|
+
return mapper;
|
|
10154
10173
|
}
|
|
10155
10174
|
/**
|
|
10156
10175
|
* @description Refreshes the list data from the configured source.
|
|
@@ -10246,13 +10265,13 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
|
|
|
10246
10265
|
* the appropriate list operations. This includes adding new items, updating existing
|
|
10247
10266
|
* ones, or removing deleted items from the list display.
|
|
10248
10267
|
*
|
|
10249
|
-
* @param {
|
|
10268
|
+
* @param {UIFunctionLike} clazz - The model instance that changed
|
|
10250
10269
|
* @param {OperationKeys} event - The type of operation (CREATE, UPDATE, DELETE)
|
|
10251
10270
|
* @param {string | number} uid - The unique identifier of the affected item
|
|
10252
10271
|
* @returns {Promise<void>}
|
|
10253
10272
|
* @memberOf ListComponent
|
|
10254
10273
|
*/
|
|
10255
|
-
async handleObserveEvent(
|
|
10274
|
+
async handleObserveEvent(clazz, event, uid) {
|
|
10256
10275
|
if (event === OperationKeys.CREATE) {
|
|
10257
10276
|
if (uid) {
|
|
10258
10277
|
await this.handleCreate(uid);
|
|
@@ -10296,7 +10315,7 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
|
|
|
10296
10315
|
*/
|
|
10297
10316
|
async handleCreate(uid) {
|
|
10298
10317
|
const result = await this._repository?.read(uid);
|
|
10299
|
-
const item = this.mapResults([result])[0];
|
|
10318
|
+
const item = (await this.mapResults([result]))[0];
|
|
10300
10319
|
this.items = this.data = [item, ...(this.items || [])];
|
|
10301
10320
|
}
|
|
10302
10321
|
/**
|
|
@@ -10512,8 +10531,7 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
|
|
|
10512
10531
|
*/
|
|
10513
10532
|
parseSearchResults(results, search) {
|
|
10514
10533
|
const filtered = results.filter((item) => Object.values(item).some((v) => {
|
|
10515
|
-
if (v
|
|
10516
|
-
.toString()
|
|
10534
|
+
if (`${v}`
|
|
10517
10535
|
.toLowerCase()
|
|
10518
10536
|
.includes(search?.toLowerCase()))
|
|
10519
10537
|
return v;
|
|
@@ -10596,7 +10614,11 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
|
|
|
10596
10614
|
async getFromModel(force = false) {
|
|
10597
10615
|
let data = [...(this.data || [])];
|
|
10598
10616
|
let request = [];
|
|
10599
|
-
|
|
10617
|
+
if (!this.repositoryObserver) {
|
|
10618
|
+
this.repositoryObserver = {
|
|
10619
|
+
refresh: async (...args) => this.handleRepositoryRefresh(...args),
|
|
10620
|
+
};
|
|
10621
|
+
}
|
|
10600
10622
|
if (!this._repository) {
|
|
10601
10623
|
this._repository = this.repository;
|
|
10602
10624
|
try {
|
|
@@ -10783,7 +10805,7 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
|
|
|
10783
10805
|
this.getMoreData(result?.length || 0);
|
|
10784
10806
|
}
|
|
10785
10807
|
return Object.keys(this.mapper || {}).length
|
|
10786
|
-
? this.mapResults(result)
|
|
10808
|
+
? await this.mapResults(result)
|
|
10787
10809
|
: result;
|
|
10788
10810
|
}
|
|
10789
10811
|
/**
|
|
@@ -10871,11 +10893,10 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
|
|
|
10871
10893
|
*
|
|
10872
10894
|
* @memberOf ListComponent
|
|
10873
10895
|
*/
|
|
10874
|
-
mapResults(data) {
|
|
10896
|
+
async mapResults(data) {
|
|
10875
10897
|
if (!data || !data.length)
|
|
10876
10898
|
return [];
|
|
10877
|
-
|
|
10878
|
-
this.mapper = this._mapper;
|
|
10899
|
+
this.mapper = await this.getMapper();
|
|
10879
10900
|
const props = Object.assign({
|
|
10880
10901
|
operations: this.operations,
|
|
10881
10902
|
route: this.route,
|
|
@@ -11621,12 +11642,7 @@ let SteppedFormComponent = class SteppedFormComponent extends NgxFormDirective {
|
|
|
11621
11642
|
if (isValid) {
|
|
11622
11643
|
const rootForm = this.formGroup?.root || this.formGroup;
|
|
11623
11644
|
const data = Object.assign({}, ...Object.values(NgxFormService.getFormData(rootForm)));
|
|
11624
|
-
this.
|
|
11625
|
-
data,
|
|
11626
|
-
component: this.componentName,
|
|
11627
|
-
name: this.action || ComponentEventNames.SUBMIT,
|
|
11628
|
-
handlers: this.handlers,
|
|
11629
|
-
});
|
|
11645
|
+
super.submitEventEmit(data, this.action || ComponentEventNames.SUBMIT, 'SteppedFormComponent', this.handlers);
|
|
11630
11646
|
}
|
|
11631
11647
|
}
|
|
11632
11648
|
}
|
|
@@ -12649,6 +12665,9 @@ let TableComponent = class TableComponent extends ListComponent {
|
|
|
12649
12665
|
}
|
|
12650
12666
|
async ngOnInit() {
|
|
12651
12667
|
this.initialized = false;
|
|
12668
|
+
this.repositoryObserver = {
|
|
12669
|
+
refresh: async (...args) => this.handleRepositoryRefresh(...args),
|
|
12670
|
+
};
|
|
12652
12671
|
this.type = ListComponentsTypes.PAGINATED;
|
|
12653
12672
|
this.empty = Object.assign({}, DefaultListEmptyOptions, this.empty);
|
|
12654
12673
|
if (!this.initialized)
|
|
@@ -12724,7 +12743,7 @@ let TableComponent = class TableComponent extends ListComponent {
|
|
|
12724
12743
|
return { ...accum, [curr]: parserFn ? parserFn(mapped[curr], this) : mapped[curr] };
|
|
12725
12744
|
}, { ...props });
|
|
12726
12745
|
}
|
|
12727
|
-
mapResults(data) {
|
|
12746
|
+
async mapResults(data) {
|
|
12728
12747
|
if (!data || !data.length)
|
|
12729
12748
|
return [];
|
|
12730
12749
|
return data.reduce((accum, curr) => [
|
|
@@ -13132,21 +13151,6 @@ class NgxModelPageDirective extends NgxPageDirective {
|
|
|
13132
13151
|
* @memberOf ModelPage
|
|
13133
13152
|
*/
|
|
13134
13153
|
this.operation = OperationKeys.READ;
|
|
13135
|
-
/**
|
|
13136
|
-
* @description Array of operations allowed for the current model instance.
|
|
13137
|
-
* @summary Dynamically determined list of operations that are permitted based on
|
|
13138
|
-
* the current context and model state. Initially contains CREATE and READ operations,
|
|
13139
|
-
* with UPDATE and DELETE added when a modelId is present. This controls which
|
|
13140
|
-
* action buttons are displayed and which operations are accessible to the user.
|
|
13141
|
-
*
|
|
13142
|
-
* @type {OperationKeys[]}
|
|
13143
|
-
* @default [OperationKeys.CREATE, OperationKeys.READ]
|
|
13144
|
-
* @memberOf ModelPage
|
|
13145
|
-
*/
|
|
13146
|
-
this.allowedOperations = [
|
|
13147
|
-
OperationKeys.CREATE,
|
|
13148
|
-
OperationKeys.READ,
|
|
13149
|
-
];
|
|
13150
13154
|
/**
|
|
13151
13155
|
* @description Current model data loaded from the repository.
|
|
13152
13156
|
* @summary Stores the raw data object representing the current model instance retrieved
|
|
@@ -13212,7 +13216,7 @@ class NgxModelPageDirective extends NgxPageDirective {
|
|
|
13212
13216
|
async ionViewWillEnter() {
|
|
13213
13217
|
// await super.ionViewWillEnter();
|
|
13214
13218
|
if (this.modelId)
|
|
13215
|
-
this.
|
|
13219
|
+
this.operations = this.operations.concat([
|
|
13216
13220
|
OperationKeys.UPDATE,
|
|
13217
13221
|
OperationKeys.DELETE,
|
|
13218
13222
|
]);
|