ng-prime-tools 1.0.40 → 1.0.41
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/esm2022/lib/pt-advanced-prime-table/pt-advanced-prime-table.component.mjs +58 -13
- package/fesm2022/ng-prime-tools.mjs +57 -12
- package/fesm2022/ng-prime-tools.mjs.map +1 -1
- package/lib/pt-advanced-prime-table/pt-advanced-prime-table.component.d.ts +3 -3
- package/lib/pt-advanced-prime-table/pt-advanced-prime-table.component.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -191,6 +191,7 @@ class PTAdvancedPrimeTableComponent {
|
|
|
191
191
|
this.filters = {};
|
|
192
192
|
// store the last filter value per column field (for all filters)
|
|
193
193
|
this.latestFilterValues = {};
|
|
194
|
+
this.clearedFields = new Set();
|
|
194
195
|
this.validCurrencyCodes = ['USD', 'EUR', 'MAD'];
|
|
195
196
|
this.iconWidth = 77;
|
|
196
197
|
// Component state
|
|
@@ -393,9 +394,16 @@ class PTAdvancedPrimeTableComponent {
|
|
|
393
394
|
this.latestFilterValues[key] = value;
|
|
394
395
|
}
|
|
395
396
|
}
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
397
|
+
onFilterClear(field) {
|
|
398
|
+
if (!field) {
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
// forget cached value for this field
|
|
402
|
+
delete this.latestFilterValues[field];
|
|
403
|
+
// mark this field as explicitly cleared so filterColumn
|
|
404
|
+
// doesn't reuse the cached value on the same event
|
|
405
|
+
this.clearedFields.add(field);
|
|
406
|
+
}
|
|
399
407
|
onFilterValueChange(field, filterModel, value) {
|
|
400
408
|
if (!field) {
|
|
401
409
|
return;
|
|
@@ -410,7 +418,27 @@ class PTAdvancedPrimeTableComponent {
|
|
|
410
418
|
this.latestFilterValues[field] = value;
|
|
411
419
|
}
|
|
412
420
|
if (filterModel) {
|
|
421
|
+
// update both places so PrimeNG emits it correctly
|
|
413
422
|
filterModel.value = value;
|
|
423
|
+
if (Array.isArray(filterModel.constraints) &&
|
|
424
|
+
filterModel.constraints.length > 0) {
|
|
425
|
+
filterModel.constraints[0].value = value;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
onNumberFilterChange(field, value) {
|
|
430
|
+
if (!field) {
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
const isEmpty = value === null ||
|
|
434
|
+
value === undefined ||
|
|
435
|
+
value === '' ||
|
|
436
|
+
(Array.isArray(value) && value.length === 0);
|
|
437
|
+
if (isEmpty) {
|
|
438
|
+
delete this.latestFilterValues[field];
|
|
439
|
+
}
|
|
440
|
+
else {
|
|
441
|
+
this.latestFilterValues[field] = value;
|
|
414
442
|
}
|
|
415
443
|
}
|
|
416
444
|
/** Helper: find column by field. Supports composed fields like "code.prop". */
|
|
@@ -424,11 +452,13 @@ class PTAdvancedPrimeTableComponent {
|
|
|
424
452
|
this.onFilterColumn.emit(event);
|
|
425
453
|
return;
|
|
426
454
|
}
|
|
455
|
+
const isNullish = (v) => v === null || v === undefined || v === '';
|
|
427
456
|
Object.keys(filters).forEach((field) => {
|
|
428
457
|
const meta = filters[field];
|
|
429
458
|
const normalizeMeta = (m) => Array.isArray(m) && m.length > 0 ? m[0] : m;
|
|
430
459
|
const m = normalizeMeta(meta);
|
|
431
460
|
const col = this.findColumnByField(field);
|
|
461
|
+
const wasCleared = this.clearedFields.has(field);
|
|
432
462
|
// nothing to do
|
|
433
463
|
if (!m && !col) {
|
|
434
464
|
return;
|
|
@@ -441,9 +471,7 @@ class PTAdvancedPrimeTableComponent {
|
|
|
441
471
|
col.composedNames?.forEach((name) => {
|
|
442
472
|
const key = `${col.code}.${name}`;
|
|
443
473
|
const val = this.latestFilterValues[key];
|
|
444
|
-
const empty = val ===
|
|
445
|
-
val === undefined ||
|
|
446
|
-
(Array.isArray(val) && val.length === 0);
|
|
474
|
+
const empty = isNullish(val) || (Array.isArray(val) && val.length === 0);
|
|
447
475
|
if (!empty) {
|
|
448
476
|
composedValues[name] = val;
|
|
449
477
|
}
|
|
@@ -461,6 +489,7 @@ class PTAdvancedPrimeTableComponent {
|
|
|
461
489
|
// send object { sub1: [...], sub2: [...] } to parent
|
|
462
490
|
m.value = composedValues;
|
|
463
491
|
}
|
|
492
|
+
const wasCleared = this.clearedFields.has(field);
|
|
464
493
|
return; // composed handled
|
|
465
494
|
}
|
|
466
495
|
// ----------------------------------------------------
|
|
@@ -469,16 +498,32 @@ class PTAdvancedPrimeTableComponent {
|
|
|
469
498
|
if (!m) {
|
|
470
499
|
return;
|
|
471
500
|
}
|
|
501
|
+
// If the user clicked Clear for this field, force it to empty
|
|
502
|
+
if (wasCleared) {
|
|
503
|
+
delete this.latestFilterValues[field];
|
|
504
|
+
m.value = null;
|
|
505
|
+
if (Array.isArray(m.constraints) && m.constraints.length > 0) {
|
|
506
|
+
m.constraints[0].value = null;
|
|
507
|
+
}
|
|
508
|
+
this.clearedFields.delete(field);
|
|
509
|
+
return;
|
|
510
|
+
}
|
|
472
511
|
let value = m.value;
|
|
512
|
+
// PrimeNG often stores the real value in constraints[0].value
|
|
473
513
|
if (Array.isArray(m.constraints) && m.constraints.length > 0) {
|
|
474
514
|
const cVal = m.constraints[0].value;
|
|
475
|
-
if (cVal
|
|
515
|
+
if (!isNullish(cVal)) {
|
|
476
516
|
value = cVal;
|
|
477
517
|
}
|
|
478
518
|
}
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
519
|
+
// 🔴 NEW: fall back to cached value typed in the input
|
|
520
|
+
const cached = this.latestFilterValues[field];
|
|
521
|
+
const hasCached = !isNullish(cached) && (!Array.isArray(cached) || cached.length > 0);
|
|
522
|
+
if ((isNullish(value) || (Array.isArray(value) && value.length === 0)) &&
|
|
523
|
+
hasCached) {
|
|
524
|
+
value = cached;
|
|
525
|
+
}
|
|
526
|
+
const isEmpty = isNullish(value) || (Array.isArray(value) && value.length === 0);
|
|
482
527
|
// CLEAR => remove from cache, reset PrimeNG metadata
|
|
483
528
|
if (isEmpty) {
|
|
484
529
|
delete this.latestFilterValues[field];
|
|
@@ -818,11 +863,11 @@ class PTAdvancedPrimeTableComponent {
|
|
|
818
863
|
return formattedNumber;
|
|
819
864
|
}
|
|
820
865
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: PTAdvancedPrimeTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
821
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.11", type: PTAdvancedPrimeTableComponent, selector: "pt-advanced-prime-table", inputs: { data: "data", columns: "columns", totalRecords: "totalRecords", rowsPerPage: "rowsPerPage", hasSearchFilter: "hasSearchFilter", hasExportExcel: "hasExportExcel", hasExportPDF: "hasExportPDF", hasColumnFilter: "hasColumnFilter", isPaginated: "isPaginated", actions: "actions", isSortable: "isSortable", loading: "loading", maxHeight: "maxHeight" }, outputs: { search: "search", exportExcelEvent: "exportExcelEvent", exportPdfEvent: "exportPdfEvent", onPageChange: "onPageChange", onSortColumn: "onSortColumn", onFilterColumn: "onFilterColumn" }, viewQueries: [{ propertyName: "dt", first: true, predicate: ["dt"], descendants: true }], ngImport: i0, template: "<div class=\"pt-advanced-prime-table table-container\">\n <p-table\n #dt\n [value]=\"data\"\n [loading]=\"loading\"\n [rows]=\"rows\"\n [paginator]=\"isPaginated\"\n [globalFilterFields]=\"globalFilterFields\"\n [rowsPerPageOptions]=\"rowsPerPage\"\n [totalRecords]=\"totalRecords\"\n [lazy]=\"isPaginated\"\n dataKey=\"id\"\n styleClass=\"p-datatable-gridlines p-datatable-striped\"\n [scrollable]=\"true\"\n [scrollHeight]=\"maxHeight !== null ? maxHeight : undefined\"\n (onFilter)=\"filterColumn($event)\"\n (onPage)=\"changePage($event)\"\n (onSort)=\"sortColumn($event)\"\n >\n <!-- COLGROUP: sync header/body widths -->\n <ng-template pTemplate=\"colgroup\" let-columns>\n <colgroup>\n <col\n *ngFor=\"let col of columns\"\n [style.width]=\"col.width || getHeaderWidth(col)\"\n />\n </colgroup>\n </ng-template>\n\n <!-- CAPTION -->\n <ng-template pTemplate=\"caption\">\n <div class=\"flex\">\n <div>\n <h3>Total: {{ totalRecords }}</h3>\n </div>\n\n <div>\n <!-- Clear filters -->\n <button\n *ngIf=\"hasSearchFilter\"\n pButton\n icon=\"pi pi-filter-slash\"\n class=\"p-button-rounded p-button-text\"\n (click)=\"clear(dt)\"\n title=\"Clear filters\"\n ></button>\n\n <!-- Export to Excel Button -->\n <button\n *ngIf=\"hasExportExcel\"\n pButton\n icon=\"pi pi-file-excel\"\n class=\"p-button-rounded p-button-text\"\n (click)=\"exportExcel()\"\n title=\"Export to Excel\"\n ></button>\n\n <!-- Export to PDF Button -->\n <button\n *ngIf=\"hasExportPDF\"\n pButton\n icon=\"pi pi-file-pdf\"\n class=\"p-button-rounded p-button-text\"\n (click)=\"exportPdf()\"\n title=\"Export to PDF\"\n ></button>\n </div>\n\n <div class=\"ml-auto\" *ngIf=\"hasSearchFilter\">\n <p-iconField iconPosition=\"left\" class=\"ml-auto\">\n <p-inputIcon>\n <i class=\"pi pi-search\"></i>\n </p-inputIcon>\n <input\n pInputText\n type=\"text\"\n [(ngModel)]=\"searchValue\"\n (input)=\"filterGlobal($event)\"\n placeholder=\"Search keyword\"\n />\n </p-iconField>\n </div>\n </div>\n </ng-template>\n\n <!-- HEADER -->\n <ng-template pTemplate=\"header\">\n <tr class=\"sticky-header\">\n <ng-container *ngFor=\"let col of columns\">\n <th\n *ngIf=\"!col.children; else groupHeader\"\n pSortableColumn=\"{{ col.code }}\"\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [style.padding]=\"'0px'\"\n [ngClass]=\"[\n getHeaderAlignClass(col),\n col.type === TableTypeEnum.ACTION ? 'action-column' : ''\n ]\"\n colspan=\"1\"\n >\n <!-- SORTABLE HEADER -->\n <ng-container\n *ngIf=\"isSortable && col.isSortable !== false; else noSortHeader\"\n >\n <div\n class=\"header-container d-flex align-items-center justify-content-between\"\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [style.padding]=\"'0px'\"\n [style.margin]=\"'10px'\"\n >\n <span [ngClass]=\"getHeaderTitleClass(col)\">\n {{ col.title }}\n </span>\n <div\n class=\"icons d-flex align-items-center\"\n [style.width]=\"'77px'\"\n >\n <p-sortIcon field=\"{{ col.code }}\" />\n\n <!-- COLUMN FILTERS -->\n <ng-container\n *ngIf=\"hasColumnFilter && col.isFilter !== false\"\n >\n <!-- COMPOSED FILTER (uses built-in Apply/Clear) -->\n <p-columnFilter\n *ngIf=\"col.type === TableTypeEnum.COMPOSED\"\n display=\"menu\"\n [field]=\"col.code\"\n type=\"text\"\n [showApplyButton]=\"true\"\n [showClearButton]=\"true\"\n (onClear)=\"onComposedColumnClear(col)\"\n >\n <ng-template\n pTemplate=\"filter\"\n let-filter=\"filterCallback\"\n let-filterModel=\"filterModel\"\n >\n <div *ngFor=\"let composedName of col.composedNames\">\n <ng-container\n *ngIf=\"\n getComposedFieldType(col, composedName) ===\n TableTypeEnum.STRING\n \"\n >\n <p-multiSelect\n [options]=\"filters[composedName]?.options\"\n [ngModel]=\"filters[composedName]?.value\"\n (ngModelChange)=\"\n onComposedFilterValueChange(\n col,\n composedName,\n $event,\n filterModel\n )\n \"\n [placeholder]=\"filters[composedName]?.placeholder\"\n display=\"chip\"\n >\n <ng-template let-item pTemplate=\"item\">\n <div class=\"custom-multiselect-item\">\n <img\n *ngIf=\"item.image\"\n [src]=\"item.image\"\n alt=\"icon\"\n class=\"filter-image\"\n />\n <span>{{ item.label }}</span>\n </div>\n </ng-template>\n </p-multiSelect>\n </ng-container>\n </div>\n </ng-template>\n </p-columnFilter>\n\n <!-- OTHER TYPES -->\n <p-columnFilter\n *ngIf=\"col.type !== TableTypeEnum.COMPOSED\"\n display=\"menu\"\n [field]=\"col.code\"\n [type]=\"getColumnFilterType(col)\"\n [showApplyButton]=\"true\"\n [showClearButton]=\"true\"\n >\n <!-- NUMBER -->\n <ng-template\n pTemplate=\"filter\"\n *ngIf=\"col.type === TableTypeEnum.NUMBER\"\n let-filterModel=\"filterModel\"\n >\n <input\n pInputText\n type=\"number\"\n [step]=\"\n col.decimalPlaces\n ? '0.' + '1'.padEnd(col.decimalPlaces, '0')\n : 'any'\n \"\n [ngModel]=\"\n latestFilterValues[col.code!] ?? filterModel?.value\n \"\n (ngModelChange)=\"\n onFilterValueChange(col.code!, filterModel, $event)\n \"\n placeholder=\"Enter a number\"\n />\n </ng-template>\n\n <!-- DATE -->\n <ng-template\n pTemplate=\"filter\"\n *ngIf=\"col.type === TableTypeEnum.DATE\"\n let-filterModel=\"filterModel\"\n >\n <p-calendar\n [ngModel]=\"\n latestFilterValues[col.code!] ?? filterModel?.value\n \"\n (ngModelChange)=\"\n onFilterValueChange(col.code!, filterModel, $event)\n \"\n dateFormat=\"dd/mm/yy\"\n placeholder=\"Choose a date\"\n ></p-calendar>\n </ng-template>\n\n <!-- MULTISELECT -->\n <ng-template\n pTemplate=\"filter\"\n *ngIf=\"\n col.type === TableTypeEnum.MULTISELECT &&\n col.filterOptions &&\n col.filterOptions.length > 0\n \"\n let-filterModel=\"filterModel\"\n >\n <p-multiSelect\n [options]=\"col.filterOptions\"\n [ngModel]=\"\n latestFilterValues[col.code!] ?? filterModel?.value\n \"\n (ngModelChange)=\"\n onFilterValueChange(col.code!, filterModel, $event)\n \"\n display=\"chip\"\n placeholder=\"Choose option\"\n class=\"custom-multiselect\"\n ></p-multiSelect>\n </ng-template>\n </p-columnFilter>\n </ng-container>\n </div>\n </div>\n </ng-container>\n\n <!-- NON-SORTABLE HEADER -->\n <ng-template #noSortHeader>\n <div\n class=\"header-container d-flex align-items-center justify-content-between\"\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [style.padding]=\"'0px'\"\n [style.margin]=\"'10px'\"\n >\n <span [ngClass]=\"getHeaderTitleClass(col)\">\n {{ col.title }}\n </span>\n\n <ng-container *ngIf=\"hasColumnFilter && col.isFilter !== false\">\n <!-- AMOUNT behaves like NUMBER -->\n <p-columnFilter\n *ngIf=\"col.type === 'AMOUNT'\"\n display=\"menu\"\n [field]=\"col.code\"\n [type]=\"getColumnFilterType(col)\"\n [currency]=\"getCurrencySymbol(col)\"\n [showApplyButton]=\"true\"\n [showClearButton]=\"true\"\n >\n <ng-template\n pTemplate=\"filter\"\n let-filterModel=\"filterModel\"\n >\n <input\n pInputText\n type=\"number\"\n [step]=\"\n col.decimalPlaces\n ? '0.' + '1'.padEnd(col.decimalPlaces, '0')\n : 'any'\n \"\n [ngModel]=\"\n latestFilterValues[col.code!] ?? filterModel?.value\n \"\n (ngModelChange)=\"\n onFilterValueChange(col.code!, filterModel, $event)\n \"\n placeholder=\"Enter an amount\"\n />\n </ng-template>\n </p-columnFilter>\n\n <p-columnFilter\n *ngIf=\"col.type !== 'AMOUNT'\"\n display=\"menu\"\n [field]=\"col.code\"\n [type]=\"getColumnFilterType(col)\"\n [showApplyButton]=\"true\"\n [showClearButton]=\"true\"\n >\n <!-- DATE -->\n <ng-template\n pTemplate=\"filter\"\n let-filterModel=\"filterModel\"\n *ngIf=\"getColumnFilterType(col) === 'date'\"\n >\n <p-calendar\n [ngModel]=\"\n latestFilterValues[col.code!] ?? filterModel?.value\n \"\n (ngModelChange)=\"\n onFilterValueChange(col.code!, filterModel, $event)\n \"\n dateFormat=\"dd/mm/yy\"\n ></p-calendar>\n </ng-template>\n\n <!-- MULTISELECT -->\n <ng-template\n pTemplate=\"filter\"\n let-filterModel=\"filterModel\"\n *ngIf=\"getColumnFilterType(col) === 'multiSelect'\"\n >\n <p-multiSelect\n [options]=\"col.filterOptions\"\n [ngModel]=\"\n latestFilterValues[col.code!] ?? filterModel?.value\n \"\n (ngModelChange)=\"\n onFilterValueChange(col.code!, filterModel, $event)\n \"\n display=\"chip\"\n placeholder=\"Select\"\n class=\"custom-multiselect\"\n ></p-multiSelect>\n </ng-template>\n </p-columnFilter>\n </ng-container>\n </div>\n </ng-template>\n </th>\n\n <!-- GROUPED HEADER -->\n <ng-template #groupHeader>\n <th\n [attr.colspan]=\"col.children?.length\"\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [ngClass]=\"getHeaderAlignClass(col)\"\n >\n <span>{{ col.title }}</span>\n </th>\n </ng-template>\n </ng-container>\n </tr>\n\n <!-- CHILD HEADERS -->\n <tr *ngIf=\"hasGroupedColumns\">\n <ng-container *ngFor=\"let col of columns\">\n <ng-container *ngIf=\"col.children\">\n <th\n *ngFor=\"let child of col.children\"\n [style.width]=\"child.width || getHeaderWidth(child)\"\n [style.padding]=\"'0px'\"\n ></th>\n </ng-container>\n </ng-container>\n </tr>\n </ng-template>\n\n <!-- EMPTY MESSAGE -->\n <ng-template pTemplate=\"emptymessage\">\n <tr class=\"p-datatable-emptymessage\">\n <!-- span all columns -->\n <td class=\"empty-message-cell\" [attr.colspan]=\"columns.length || 1\">\n <div class=\"empty-message-wrapper\">\n <div class=\"empty-message\">\n <i class=\"pi pi-info-circle\"></i>\n <p>No records available to display.</p>\n </div>\n </div>\n </td>\n </tr>\n </ng-template>\n\n <!-- BODY -->\n <ng-template\n pTemplate=\"body\"\n let-data\n let-editing=\"editing\"\n let-ri=\"rowIndex\"\n >\n <tr *ngIf=\"!loading\" [pEditableRow]=\"isEdit ? data : null\">\n <ng-container *ngFor=\"let col of columns\">\n <!-- SIMPLE COLUMNS (no children) -->\n <ng-container *ngIf=\"!col.children; else childColumns\">\n <!-- EDITABLE CELL -->\n <td\n *ngIf=\"\n isEditable(col.code!) && col.type !== TableTypeEnum.ACTION;\n else normalTD\n \"\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [ngClass]=\"getDataAlignClass(col)\"\n >\n <!-- Editable input for NUMBER/DATE/STRING/MULTISELECT -->\n <ng-container *ngIf=\"isMultiSelect(col.code); else datePicker\">\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <p-multiSelect\n appendTo=\"body\"\n [ngModel]=\"data[col.code!]\"\n [style]=\"{ width: '100%' }\"\n (ngModelChange)=\"changeHandler(data.id, col.code, $event)\"\n [options]=\"optionValues\"\n ></p-multiSelect>\n </ng-template>\n <ng-template pTemplate=\"output\">\n <div class=\"multi-select-container\">\n <ng-container *ngFor=\"let rec of data[col.code!]\">\n <p-tag [value]=\"rec\"></p-tag>\n </ng-container>\n </div>\n </ng-template>\n </p-cellEditor>\n </ng-container>\n\n <ng-template #datePicker>\n <ng-container *ngIf=\"isDatePicker(col.code); else normalInput\">\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <p-calendar\n [inputId]=\"data[col.code!]\"\n [ngModel]=\"data[col.code!]\"\n (ngModelChange)=\"\n changeHandler(data.id, col.code, $event)\n \"\n [dateFormat]=\"'dd/mm/yy'\"\n ></p-calendar>\n </ng-template>\n <ng-template pTemplate=\"output\">\n {{ data[col.code!] | customDate }}\n </ng-template>\n </p-cellEditor>\n </ng-container>\n </ng-template>\n\n <ng-template #normalInput>\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <input\n pInputText\n type=\"text\"\n [ngModel]=\"data[col.code!]\"\n (change)=\"onChange($event, data.id, col.code)\"\n />\n </ng-template>\n <ng-template pTemplate=\"output\">\n <ng-container\n *ngIf=\"\n col.type === TableTypeEnum.AMOUNT;\n else normalOutput\n \"\n >\n {{\n data[col.code!]\n | customCurrency\n : getCurrencySymbol(col)\n : col.decimalPlaces\n : col.thousandSeparator\n : col.decimalSeparator\n }}\n </ng-container>\n <ng-template #normalOutput>\n {{ data[col.code!] }}\n </ng-template>\n </ng-template>\n </p-cellEditor>\n </ng-template>\n </td>\n\n <!-- NON-EDITABLE CELL (ALWAYS RENDERED) -->\n <ng-template #normalTD>\n <td\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [ngClass]=\"[\n getDataAlignClass(col),\n col.type === TableTypeEnum.ACTION ? 'action-column' : ''\n ]\"\n >\n <!-- ACTION column: built-in edit/delete + custom actions -->\n <ng-container\n *ngIf=\"col.type === TableTypeEnum.ACTION; else nonActionCell\"\n >\n <div class=\"action-buttons-container\">\n <!-- built-in delete -->\n <button\n *ngIf=\"isDelete\"\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-trash\"\n (click)=\"Delete(data.id)\"\n class=\"p-button-rounded p-button-text\"\n ></button>\n\n <!-- built-in inline edit -->\n <div *ngIf=\"isEdit\">\n <button\n pInitEditableRow\n *ngIf=\"!editing\"\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-pencil\"\n (click)=\"initEditableRow(data)\"\n class=\"p-button-rounded p-button-text\"\n ></button>\n <button\n *ngIf=\"editing\"\n pSaveEditableRow\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-check\"\n (click)=\"saveEditableRow(data)\"\n class=\"p-button-rounded p-button-text\"\n ></button>\n <button\n *ngIf=\"editing\"\n pCancelEditableRow\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-times\"\n (click)=\"cancelEditableRow(data)\"\n class=\"p-button-rounded p-button-text\"\n ></button>\n </div>\n\n <!-- custom actions -->\n <button\n *ngFor=\"let act of customActions\"\n pButton\n pRipple\n type=\"button\"\n class=\"p-button-rounded p-button-text\"\n [icon]=\"act.icon || 'pi pi-ellipsis-h'\"\n [ngClass]=\"act.styleClass\"\n (click)=\"onCustomActionClick(act, data)\"\n ></button>\n </div>\n </ng-container>\n\n <!-- NON-ACTION cells -->\n <ng-template #nonActionCell>\n <!-- COMPOSED -->\n <ng-container\n *ngIf=\"\n col.type === TableTypeEnum.COMPOSED;\n else nonComposed\n \"\n >\n <div class=\"composed-cell\">\n <ng-container\n *ngFor=\"\n let composedName of col.composedNames;\n let i = index\n \"\n >\n <!-- IMAGE -->\n <ng-container\n *ngIf=\"\n col.composedTypes &&\n col.composedTypes[i] === TableTypeEnum.IMAGE\n \"\n >\n <img\n [src]=\"data[col.code!]?.[composedName]\"\n alt=\"composed-img\"\n class=\"composed-image\"\n [ngStyle]=\"\n getImageStyle(col.composedStyles?.[composedName])\n \"\n />\n </ng-container>\n\n <!-- STRING -->\n <ng-container\n *ngIf=\"\n col.composedTypes &&\n col.composedTypes[i] === TableTypeEnum.STRING\n \"\n >\n <span\n class=\"composed-text\"\n [ngStyle]=\"\n getTitleStyle(\n col.composedStyles?.[composedName]\n )\n \"\n >\n {{ data[col.code!]?.[composedName] }}\n </span>\n </ng-container>\n </ng-container>\n </div>\n </ng-container>\n\n <ng-template #nonComposed>\n <!-- AMOUNT-->\n <ng-container\n *ngIf=\"col.type === TableTypeEnum.AMOUNT; else nonAmount\"\n >\n {{\n data[col.code!]\n | customCurrency\n : getCurrencySymbol(col)\n : col.decimalPlaces\n : col.thousandSeparator\n : col.decimalSeparator\n }}\n </ng-container>\n\n <ng-template #nonAmount>\n <!-- NUMBER-->\n <ng-container\n *ngIf=\"\n col.type === TableTypeEnum.NUMBER;\n else nonNumber\n \"\n >\n {{\n formatNumber(\n data[col.code!],\n col.decimalPlaces,\n col.thousandSeparator,\n col.decimalSeparator\n )\n }}\n </ng-container>\n\n <ng-template #nonNumber>\n <!-- DATE -->\n <ng-container\n *ngIf=\"\n col.type === TableTypeEnum.DATE;\n else normalTypes\n \"\n >\n {{ formatDate(data[col.code!]) }}\n </ng-container>\n\n <ng-template #normalTypes>\n <!-- STRING, MULTISELECT-->\n <ng-container\n *ngIf=\"\n [\n TableTypeEnum.STRING,\n TableTypeEnum.MULTISELECT\n ].includes(col.type!)\n \"\n >\n {{ data[col.code!] }}\n </ng-container>\n </ng-template>\n </ng-template>\n </ng-template>\n </ng-template>\n </ng-template>\n </td>\n </ng-template>\n </ng-container>\n\n <!-- CHILD COLUMNS -->\n <ng-template #childColumns>\n <ng-container *ngFor=\"let child of col.children\">\n <td\n [style.width]=\"child.width || getHeaderWidth(child)\"\n [ngClass]=\"getDataAlignClass(child)\"\n >\n <ng-container\n *ngIf=\"isEditable(child.code); else childNormalTD\"\n >\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <input\n pInputText\n type=\"text\"\n [ngModel]=\"child.code ? data[child.code] : null\"\n (change)=\"onChange($event, data.id, child.code)\"\n />\n </ng-template>\n <ng-template pTemplate=\"output\">\n {{ child.code ? data[child.code] : \"\" }}\n </ng-template>\n </p-cellEditor>\n </ng-container>\n\n <ng-template #childNormalTD>\n {{ child.code ? data[child.code] : \"\" }}\n </ng-template>\n </td>\n </ng-container>\n </ng-template>\n </ng-container>\n </tr>\n </ng-template>\n </p-table>\n</div>\n", styles: [".pt-advanced-prime-table .bread-crumb{margin-bottom:15px}.pt-advanced-prime-table .date{width:100%;height:5rem;display:grid;justify-items:start;align-items:center}.pt-advanced-prime-table .filter-container{width:100%;display:flex;justify-content:space-between;align-items:center}.pt-advanced-prime-table .settings{display:flex;gap:1rem}.pt-advanced-prime-table .multi-select-container{display:flex;justify-content:center;align-items:center;gap:.3rem}.pt-advanced-prime-table ::ng-deep p-table{min-width:50rem}.pt-advanced-prime-table ::ng-deep .custom-multiselect .p-hidden-accessible input{display:none}.pt-advanced-prime-table ::ng-deep .p-datatable .p-sortable-column.p-highlight:hover{background:none}.pt-advanced-prime-table ::ng-deep .p-datatable .p-sortable-column:focus{box-shadow:none;outline:0 none}.pt-advanced-prime-table ::ng-deep .header-container{display:flex;justify-content:space-between;align-items:center;width:100%}.pt-advanced-prime-table ::ng-deep .header-title-left,.pt-advanced-prime-table ::ng-deep .header-title-center,.pt-advanced-prime-table ::ng-deep .header-title-right{flex:1}.pt-advanced-prime-table ::ng-deep .header-title-left{text-align:left}.pt-advanced-prime-table ::ng-deep .header-title-center{text-align:center}.pt-advanced-prime-table ::ng-deep .header-title-right{text-align:right}.pt-advanced-prime-table ::ng-deep .header-align-left{text-align:left}.pt-advanced-prime-table ::ng-deep .header-align-center{text-align:center}.pt-advanced-prime-table ::ng-deep .header-align-right{text-align:right}.pt-advanced-prime-table ::ng-deep p-columnfilter.p-element.ng-star-inserted{margin-top:4px}.pt-advanced-prime-table .flex{display:flex;justify-content:space-between;align-items:center}.pt-advanced-prime-table .ml-auto{margin-left:auto}.pt-advanced-prime-table ::ng-deep p-inputicon{margin-right:-1.5rem;z-index:2;position:relative}.pt-advanced-prime-table ::ng-deep .p-inputtext{padding-left:1.7rem}.pt-advanced-prime-table ::ng-deep .bt-filter-btn button{cursor:pointer;margin-left:1rem}.pt-advanced-prime-table ::ng-deep .p-icon-field-left .p-input-icon:first-of-type{left:-1rem}.pt-advanced-prime-table .table-row{text-align:center;display:flex;gap:1rem;justify-content:center}.pt-advanced-prime-table ::ng-deep span.p-button-icon.pi.pi-file-excel{font-size:1.25em;color:green}.pt-advanced-prime-table ::ng-deep span.p-button-icon.pi.pi-file-pdf{font-size:1.25em;color:red}.pt-advanced-prime-table .table-container{display:block;width:100%}.pt-advanced-prime-table ::ng-deep .p-datatable-emptymessage>td.empty-message-cell{padding:0!important}.pt-advanced-prime-table .empty-message-wrapper{width:100%;height:100%;min-height:180px;display:flex;align-items:center;justify-content:center}.pt-advanced-prime-table .empty-message{text-align:center;color:#888;font-size:1.2rem}.pt-advanced-prime-table .empty-message i{display:block;font-size:2rem;margin-bottom:.5rem}.pt-advanced-prime-table th{white-space:normal;word-wrap:break-word}.filter-image{width:22px;height:14px;margin-right:5px}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr>td.cell-align-left{text-align:left!important}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr>td.cell-align-center{text-align:center!important}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr>td.cell-align-right{text-align:right!important}.pt-advanced-prime-table ::ng-deep th.action-column,.pt-advanced-prime-table ::ng-deep td.action-column{text-align:center!important;justify-content:center;align-items:center;overflow:hidden;white-space:nowrap;padding:0}.pt-advanced-prime-table ::ng-deep .action-buttons-container{width:100%;display:flex;justify-content:center!important;align-items:center!important;gap:.35rem}.pt-advanced-prime-table ::ng-deep .action-buttons-container .p-button.p-button-rounded.p-button-text{padding:.25rem!important;min-width:22px!important;height:22px!important}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: i2.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "style", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "scrollDirection", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "responsive", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "autoLayout", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll", "virtualRowHeight"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "directive", type: i1$1.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "directive", type: i2.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { kind: "component", type: i2.CellEditor, selector: "p-cellEditor" }, { kind: "component", type: i2.SortIcon, selector: "p-sortIcon", inputs: ["field"] }, { kind: "directive", type: i2.EditableRow, selector: "[pEditableRow]", inputs: ["pEditableRow", "pEditableRowDisabled"] }, { kind: "directive", type: i2.InitEditableRow, selector: "[pInitEditableRow]" }, { kind: "directive", type: i2.SaveEditableRow, selector: "[pSaveEditableRow]" }, { kind: "directive", type: i2.CancelEditableRow, selector: "[pCancelEditableRow]" }, { kind: "component", type: i2.ColumnFilter, selector: "p-columnFilter", inputs: ["field", "type", "display", "showMenu", "matchMode", "operator", "showOperator", "showClearButton", "showApplyButton", "showMatchModes", "showAddButton", "hideOnClear", "placeholder", "matchModeOptions", "maxConstraints", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "locale", "localeMatcher", "currency", "currencyDisplay", "useGrouping", "showButtons", "ariaLabel"], outputs: ["onShow", "onHide"] }, { kind: "directive", type: i4.InputText, selector: "[pInputText]", inputs: ["variant"] }, { kind: "directive", type: i3.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "label", "icon", "loading", "severity", "raised", "rounded", "text", "outlined", "size", "plain"] }, { kind: "component", type: i6.Calendar, selector: "p-calendar", inputs: ["iconDisplay", "style", "styleClass", "inputStyle", "inputId", "name", "inputStyleClass", "placeholder", "ariaLabelledBy", "ariaLabel", "iconAriaLabel", "disabled", "dateFormat", "multipleSeparator", "rangeSeparator", "inline", "showOtherMonths", "selectOtherMonths", "showIcon", "icon", "appendTo", "readonlyInput", "shortYearCutoff", "monthNavigator", "yearNavigator", "hourFormat", "timeOnly", "stepYearPicker", "stepHour", "stepMinute", "stepSecond", "showSeconds", "required", "showOnFocus", "showWeek", "startWeekFromFirstDayOfYear", "showClear", "dataType", "selectionMode", "maxDateCount", "showButtonBar", "todayButtonStyleClass", "clearButtonStyleClass", "autofocus", "autoZIndex", "baseZIndex", "panelStyleClass", "panelStyle", "keepInvalid", "hideOnDateTimeSelect", "touchUI", "timeSeparator", "focusTrap", "showTransitionOptions", "hideTransitionOptions", "tabindex", "variant", "minDate", "maxDate", "disabledDates", "disabledDays", "yearRange", "showTime", "responsiveOptions", "numberOfMonths", "firstDayOfWeek", "locale", "view", "defaultDate"], outputs: ["onFocus", "onBlur", "onClose", "onSelect", "onClear", "onInput", "onTodayClick", "onClearClick", "onMonthChange", "onYearChange", "onClickOutside", "onShow"] }, { kind: "directive", type: i2$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i8.MultiSelect, selector: "p-multiSelect", inputs: ["id", "ariaLabel", "style", "styleClass", "panelStyle", "panelStyleClass", "inputId", "disabled", "readonly", "group", "filter", "filterPlaceHolder", "filterLocale", "overlayVisible", "tabindex", "variant", "appendTo", "dataKey", "name", "ariaLabelledBy", "displaySelectedLabel", "maxSelectedLabels", "selectionLimit", "selectedItemsLabel", "showToggleAll", "emptyFilterMessage", "emptyMessage", "resetFilterOnHide", "dropdownIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "showHeader", "filterBy", "scrollHeight", "lazy", "virtualScroll", "loading", "virtualScrollItemSize", "loadingIcon", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "display", "autocomplete", "showClear", "autofocus", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "defaultLabel", "placeholder", "options", "filterValue", "itemSize", "selectAll", "focusOnHover", "filterFields", "selectOnFocus", "autoOptionFocus"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onClear", "onPanelShow", "onPanelHide", "onLazyLoad", "onRemove", "onSelectAllChange"] }, { kind: "component", type: i9.Tag, selector: "p-tag", inputs: ["style", "styleClass", "severity", "value", "icon", "rounded"] }, { kind: "component", type: i10.IconField, selector: "p-iconField", inputs: ["iconPosition"] }, { kind: "component", type: i11.InputIcon, selector: "p-inputIcon", inputs: ["styleClass"] }, { kind: "pipe", type: CustomCurrencyPipe, name: "customCurrency" }, { kind: "pipe", type: CustomDatePipe, name: "customDate" }] }); }
|
|
866
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.11", type: PTAdvancedPrimeTableComponent, selector: "pt-advanced-prime-table", inputs: { data: "data", columns: "columns", totalRecords: "totalRecords", rowsPerPage: "rowsPerPage", hasSearchFilter: "hasSearchFilter", hasExportExcel: "hasExportExcel", hasExportPDF: "hasExportPDF", hasColumnFilter: "hasColumnFilter", isPaginated: "isPaginated", actions: "actions", isSortable: "isSortable", loading: "loading", maxHeight: "maxHeight" }, outputs: { search: "search", exportExcelEvent: "exportExcelEvent", exportPdfEvent: "exportPdfEvent", onPageChange: "onPageChange", onSortColumn: "onSortColumn", onFilterColumn: "onFilterColumn" }, viewQueries: [{ propertyName: "dt", first: true, predicate: ["dt"], descendants: true }], ngImport: i0, template: "<div class=\"pt-advanced-prime-table table-container\">\n <p-table\n #dt\n [value]=\"data\"\n [loading]=\"loading\"\n [rows]=\"rows\"\n [paginator]=\"isPaginated\"\n [globalFilterFields]=\"globalFilterFields\"\n [rowsPerPageOptions]=\"rowsPerPage\"\n [totalRecords]=\"totalRecords\"\n [lazy]=\"isPaginated\"\n dataKey=\"id\"\n styleClass=\"p-datatable-gridlines p-datatable-striped\"\n [scrollable]=\"true\"\n [scrollHeight]=\"maxHeight !== null ? maxHeight : undefined\"\n (onFilter)=\"filterColumn($event)\"\n (onPage)=\"changePage($event)\"\n (onSort)=\"sortColumn($event)\"\n >\n <!-- COLGROUP: sync header/body widths -->\n <ng-template pTemplate=\"colgroup\" let-columns>\n <colgroup>\n <col\n *ngFor=\"let col of columns\"\n [style.width]=\"col.width || getHeaderWidth(col)\"\n />\n </colgroup>\n </ng-template>\n\n <!-- CAPTION -->\n <ng-template pTemplate=\"caption\">\n <div class=\"flex\">\n <div>\n <h3>Total: {{ totalRecords }}</h3>\n </div>\n\n <div>\n <!-- Clear filters -->\n <button\n *ngIf=\"hasSearchFilter\"\n pButton\n icon=\"pi pi-filter-slash\"\n class=\"p-button-rounded p-button-text\"\n (click)=\"clear(dt)\"\n title=\"Clear filters\"\n ></button>\n\n <!-- Export to Excel Button -->\n <button\n *ngIf=\"hasExportExcel\"\n pButton\n icon=\"pi pi-file-excel\"\n class=\"p-button-rounded p-button-text\"\n (click)=\"exportExcel()\"\n title=\"Export to Excel\"\n ></button>\n\n <!-- Export to PDF Button -->\n <button\n *ngIf=\"hasExportPDF\"\n pButton\n icon=\"pi pi-file-pdf\"\n class=\"p-button-rounded p-button-text\"\n (click)=\"exportPdf()\"\n title=\"Export to PDF\"\n ></button>\n </div>\n\n <div class=\"ml-auto\" *ngIf=\"hasSearchFilter\">\n <p-iconField iconPosition=\"left\" class=\"ml-auto\">\n <p-inputIcon>\n <i class=\"pi pi-search\"></i>\n </p-inputIcon>\n <input\n pInputText\n type=\"text\"\n [(ngModel)]=\"searchValue\"\n (input)=\"filterGlobal($event)\"\n placeholder=\"Search keyword\"\n />\n </p-iconField>\n </div>\n </div>\n </ng-template>\n\n <!-- HEADER -->\n <ng-template pTemplate=\"header\">\n <tr class=\"sticky-header\">\n <ng-container *ngFor=\"let col of columns\">\n <th\n *ngIf=\"!col.children; else groupHeader\"\n pSortableColumn=\"{{ col.code }}\"\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [style.padding]=\"'0px'\"\n [ngClass]=\"[\n getHeaderAlignClass(col),\n col.type === TableTypeEnum.ACTION ? 'action-column' : ''\n ]\"\n colspan=\"1\"\n >\n <!-- SORTABLE HEADER -->\n <ng-container\n *ngIf=\"isSortable && col.isSortable !== false; else noSortHeader\"\n >\n <div\n class=\"header-container d-flex align-items-center justify-content-between\"\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [style.padding]=\"'0px'\"\n [style.margin]=\"'10px'\"\n >\n <span [ngClass]=\"getHeaderTitleClass(col)\">\n {{ col.title }}\n </span>\n <div\n class=\"icons d-flex align-items-center\"\n [style.width]=\"'77px'\"\n >\n <p-sortIcon field=\"{{ col.code }}\" />\n\n <!-- COLUMN FILTERS -->\n <ng-container\n *ngIf=\"hasColumnFilter && col.isFilter !== false\"\n >\n <!-- COMPOSED FILTER (uses built-in Apply/Clear) -->\n <p-columnFilter\n *ngIf=\"col.type === TableTypeEnum.COMPOSED\"\n display=\"menu\"\n [field]=\"col.code\"\n type=\"text\"\n [showApplyButton]=\"true\"\n [showClearButton]=\"true\"\n (onClear)=\"onComposedColumnClear(col)\"\n >\n <ng-template\n pTemplate=\"filter\"\n let-filter=\"filterCallback\"\n let-filterModel=\"filterModel\"\n >\n <div *ngFor=\"let composedName of col.composedNames\">\n <ng-container\n *ngIf=\"\n getComposedFieldType(col, composedName) ===\n TableTypeEnum.STRING\n \"\n >\n <p-multiSelect\n [options]=\"filters[composedName]?.options\"\n [ngModel]=\"filters[composedName]?.value\"\n (ngModelChange)=\"\n onComposedFilterValueChange(\n col,\n composedName,\n $event,\n filterModel\n )\n \"\n [placeholder]=\"filters[composedName]?.placeholder\"\n display=\"chip\"\n >\n <ng-template let-item pTemplate=\"item\">\n <div class=\"custom-multiselect-item\">\n <img\n *ngIf=\"item.image\"\n [src]=\"item.image\"\n alt=\"icon\"\n class=\"filter-image\"\n />\n <span>{{ item.label }}</span>\n </div>\n </ng-template>\n </p-multiSelect>\n </ng-container>\n </div>\n </ng-template>\n </p-columnFilter>\n\n <!-- OTHER TYPES -->\n <p-columnFilter\n *ngIf=\"col.type !== TableTypeEnum.COMPOSED\"\n display=\"menu\"\n [field]=\"col.code\"\n [type]=\"getColumnFilterType(col)\"\n [showApplyButton]=\"true\"\n [showClearButton]=\"true\"\n (onClear)=\"onFilterClear(col.code!)\"\n >\n <!-- NUMBER / AMOUNT: use text input so '.' works -->\n <ng-template\n pTemplate=\"filter\"\n *ngIf=\"\n col.type === TableTypeEnum.NUMBER ||\n col.type === TableTypeEnum.AMOUNT\n \"\n let-value\n >\n <input\n pInputText\n type=\"text\"\n inputmode=\"decimal\"\n [ngModel]=\"latestFilterValues[col.code!] ?? value\"\n (ngModelChange)=\"\n onNumberFilterChange(col.code!, $event)\n \"\n placeholder=\"Enter a number\"\n />\n </ng-template>\n\n <!-- DATE -->\n <ng-template\n pTemplate=\"filter\"\n *ngIf=\"col.type === TableTypeEnum.DATE\"\n let-filterModel=\"filterModel\"\n >\n <p-calendar\n [ngModel]=\"\n latestFilterValues[col.code!] ?? filterModel?.value\n \"\n (ngModelChange)=\"\n onFilterValueChange(col.code!, filterModel, $event)\n \"\n dateFormat=\"dd/mm/yy\"\n placeholder=\"Choose a date\"\n ></p-calendar>\n </ng-template>\n\n <!-- MULTISELECT -->\n <ng-template\n pTemplate=\"filter\"\n *ngIf=\"\n col.type === TableTypeEnum.MULTISELECT &&\n col.filterOptions &&\n col.filterOptions.length > 0\n \"\n let-filterModel=\"filterModel\"\n >\n <p-multiSelect\n [options]=\"col.filterOptions\"\n [ngModel]=\"\n latestFilterValues[col.code!] ?? filterModel?.value\n \"\n (ngModelChange)=\"\n onFilterValueChange(col.code!, filterModel, $event)\n \"\n display=\"chip\"\n placeholder=\"Choose option\"\n class=\"custom-multiselect\"\n ></p-multiSelect>\n </ng-template>\n </p-columnFilter>\n </ng-container>\n </div>\n </div>\n </ng-container>\n\n <!-- NON-SORTABLE HEADER -->\n <ng-template #noSortHeader>\n <div\n class=\"header-container d-flex align-items-center justify-content-between\"\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [style.padding]=\"'0px'\"\n [style.margin]=\"'10px'\"\n >\n <span [ngClass]=\"getHeaderTitleClass(col)\">\n {{ col.title }}\n </span>\n\n <ng-container *ngIf=\"hasColumnFilter && col.isFilter !== false\">\n <!-- AMOUNT behaves like NUMBER -->\n <p-columnFilter\n *ngIf=\"col.type === 'AMOUNT'\"\n display=\"menu\"\n [field]=\"col.code\"\n [type]=\"getColumnFilterType(col)\"\n [currency]=\"getCurrencySymbol(col)\"\n [showApplyButton]=\"true\"\n [showClearButton]=\"true\"\n >\n <ng-template\n pTemplate=\"filter\"\n let-filterModel=\"filterModel\"\n >\n <input\n pInputText\n type=\"text\"\n inputmode=\"decimal\"\n [ngModel]=\"\n latestFilterValues[col.code!] ?? filterModel?.value\n \"\n (ngModelChange)=\"\n onFilterValueChange(col.code!, filterModel, $event)\n \"\n placeholder=\"Enter an amount\"\n />\n </ng-template>\n </p-columnFilter>\n\n <p-columnFilter\n *ngIf=\"col.type !== 'AMOUNT'\"\n display=\"menu\"\n [field]=\"col.code\"\n [type]=\"getColumnFilterType(col)\"\n [showApplyButton]=\"true\"\n [showClearButton]=\"true\"\n >\n <!-- DATE -->\n <ng-template\n pTemplate=\"filter\"\n let-filterModel=\"filterModel\"\n *ngIf=\"getColumnFilterType(col) === 'date'\"\n >\n <p-calendar\n [ngModel]=\"\n latestFilterValues[col.code!] ?? filterModel?.value\n \"\n (ngModelChange)=\"\n onFilterValueChange(col.code!, filterModel, $event)\n \"\n dateFormat=\"dd/mm/yy\"\n ></p-calendar>\n </ng-template>\n\n <!-- MULTISELECT -->\n <ng-template\n pTemplate=\"filter\"\n let-filterModel=\"filterModel\"\n *ngIf=\"getColumnFilterType(col) === 'multiSelect'\"\n >\n <p-multiSelect\n [options]=\"col.filterOptions\"\n [ngModel]=\"\n latestFilterValues[col.code!] ?? filterModel?.value\n \"\n (ngModelChange)=\"\n onFilterValueChange(col.code!, filterModel, $event)\n \"\n display=\"chip\"\n placeholder=\"Select\"\n class=\"custom-multiselect\"\n ></p-multiSelect>\n </ng-template>\n </p-columnFilter>\n </ng-container>\n </div>\n </ng-template>\n </th>\n\n <!-- GROUPED HEADER -->\n <ng-template #groupHeader>\n <th\n [attr.colspan]=\"col.children?.length\"\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [ngClass]=\"getHeaderAlignClass(col)\"\n >\n <span>{{ col.title }}</span>\n </th>\n </ng-template>\n </ng-container>\n </tr>\n\n <!-- CHILD HEADERS -->\n <tr *ngIf=\"hasGroupedColumns\">\n <ng-container *ngFor=\"let col of columns\">\n <ng-container *ngIf=\"col.children\">\n <th\n *ngFor=\"let child of col.children\"\n [style.width]=\"child.width || getHeaderWidth(child)\"\n [style.padding]=\"'0px'\"\n ></th>\n </ng-container>\n </ng-container>\n </tr>\n </ng-template>\n\n <!-- EMPTY MESSAGE -->\n <ng-template pTemplate=\"emptymessage\">\n <tr class=\"p-datatable-emptymessage\">\n <!-- span all columns -->\n <td class=\"empty-message-cell\" [attr.colspan]=\"columns.length || 1\">\n <div class=\"empty-message-wrapper\">\n <div class=\"empty-message\">\n <i class=\"pi pi-info-circle\"></i>\n <p>No records available to display.</p>\n </div>\n </div>\n </td>\n </tr>\n </ng-template>\n\n <!-- BODY -->\n <ng-template\n pTemplate=\"body\"\n let-data\n let-editing=\"editing\"\n let-ri=\"rowIndex\"\n >\n <tr *ngIf=\"!loading\" [pEditableRow]=\"isEdit ? data : null\">\n <ng-container *ngFor=\"let col of columns\">\n <!-- SIMPLE COLUMNS (no children) -->\n <ng-container *ngIf=\"!col.children; else childColumns\">\n <!-- EDITABLE CELL -->\n <td\n *ngIf=\"\n isEditable(col.code!) && col.type !== TableTypeEnum.ACTION;\n else normalTD\n \"\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [ngClass]=\"getDataAlignClass(col)\"\n >\n <!-- Editable input for NUMBER/DATE/STRING/MULTISELECT -->\n <ng-container *ngIf=\"isMultiSelect(col.code); else datePicker\">\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <p-multiSelect\n appendTo=\"body\"\n [ngModel]=\"data[col.code!]\"\n [style]=\"{ width: '100%' }\"\n (ngModelChange)=\"changeHandler(data.id, col.code, $event)\"\n [options]=\"optionValues\"\n ></p-multiSelect>\n </ng-template>\n <ng-template pTemplate=\"output\">\n <div class=\"multi-select-container\">\n <ng-container *ngFor=\"let rec of data[col.code!]\">\n <p-tag [value]=\"rec\"></p-tag>\n </ng-container>\n </div>\n </ng-template>\n </p-cellEditor>\n </ng-container>\n\n <ng-template #datePicker>\n <ng-container *ngIf=\"isDatePicker(col.code); else normalInput\">\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <p-calendar\n [inputId]=\"data[col.code!]\"\n [ngModel]=\"data[col.code!]\"\n (ngModelChange)=\"\n changeHandler(data.id, col.code, $event)\n \"\n [dateFormat]=\"'dd/mm/yy'\"\n ></p-calendar>\n </ng-template>\n <ng-template pTemplate=\"output\">\n {{ data[col.code!] | customDate }}\n </ng-template>\n </p-cellEditor>\n </ng-container>\n </ng-template>\n\n <ng-template #normalInput>\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <input\n pInputText\n type=\"text\"\n [ngModel]=\"data[col.code!]\"\n (change)=\"onChange($event, data.id, col.code)\"\n />\n </ng-template>\n <ng-template pTemplate=\"output\">\n <ng-container\n *ngIf=\"\n col.type === TableTypeEnum.AMOUNT;\n else normalOutput\n \"\n >\n {{\n data[col.code!]\n | customCurrency\n : getCurrencySymbol(col)\n : col.decimalPlaces\n : col.thousandSeparator\n : col.decimalSeparator\n }}\n </ng-container>\n <ng-template #normalOutput>\n {{ data[col.code!] }}\n </ng-template>\n </ng-template>\n </p-cellEditor>\n </ng-template>\n </td>\n\n <!-- NON-EDITABLE CELL (ALWAYS RENDERED) -->\n <ng-template #normalTD>\n <td\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [ngClass]=\"[\n getDataAlignClass(col),\n col.type === TableTypeEnum.ACTION ? 'action-column' : ''\n ]\"\n >\n <!-- ACTION column: built-in edit/delete + custom actions -->\n <ng-container\n *ngIf=\"col.type === TableTypeEnum.ACTION; else nonActionCell\"\n >\n <div class=\"action-buttons-container\">\n <!-- built-in delete -->\n <button\n *ngIf=\"isDelete\"\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-trash\"\n (click)=\"Delete(data.id)\"\n class=\"p-button-rounded p-button-text\"\n ></button>\n\n <!-- built-in inline edit -->\n <div *ngIf=\"isEdit\">\n <button\n pInitEditableRow\n *ngIf=\"!editing\"\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-pencil\"\n (click)=\"initEditableRow(data)\"\n class=\"p-button-rounded p-button-text\"\n ></button>\n <button\n *ngIf=\"editing\"\n pSaveEditableRow\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-check\"\n (click)=\"saveEditableRow(data)\"\n class=\"p-button-rounded p-button-text\"\n ></button>\n <button\n *ngIf=\"editing\"\n pCancelEditableRow\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-times\"\n (click)=\"cancelEditableRow(data)\"\n class=\"p-button-rounded p-button-text\"\n ></button>\n </div>\n\n <!-- custom actions -->\n <button\n *ngFor=\"let act of customActions\"\n pButton\n pRipple\n type=\"button\"\n class=\"p-button-rounded p-button-text\"\n [icon]=\"act.icon || 'pi pi-ellipsis-h'\"\n [ngClass]=\"act.styleClass\"\n (click)=\"onCustomActionClick(act, data)\"\n ></button>\n </div>\n </ng-container>\n\n <!-- NON-ACTION cells -->\n <ng-template #nonActionCell>\n <!-- COMPOSED -->\n <ng-container\n *ngIf=\"\n col.type === TableTypeEnum.COMPOSED;\n else nonComposed\n \"\n >\n <div class=\"composed-cell\">\n <ng-container\n *ngFor=\"\n let composedName of col.composedNames;\n let i = index\n \"\n >\n <!-- IMAGE -->\n <ng-container\n *ngIf=\"\n col.composedTypes &&\n col.composedTypes[i] === TableTypeEnum.IMAGE\n \"\n >\n <img\n [src]=\"data[col.code!]?.[composedName]\"\n alt=\"composed-img\"\n class=\"composed-image\"\n [ngStyle]=\"\n getImageStyle(col.composedStyles?.[composedName])\n \"\n />\n </ng-container>\n\n <!-- STRING -->\n <ng-container\n *ngIf=\"\n col.composedTypes &&\n col.composedTypes[i] === TableTypeEnum.STRING\n \"\n >\n <span\n class=\"composed-text\"\n [ngStyle]=\"\n getTitleStyle(\n col.composedStyles?.[composedName]\n )\n \"\n >\n {{ data[col.code!]?.[composedName] }}\n </span>\n </ng-container>\n </ng-container>\n </div>\n </ng-container>\n\n <ng-template #nonComposed>\n <!-- AMOUNT-->\n <ng-container\n *ngIf=\"col.type === TableTypeEnum.AMOUNT; else nonAmount\"\n >\n {{\n data[col.code!]\n | customCurrency\n : getCurrencySymbol(col)\n : col.decimalPlaces\n : col.thousandSeparator\n : col.decimalSeparator\n }}\n </ng-container>\n\n <ng-template #nonAmount>\n <!-- NUMBER-->\n <ng-container\n *ngIf=\"\n col.type === TableTypeEnum.NUMBER;\n else nonNumber\n \"\n >\n {{\n formatNumber(\n data[col.code!],\n col.decimalPlaces,\n col.thousandSeparator,\n col.decimalSeparator\n )\n }}\n </ng-container>\n\n <ng-template #nonNumber>\n <!-- DATE -->\n <ng-container\n *ngIf=\"\n col.type === TableTypeEnum.DATE;\n else normalTypes\n \"\n >\n {{ formatDate(data[col.code!]) }}\n </ng-container>\n\n <ng-template #normalTypes>\n <!-- STRING, MULTISELECT-->\n <ng-container\n *ngIf=\"\n [\n TableTypeEnum.STRING,\n TableTypeEnum.MULTISELECT\n ].includes(col.type!)\n \"\n >\n {{ data[col.code!] }}\n </ng-container>\n </ng-template>\n </ng-template>\n </ng-template>\n </ng-template>\n </ng-template>\n </td>\n </ng-template>\n </ng-container>\n\n <!-- CHILD COLUMNS -->\n <ng-template #childColumns>\n <ng-container *ngFor=\"let child of col.children\">\n <td\n [style.width]=\"child.width || getHeaderWidth(child)\"\n [ngClass]=\"getDataAlignClass(child)\"\n >\n <ng-container\n *ngIf=\"isEditable(child.code); else childNormalTD\"\n >\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <input\n pInputText\n type=\"text\"\n [ngModel]=\"child.code ? data[child.code] : null\"\n (change)=\"onChange($event, data.id, child.code)\"\n />\n </ng-template>\n <ng-template pTemplate=\"output\">\n {{ child.code ? data[child.code] : \"\" }}\n </ng-template>\n </p-cellEditor>\n </ng-container>\n\n <ng-template #childNormalTD>\n {{ child.code ? data[child.code] : \"\" }}\n </ng-template>\n </td>\n </ng-container>\n </ng-template>\n </ng-container>\n </tr>\n </ng-template>\n </p-table>\n</div>\n", styles: [".pt-advanced-prime-table .bread-crumb{margin-bottom:15px}.pt-advanced-prime-table .date{width:100%;height:5rem;display:grid;justify-items:start;align-items:center}.pt-advanced-prime-table .filter-container{width:100%;display:flex;justify-content:space-between;align-items:center}.pt-advanced-prime-table .settings{display:flex;gap:1rem}.pt-advanced-prime-table .multi-select-container{display:flex;justify-content:center;align-items:center;gap:.3rem}.pt-advanced-prime-table ::ng-deep p-table{min-width:50rem}.pt-advanced-prime-table ::ng-deep .custom-multiselect .p-hidden-accessible input{display:none}.pt-advanced-prime-table ::ng-deep .p-datatable .p-sortable-column.p-highlight:hover{background:none}.pt-advanced-prime-table ::ng-deep .p-datatable .p-sortable-column:focus{box-shadow:none;outline:0 none}.pt-advanced-prime-table ::ng-deep .header-container{display:flex;justify-content:space-between;align-items:center;width:100%}.pt-advanced-prime-table ::ng-deep .header-title-left,.pt-advanced-prime-table ::ng-deep .header-title-center,.pt-advanced-prime-table ::ng-deep .header-title-right{flex:1}.pt-advanced-prime-table ::ng-deep .header-title-left{text-align:left}.pt-advanced-prime-table ::ng-deep .header-title-center{text-align:center}.pt-advanced-prime-table ::ng-deep .header-title-right{text-align:right}.pt-advanced-prime-table ::ng-deep .header-align-left{text-align:left}.pt-advanced-prime-table ::ng-deep .header-align-center{text-align:center}.pt-advanced-prime-table ::ng-deep .header-align-right{text-align:right}.pt-advanced-prime-table ::ng-deep p-columnfilter.p-element.ng-star-inserted{margin-top:4px}.pt-advanced-prime-table .flex{display:flex;justify-content:space-between;align-items:center}.pt-advanced-prime-table .ml-auto{margin-left:auto}.pt-advanced-prime-table ::ng-deep p-inputicon{margin-right:-1.5rem;z-index:2;position:relative}.pt-advanced-prime-table ::ng-deep .p-inputtext{padding-left:1.7rem}.pt-advanced-prime-table ::ng-deep .bt-filter-btn button{cursor:pointer;margin-left:1rem}.pt-advanced-prime-table ::ng-deep .p-icon-field-left .p-input-icon:first-of-type{left:-1rem}.pt-advanced-prime-table .table-row{text-align:center;display:flex;gap:1rem;justify-content:center}.pt-advanced-prime-table ::ng-deep span.p-button-icon.pi.pi-file-excel{font-size:1.25em;color:green}.pt-advanced-prime-table ::ng-deep span.p-button-icon.pi.pi-file-pdf{font-size:1.25em;color:red}.pt-advanced-prime-table .table-container{display:block;width:100%}.pt-advanced-prime-table ::ng-deep .p-datatable-emptymessage>td.empty-message-cell{padding:0!important}.pt-advanced-prime-table .empty-message-wrapper{width:100%;height:100%;min-height:180px;display:flex;align-items:center;justify-content:center}.pt-advanced-prime-table .empty-message{text-align:center;color:#888;font-size:1.2rem}.pt-advanced-prime-table .empty-message i{display:block;font-size:2rem;margin-bottom:.5rem}.pt-advanced-prime-table th{white-space:normal;word-wrap:break-word}.filter-image{width:22px;height:14px;margin-right:5px}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr>td.cell-align-left{text-align:left!important}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr>td.cell-align-center{text-align:center!important}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr>td.cell-align-right{text-align:right!important}.pt-advanced-prime-table ::ng-deep th.action-column,.pt-advanced-prime-table ::ng-deep td.action-column{text-align:center!important;justify-content:center;align-items:center;overflow:hidden;white-space:nowrap;padding:0}.pt-advanced-prime-table ::ng-deep .action-buttons-container{width:100%;display:flex;justify-content:center!important;align-items:center!important;gap:.35rem}.pt-advanced-prime-table ::ng-deep .action-buttons-container .p-button.p-button-rounded.p-button-text{padding:.25rem!important;min-width:22px!important;height:22px!important}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: i2.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "style", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "scrollDirection", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "responsive", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "autoLayout", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll", "virtualRowHeight"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "directive", type: i1$1.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "directive", type: i2.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { kind: "component", type: i2.CellEditor, selector: "p-cellEditor" }, { kind: "component", type: i2.SortIcon, selector: "p-sortIcon", inputs: ["field"] }, { kind: "directive", type: i2.EditableRow, selector: "[pEditableRow]", inputs: ["pEditableRow", "pEditableRowDisabled"] }, { kind: "directive", type: i2.InitEditableRow, selector: "[pInitEditableRow]" }, { kind: "directive", type: i2.SaveEditableRow, selector: "[pSaveEditableRow]" }, { kind: "directive", type: i2.CancelEditableRow, selector: "[pCancelEditableRow]" }, { kind: "component", type: i2.ColumnFilter, selector: "p-columnFilter", inputs: ["field", "type", "display", "showMenu", "matchMode", "operator", "showOperator", "showClearButton", "showApplyButton", "showMatchModes", "showAddButton", "hideOnClear", "placeholder", "matchModeOptions", "maxConstraints", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "locale", "localeMatcher", "currency", "currencyDisplay", "useGrouping", "showButtons", "ariaLabel"], outputs: ["onShow", "onHide"] }, { kind: "directive", type: i4.InputText, selector: "[pInputText]", inputs: ["variant"] }, { kind: "directive", type: i3.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "label", "icon", "loading", "severity", "raised", "rounded", "text", "outlined", "size", "plain"] }, { kind: "component", type: i6.Calendar, selector: "p-calendar", inputs: ["iconDisplay", "style", "styleClass", "inputStyle", "inputId", "name", "inputStyleClass", "placeholder", "ariaLabelledBy", "ariaLabel", "iconAriaLabel", "disabled", "dateFormat", "multipleSeparator", "rangeSeparator", "inline", "showOtherMonths", "selectOtherMonths", "showIcon", "icon", "appendTo", "readonlyInput", "shortYearCutoff", "monthNavigator", "yearNavigator", "hourFormat", "timeOnly", "stepYearPicker", "stepHour", "stepMinute", "stepSecond", "showSeconds", "required", "showOnFocus", "showWeek", "startWeekFromFirstDayOfYear", "showClear", "dataType", "selectionMode", "maxDateCount", "showButtonBar", "todayButtonStyleClass", "clearButtonStyleClass", "autofocus", "autoZIndex", "baseZIndex", "panelStyleClass", "panelStyle", "keepInvalid", "hideOnDateTimeSelect", "touchUI", "timeSeparator", "focusTrap", "showTransitionOptions", "hideTransitionOptions", "tabindex", "variant", "minDate", "maxDate", "disabledDates", "disabledDays", "yearRange", "showTime", "responsiveOptions", "numberOfMonths", "firstDayOfWeek", "locale", "view", "defaultDate"], outputs: ["onFocus", "onBlur", "onClose", "onSelect", "onClear", "onInput", "onTodayClick", "onClearClick", "onMonthChange", "onYearChange", "onClickOutside", "onShow"] }, { kind: "directive", type: i2$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i8.MultiSelect, selector: "p-multiSelect", inputs: ["id", "ariaLabel", "style", "styleClass", "panelStyle", "panelStyleClass", "inputId", "disabled", "readonly", "group", "filter", "filterPlaceHolder", "filterLocale", "overlayVisible", "tabindex", "variant", "appendTo", "dataKey", "name", "ariaLabelledBy", "displaySelectedLabel", "maxSelectedLabels", "selectionLimit", "selectedItemsLabel", "showToggleAll", "emptyFilterMessage", "emptyMessage", "resetFilterOnHide", "dropdownIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "showHeader", "filterBy", "scrollHeight", "lazy", "virtualScroll", "loading", "virtualScrollItemSize", "loadingIcon", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "display", "autocomplete", "showClear", "autofocus", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "defaultLabel", "placeholder", "options", "filterValue", "itemSize", "selectAll", "focusOnHover", "filterFields", "selectOnFocus", "autoOptionFocus"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onClear", "onPanelShow", "onPanelHide", "onLazyLoad", "onRemove", "onSelectAllChange"] }, { kind: "component", type: i9.Tag, selector: "p-tag", inputs: ["style", "styleClass", "severity", "value", "icon", "rounded"] }, { kind: "component", type: i10.IconField, selector: "p-iconField", inputs: ["iconPosition"] }, { kind: "component", type: i11.InputIcon, selector: "p-inputIcon", inputs: ["styleClass"] }, { kind: "pipe", type: CustomCurrencyPipe, name: "customCurrency" }, { kind: "pipe", type: CustomDatePipe, name: "customDate" }] }); }
|
|
822
867
|
}
|
|
823
868
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: PTAdvancedPrimeTableComponent, decorators: [{
|
|
824
869
|
type: Component,
|
|
825
|
-
args: [{ selector: 'pt-advanced-prime-table', template: "<div class=\"pt-advanced-prime-table table-container\">\n <p-table\n #dt\n [value]=\"data\"\n [loading]=\"loading\"\n [rows]=\"rows\"\n [paginator]=\"isPaginated\"\n [globalFilterFields]=\"globalFilterFields\"\n [rowsPerPageOptions]=\"rowsPerPage\"\n [totalRecords]=\"totalRecords\"\n [lazy]=\"isPaginated\"\n dataKey=\"id\"\n styleClass=\"p-datatable-gridlines p-datatable-striped\"\n [scrollable]=\"true\"\n [scrollHeight]=\"maxHeight !== null ? maxHeight : undefined\"\n (onFilter)=\"filterColumn($event)\"\n (onPage)=\"changePage($event)\"\n (onSort)=\"sortColumn($event)\"\n >\n <!-- COLGROUP: sync header/body widths -->\n <ng-template pTemplate=\"colgroup\" let-columns>\n <colgroup>\n <col\n *ngFor=\"let col of columns\"\n [style.width]=\"col.width || getHeaderWidth(col)\"\n />\n </colgroup>\n </ng-template>\n\n <!-- CAPTION -->\n <ng-template pTemplate=\"caption\">\n <div class=\"flex\">\n <div>\n <h3>Total: {{ totalRecords }}</h3>\n </div>\n\n <div>\n <!-- Clear filters -->\n <button\n *ngIf=\"hasSearchFilter\"\n pButton\n icon=\"pi pi-filter-slash\"\n class=\"p-button-rounded p-button-text\"\n (click)=\"clear(dt)\"\n title=\"Clear filters\"\n ></button>\n\n <!-- Export to Excel Button -->\n <button\n *ngIf=\"hasExportExcel\"\n pButton\n icon=\"pi pi-file-excel\"\n class=\"p-button-rounded p-button-text\"\n (click)=\"exportExcel()\"\n title=\"Export to Excel\"\n ></button>\n\n <!-- Export to PDF Button -->\n <button\n *ngIf=\"hasExportPDF\"\n pButton\n icon=\"pi pi-file-pdf\"\n class=\"p-button-rounded p-button-text\"\n (click)=\"exportPdf()\"\n title=\"Export to PDF\"\n ></button>\n </div>\n\n <div class=\"ml-auto\" *ngIf=\"hasSearchFilter\">\n <p-iconField iconPosition=\"left\" class=\"ml-auto\">\n <p-inputIcon>\n <i class=\"pi pi-search\"></i>\n </p-inputIcon>\n <input\n pInputText\n type=\"text\"\n [(ngModel)]=\"searchValue\"\n (input)=\"filterGlobal($event)\"\n placeholder=\"Search keyword\"\n />\n </p-iconField>\n </div>\n </div>\n </ng-template>\n\n <!-- HEADER -->\n <ng-template pTemplate=\"header\">\n <tr class=\"sticky-header\">\n <ng-container *ngFor=\"let col of columns\">\n <th\n *ngIf=\"!col.children; else groupHeader\"\n pSortableColumn=\"{{ col.code }}\"\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [style.padding]=\"'0px'\"\n [ngClass]=\"[\n getHeaderAlignClass(col),\n col.type === TableTypeEnum.ACTION ? 'action-column' : ''\n ]\"\n colspan=\"1\"\n >\n <!-- SORTABLE HEADER -->\n <ng-container\n *ngIf=\"isSortable && col.isSortable !== false; else noSortHeader\"\n >\n <div\n class=\"header-container d-flex align-items-center justify-content-between\"\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [style.padding]=\"'0px'\"\n [style.margin]=\"'10px'\"\n >\n <span [ngClass]=\"getHeaderTitleClass(col)\">\n {{ col.title }}\n </span>\n <div\n class=\"icons d-flex align-items-center\"\n [style.width]=\"'77px'\"\n >\n <p-sortIcon field=\"{{ col.code }}\" />\n\n <!-- COLUMN FILTERS -->\n <ng-container\n *ngIf=\"hasColumnFilter && col.isFilter !== false\"\n >\n <!-- COMPOSED FILTER (uses built-in Apply/Clear) -->\n <p-columnFilter\n *ngIf=\"col.type === TableTypeEnum.COMPOSED\"\n display=\"menu\"\n [field]=\"col.code\"\n type=\"text\"\n [showApplyButton]=\"true\"\n [showClearButton]=\"true\"\n (onClear)=\"onComposedColumnClear(col)\"\n >\n <ng-template\n pTemplate=\"filter\"\n let-filter=\"filterCallback\"\n let-filterModel=\"filterModel\"\n >\n <div *ngFor=\"let composedName of col.composedNames\">\n <ng-container\n *ngIf=\"\n getComposedFieldType(col, composedName) ===\n TableTypeEnum.STRING\n \"\n >\n <p-multiSelect\n [options]=\"filters[composedName]?.options\"\n [ngModel]=\"filters[composedName]?.value\"\n (ngModelChange)=\"\n onComposedFilterValueChange(\n col,\n composedName,\n $event,\n filterModel\n )\n \"\n [placeholder]=\"filters[composedName]?.placeholder\"\n display=\"chip\"\n >\n <ng-template let-item pTemplate=\"item\">\n <div class=\"custom-multiselect-item\">\n <img\n *ngIf=\"item.image\"\n [src]=\"item.image\"\n alt=\"icon\"\n class=\"filter-image\"\n />\n <span>{{ item.label }}</span>\n </div>\n </ng-template>\n </p-multiSelect>\n </ng-container>\n </div>\n </ng-template>\n </p-columnFilter>\n\n <!-- OTHER TYPES -->\n <p-columnFilter\n *ngIf=\"col.type !== TableTypeEnum.COMPOSED\"\n display=\"menu\"\n [field]=\"col.code\"\n [type]=\"getColumnFilterType(col)\"\n [showApplyButton]=\"true\"\n [showClearButton]=\"true\"\n >\n <!-- NUMBER -->\n <ng-template\n pTemplate=\"filter\"\n *ngIf=\"col.type === TableTypeEnum.NUMBER\"\n let-filterModel=\"filterModel\"\n >\n <input\n pInputText\n type=\"number\"\n [step]=\"\n col.decimalPlaces\n ? '0.' + '1'.padEnd(col.decimalPlaces, '0')\n : 'any'\n \"\n [ngModel]=\"\n latestFilterValues[col.code!] ?? filterModel?.value\n \"\n (ngModelChange)=\"\n onFilterValueChange(col.code!, filterModel, $event)\n \"\n placeholder=\"Enter a number\"\n />\n </ng-template>\n\n <!-- DATE -->\n <ng-template\n pTemplate=\"filter\"\n *ngIf=\"col.type === TableTypeEnum.DATE\"\n let-filterModel=\"filterModel\"\n >\n <p-calendar\n [ngModel]=\"\n latestFilterValues[col.code!] ?? filterModel?.value\n \"\n (ngModelChange)=\"\n onFilterValueChange(col.code!, filterModel, $event)\n \"\n dateFormat=\"dd/mm/yy\"\n placeholder=\"Choose a date\"\n ></p-calendar>\n </ng-template>\n\n <!-- MULTISELECT -->\n <ng-template\n pTemplate=\"filter\"\n *ngIf=\"\n col.type === TableTypeEnum.MULTISELECT &&\n col.filterOptions &&\n col.filterOptions.length > 0\n \"\n let-filterModel=\"filterModel\"\n >\n <p-multiSelect\n [options]=\"col.filterOptions\"\n [ngModel]=\"\n latestFilterValues[col.code!] ?? filterModel?.value\n \"\n (ngModelChange)=\"\n onFilterValueChange(col.code!, filterModel, $event)\n \"\n display=\"chip\"\n placeholder=\"Choose option\"\n class=\"custom-multiselect\"\n ></p-multiSelect>\n </ng-template>\n </p-columnFilter>\n </ng-container>\n </div>\n </div>\n </ng-container>\n\n <!-- NON-SORTABLE HEADER -->\n <ng-template #noSortHeader>\n <div\n class=\"header-container d-flex align-items-center justify-content-between\"\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [style.padding]=\"'0px'\"\n [style.margin]=\"'10px'\"\n >\n <span [ngClass]=\"getHeaderTitleClass(col)\">\n {{ col.title }}\n </span>\n\n <ng-container *ngIf=\"hasColumnFilter && col.isFilter !== false\">\n <!-- AMOUNT behaves like NUMBER -->\n <p-columnFilter\n *ngIf=\"col.type === 'AMOUNT'\"\n display=\"menu\"\n [field]=\"col.code\"\n [type]=\"getColumnFilterType(col)\"\n [currency]=\"getCurrencySymbol(col)\"\n [showApplyButton]=\"true\"\n [showClearButton]=\"true\"\n >\n <ng-template\n pTemplate=\"filter\"\n let-filterModel=\"filterModel\"\n >\n <input\n pInputText\n type=\"number\"\n [step]=\"\n col.decimalPlaces\n ? '0.' + '1'.padEnd(col.decimalPlaces, '0')\n : 'any'\n \"\n [ngModel]=\"\n latestFilterValues[col.code!] ?? filterModel?.value\n \"\n (ngModelChange)=\"\n onFilterValueChange(col.code!, filterModel, $event)\n \"\n placeholder=\"Enter an amount\"\n />\n </ng-template>\n </p-columnFilter>\n\n <p-columnFilter\n *ngIf=\"col.type !== 'AMOUNT'\"\n display=\"menu\"\n [field]=\"col.code\"\n [type]=\"getColumnFilterType(col)\"\n [showApplyButton]=\"true\"\n [showClearButton]=\"true\"\n >\n <!-- DATE -->\n <ng-template\n pTemplate=\"filter\"\n let-filterModel=\"filterModel\"\n *ngIf=\"getColumnFilterType(col) === 'date'\"\n >\n <p-calendar\n [ngModel]=\"\n latestFilterValues[col.code!] ?? filterModel?.value\n \"\n (ngModelChange)=\"\n onFilterValueChange(col.code!, filterModel, $event)\n \"\n dateFormat=\"dd/mm/yy\"\n ></p-calendar>\n </ng-template>\n\n <!-- MULTISELECT -->\n <ng-template\n pTemplate=\"filter\"\n let-filterModel=\"filterModel\"\n *ngIf=\"getColumnFilterType(col) === 'multiSelect'\"\n >\n <p-multiSelect\n [options]=\"col.filterOptions\"\n [ngModel]=\"\n latestFilterValues[col.code!] ?? filterModel?.value\n \"\n (ngModelChange)=\"\n onFilterValueChange(col.code!, filterModel, $event)\n \"\n display=\"chip\"\n placeholder=\"Select\"\n class=\"custom-multiselect\"\n ></p-multiSelect>\n </ng-template>\n </p-columnFilter>\n </ng-container>\n </div>\n </ng-template>\n </th>\n\n <!-- GROUPED HEADER -->\n <ng-template #groupHeader>\n <th\n [attr.colspan]=\"col.children?.length\"\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [ngClass]=\"getHeaderAlignClass(col)\"\n >\n <span>{{ col.title }}</span>\n </th>\n </ng-template>\n </ng-container>\n </tr>\n\n <!-- CHILD HEADERS -->\n <tr *ngIf=\"hasGroupedColumns\">\n <ng-container *ngFor=\"let col of columns\">\n <ng-container *ngIf=\"col.children\">\n <th\n *ngFor=\"let child of col.children\"\n [style.width]=\"child.width || getHeaderWidth(child)\"\n [style.padding]=\"'0px'\"\n ></th>\n </ng-container>\n </ng-container>\n </tr>\n </ng-template>\n\n <!-- EMPTY MESSAGE -->\n <ng-template pTemplate=\"emptymessage\">\n <tr class=\"p-datatable-emptymessage\">\n <!-- span all columns -->\n <td class=\"empty-message-cell\" [attr.colspan]=\"columns.length || 1\">\n <div class=\"empty-message-wrapper\">\n <div class=\"empty-message\">\n <i class=\"pi pi-info-circle\"></i>\n <p>No records available to display.</p>\n </div>\n </div>\n </td>\n </tr>\n </ng-template>\n\n <!-- BODY -->\n <ng-template\n pTemplate=\"body\"\n let-data\n let-editing=\"editing\"\n let-ri=\"rowIndex\"\n >\n <tr *ngIf=\"!loading\" [pEditableRow]=\"isEdit ? data : null\">\n <ng-container *ngFor=\"let col of columns\">\n <!-- SIMPLE COLUMNS (no children) -->\n <ng-container *ngIf=\"!col.children; else childColumns\">\n <!-- EDITABLE CELL -->\n <td\n *ngIf=\"\n isEditable(col.code!) && col.type !== TableTypeEnum.ACTION;\n else normalTD\n \"\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [ngClass]=\"getDataAlignClass(col)\"\n >\n <!-- Editable input for NUMBER/DATE/STRING/MULTISELECT -->\n <ng-container *ngIf=\"isMultiSelect(col.code); else datePicker\">\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <p-multiSelect\n appendTo=\"body\"\n [ngModel]=\"data[col.code!]\"\n [style]=\"{ width: '100%' }\"\n (ngModelChange)=\"changeHandler(data.id, col.code, $event)\"\n [options]=\"optionValues\"\n ></p-multiSelect>\n </ng-template>\n <ng-template pTemplate=\"output\">\n <div class=\"multi-select-container\">\n <ng-container *ngFor=\"let rec of data[col.code!]\">\n <p-tag [value]=\"rec\"></p-tag>\n </ng-container>\n </div>\n </ng-template>\n </p-cellEditor>\n </ng-container>\n\n <ng-template #datePicker>\n <ng-container *ngIf=\"isDatePicker(col.code); else normalInput\">\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <p-calendar\n [inputId]=\"data[col.code!]\"\n [ngModel]=\"data[col.code!]\"\n (ngModelChange)=\"\n changeHandler(data.id, col.code, $event)\n \"\n [dateFormat]=\"'dd/mm/yy'\"\n ></p-calendar>\n </ng-template>\n <ng-template pTemplate=\"output\">\n {{ data[col.code!] | customDate }}\n </ng-template>\n </p-cellEditor>\n </ng-container>\n </ng-template>\n\n <ng-template #normalInput>\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <input\n pInputText\n type=\"text\"\n [ngModel]=\"data[col.code!]\"\n (change)=\"onChange($event, data.id, col.code)\"\n />\n </ng-template>\n <ng-template pTemplate=\"output\">\n <ng-container\n *ngIf=\"\n col.type === TableTypeEnum.AMOUNT;\n else normalOutput\n \"\n >\n {{\n data[col.code!]\n | customCurrency\n : getCurrencySymbol(col)\n : col.decimalPlaces\n : col.thousandSeparator\n : col.decimalSeparator\n }}\n </ng-container>\n <ng-template #normalOutput>\n {{ data[col.code!] }}\n </ng-template>\n </ng-template>\n </p-cellEditor>\n </ng-template>\n </td>\n\n <!-- NON-EDITABLE CELL (ALWAYS RENDERED) -->\n <ng-template #normalTD>\n <td\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [ngClass]=\"[\n getDataAlignClass(col),\n col.type === TableTypeEnum.ACTION ? 'action-column' : ''\n ]\"\n >\n <!-- ACTION column: built-in edit/delete + custom actions -->\n <ng-container\n *ngIf=\"col.type === TableTypeEnum.ACTION; else nonActionCell\"\n >\n <div class=\"action-buttons-container\">\n <!-- built-in delete -->\n <button\n *ngIf=\"isDelete\"\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-trash\"\n (click)=\"Delete(data.id)\"\n class=\"p-button-rounded p-button-text\"\n ></button>\n\n <!-- built-in inline edit -->\n <div *ngIf=\"isEdit\">\n <button\n pInitEditableRow\n *ngIf=\"!editing\"\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-pencil\"\n (click)=\"initEditableRow(data)\"\n class=\"p-button-rounded p-button-text\"\n ></button>\n <button\n *ngIf=\"editing\"\n pSaveEditableRow\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-check\"\n (click)=\"saveEditableRow(data)\"\n class=\"p-button-rounded p-button-text\"\n ></button>\n <button\n *ngIf=\"editing\"\n pCancelEditableRow\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-times\"\n (click)=\"cancelEditableRow(data)\"\n class=\"p-button-rounded p-button-text\"\n ></button>\n </div>\n\n <!-- custom actions -->\n <button\n *ngFor=\"let act of customActions\"\n pButton\n pRipple\n type=\"button\"\n class=\"p-button-rounded p-button-text\"\n [icon]=\"act.icon || 'pi pi-ellipsis-h'\"\n [ngClass]=\"act.styleClass\"\n (click)=\"onCustomActionClick(act, data)\"\n ></button>\n </div>\n </ng-container>\n\n <!-- NON-ACTION cells -->\n <ng-template #nonActionCell>\n <!-- COMPOSED -->\n <ng-container\n *ngIf=\"\n col.type === TableTypeEnum.COMPOSED;\n else nonComposed\n \"\n >\n <div class=\"composed-cell\">\n <ng-container\n *ngFor=\"\n let composedName of col.composedNames;\n let i = index\n \"\n >\n <!-- IMAGE -->\n <ng-container\n *ngIf=\"\n col.composedTypes &&\n col.composedTypes[i] === TableTypeEnum.IMAGE\n \"\n >\n <img\n [src]=\"data[col.code!]?.[composedName]\"\n alt=\"composed-img\"\n class=\"composed-image\"\n [ngStyle]=\"\n getImageStyle(col.composedStyles?.[composedName])\n \"\n />\n </ng-container>\n\n <!-- STRING -->\n <ng-container\n *ngIf=\"\n col.composedTypes &&\n col.composedTypes[i] === TableTypeEnum.STRING\n \"\n >\n <span\n class=\"composed-text\"\n [ngStyle]=\"\n getTitleStyle(\n col.composedStyles?.[composedName]\n )\n \"\n >\n {{ data[col.code!]?.[composedName] }}\n </span>\n </ng-container>\n </ng-container>\n </div>\n </ng-container>\n\n <ng-template #nonComposed>\n <!-- AMOUNT-->\n <ng-container\n *ngIf=\"col.type === TableTypeEnum.AMOUNT; else nonAmount\"\n >\n {{\n data[col.code!]\n | customCurrency\n : getCurrencySymbol(col)\n : col.decimalPlaces\n : col.thousandSeparator\n : col.decimalSeparator\n }}\n </ng-container>\n\n <ng-template #nonAmount>\n <!-- NUMBER-->\n <ng-container\n *ngIf=\"\n col.type === TableTypeEnum.NUMBER;\n else nonNumber\n \"\n >\n {{\n formatNumber(\n data[col.code!],\n col.decimalPlaces,\n col.thousandSeparator,\n col.decimalSeparator\n )\n }}\n </ng-container>\n\n <ng-template #nonNumber>\n <!-- DATE -->\n <ng-container\n *ngIf=\"\n col.type === TableTypeEnum.DATE;\n else normalTypes\n \"\n >\n {{ formatDate(data[col.code!]) }}\n </ng-container>\n\n <ng-template #normalTypes>\n <!-- STRING, MULTISELECT-->\n <ng-container\n *ngIf=\"\n [\n TableTypeEnum.STRING,\n TableTypeEnum.MULTISELECT\n ].includes(col.type!)\n \"\n >\n {{ data[col.code!] }}\n </ng-container>\n </ng-template>\n </ng-template>\n </ng-template>\n </ng-template>\n </ng-template>\n </td>\n </ng-template>\n </ng-container>\n\n <!-- CHILD COLUMNS -->\n <ng-template #childColumns>\n <ng-container *ngFor=\"let child of col.children\">\n <td\n [style.width]=\"child.width || getHeaderWidth(child)\"\n [ngClass]=\"getDataAlignClass(child)\"\n >\n <ng-container\n *ngIf=\"isEditable(child.code); else childNormalTD\"\n >\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <input\n pInputText\n type=\"text\"\n [ngModel]=\"child.code ? data[child.code] : null\"\n (change)=\"onChange($event, data.id, child.code)\"\n />\n </ng-template>\n <ng-template pTemplate=\"output\">\n {{ child.code ? data[child.code] : \"\" }}\n </ng-template>\n </p-cellEditor>\n </ng-container>\n\n <ng-template #childNormalTD>\n {{ child.code ? data[child.code] : \"\" }}\n </ng-template>\n </td>\n </ng-container>\n </ng-template>\n </ng-container>\n </tr>\n </ng-template>\n </p-table>\n</div>\n", styles: [".pt-advanced-prime-table .bread-crumb{margin-bottom:15px}.pt-advanced-prime-table .date{width:100%;height:5rem;display:grid;justify-items:start;align-items:center}.pt-advanced-prime-table .filter-container{width:100%;display:flex;justify-content:space-between;align-items:center}.pt-advanced-prime-table .settings{display:flex;gap:1rem}.pt-advanced-prime-table .multi-select-container{display:flex;justify-content:center;align-items:center;gap:.3rem}.pt-advanced-prime-table ::ng-deep p-table{min-width:50rem}.pt-advanced-prime-table ::ng-deep .custom-multiselect .p-hidden-accessible input{display:none}.pt-advanced-prime-table ::ng-deep .p-datatable .p-sortable-column.p-highlight:hover{background:none}.pt-advanced-prime-table ::ng-deep .p-datatable .p-sortable-column:focus{box-shadow:none;outline:0 none}.pt-advanced-prime-table ::ng-deep .header-container{display:flex;justify-content:space-between;align-items:center;width:100%}.pt-advanced-prime-table ::ng-deep .header-title-left,.pt-advanced-prime-table ::ng-deep .header-title-center,.pt-advanced-prime-table ::ng-deep .header-title-right{flex:1}.pt-advanced-prime-table ::ng-deep .header-title-left{text-align:left}.pt-advanced-prime-table ::ng-deep .header-title-center{text-align:center}.pt-advanced-prime-table ::ng-deep .header-title-right{text-align:right}.pt-advanced-prime-table ::ng-deep .header-align-left{text-align:left}.pt-advanced-prime-table ::ng-deep .header-align-center{text-align:center}.pt-advanced-prime-table ::ng-deep .header-align-right{text-align:right}.pt-advanced-prime-table ::ng-deep p-columnfilter.p-element.ng-star-inserted{margin-top:4px}.pt-advanced-prime-table .flex{display:flex;justify-content:space-between;align-items:center}.pt-advanced-prime-table .ml-auto{margin-left:auto}.pt-advanced-prime-table ::ng-deep p-inputicon{margin-right:-1.5rem;z-index:2;position:relative}.pt-advanced-prime-table ::ng-deep .p-inputtext{padding-left:1.7rem}.pt-advanced-prime-table ::ng-deep .bt-filter-btn button{cursor:pointer;margin-left:1rem}.pt-advanced-prime-table ::ng-deep .p-icon-field-left .p-input-icon:first-of-type{left:-1rem}.pt-advanced-prime-table .table-row{text-align:center;display:flex;gap:1rem;justify-content:center}.pt-advanced-prime-table ::ng-deep span.p-button-icon.pi.pi-file-excel{font-size:1.25em;color:green}.pt-advanced-prime-table ::ng-deep span.p-button-icon.pi.pi-file-pdf{font-size:1.25em;color:red}.pt-advanced-prime-table .table-container{display:block;width:100%}.pt-advanced-prime-table ::ng-deep .p-datatable-emptymessage>td.empty-message-cell{padding:0!important}.pt-advanced-prime-table .empty-message-wrapper{width:100%;height:100%;min-height:180px;display:flex;align-items:center;justify-content:center}.pt-advanced-prime-table .empty-message{text-align:center;color:#888;font-size:1.2rem}.pt-advanced-prime-table .empty-message i{display:block;font-size:2rem;margin-bottom:.5rem}.pt-advanced-prime-table th{white-space:normal;word-wrap:break-word}.filter-image{width:22px;height:14px;margin-right:5px}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr>td.cell-align-left{text-align:left!important}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr>td.cell-align-center{text-align:center!important}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr>td.cell-align-right{text-align:right!important}.pt-advanced-prime-table ::ng-deep th.action-column,.pt-advanced-prime-table ::ng-deep td.action-column{text-align:center!important;justify-content:center;align-items:center;overflow:hidden;white-space:nowrap;padding:0}.pt-advanced-prime-table ::ng-deep .action-buttons-container{width:100%;display:flex;justify-content:center!important;align-items:center!important;gap:.35rem}.pt-advanced-prime-table ::ng-deep .action-buttons-container .p-button.p-button-rounded.p-button-text{padding:.25rem!important;min-width:22px!important;height:22px!important}\n"] }]
|
|
870
|
+
args: [{ selector: 'pt-advanced-prime-table', template: "<div class=\"pt-advanced-prime-table table-container\">\n <p-table\n #dt\n [value]=\"data\"\n [loading]=\"loading\"\n [rows]=\"rows\"\n [paginator]=\"isPaginated\"\n [globalFilterFields]=\"globalFilterFields\"\n [rowsPerPageOptions]=\"rowsPerPage\"\n [totalRecords]=\"totalRecords\"\n [lazy]=\"isPaginated\"\n dataKey=\"id\"\n styleClass=\"p-datatable-gridlines p-datatable-striped\"\n [scrollable]=\"true\"\n [scrollHeight]=\"maxHeight !== null ? maxHeight : undefined\"\n (onFilter)=\"filterColumn($event)\"\n (onPage)=\"changePage($event)\"\n (onSort)=\"sortColumn($event)\"\n >\n <!-- COLGROUP: sync header/body widths -->\n <ng-template pTemplate=\"colgroup\" let-columns>\n <colgroup>\n <col\n *ngFor=\"let col of columns\"\n [style.width]=\"col.width || getHeaderWidth(col)\"\n />\n </colgroup>\n </ng-template>\n\n <!-- CAPTION -->\n <ng-template pTemplate=\"caption\">\n <div class=\"flex\">\n <div>\n <h3>Total: {{ totalRecords }}</h3>\n </div>\n\n <div>\n <!-- Clear filters -->\n <button\n *ngIf=\"hasSearchFilter\"\n pButton\n icon=\"pi pi-filter-slash\"\n class=\"p-button-rounded p-button-text\"\n (click)=\"clear(dt)\"\n title=\"Clear filters\"\n ></button>\n\n <!-- Export to Excel Button -->\n <button\n *ngIf=\"hasExportExcel\"\n pButton\n icon=\"pi pi-file-excel\"\n class=\"p-button-rounded p-button-text\"\n (click)=\"exportExcel()\"\n title=\"Export to Excel\"\n ></button>\n\n <!-- Export to PDF Button -->\n <button\n *ngIf=\"hasExportPDF\"\n pButton\n icon=\"pi pi-file-pdf\"\n class=\"p-button-rounded p-button-text\"\n (click)=\"exportPdf()\"\n title=\"Export to PDF\"\n ></button>\n </div>\n\n <div class=\"ml-auto\" *ngIf=\"hasSearchFilter\">\n <p-iconField iconPosition=\"left\" class=\"ml-auto\">\n <p-inputIcon>\n <i class=\"pi pi-search\"></i>\n </p-inputIcon>\n <input\n pInputText\n type=\"text\"\n [(ngModel)]=\"searchValue\"\n (input)=\"filterGlobal($event)\"\n placeholder=\"Search keyword\"\n />\n </p-iconField>\n </div>\n </div>\n </ng-template>\n\n <!-- HEADER -->\n <ng-template pTemplate=\"header\">\n <tr class=\"sticky-header\">\n <ng-container *ngFor=\"let col of columns\">\n <th\n *ngIf=\"!col.children; else groupHeader\"\n pSortableColumn=\"{{ col.code }}\"\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [style.padding]=\"'0px'\"\n [ngClass]=\"[\n getHeaderAlignClass(col),\n col.type === TableTypeEnum.ACTION ? 'action-column' : ''\n ]\"\n colspan=\"1\"\n >\n <!-- SORTABLE HEADER -->\n <ng-container\n *ngIf=\"isSortable && col.isSortable !== false; else noSortHeader\"\n >\n <div\n class=\"header-container d-flex align-items-center justify-content-between\"\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [style.padding]=\"'0px'\"\n [style.margin]=\"'10px'\"\n >\n <span [ngClass]=\"getHeaderTitleClass(col)\">\n {{ col.title }}\n </span>\n <div\n class=\"icons d-flex align-items-center\"\n [style.width]=\"'77px'\"\n >\n <p-sortIcon field=\"{{ col.code }}\" />\n\n <!-- COLUMN FILTERS -->\n <ng-container\n *ngIf=\"hasColumnFilter && col.isFilter !== false\"\n >\n <!-- COMPOSED FILTER (uses built-in Apply/Clear) -->\n <p-columnFilter\n *ngIf=\"col.type === TableTypeEnum.COMPOSED\"\n display=\"menu\"\n [field]=\"col.code\"\n type=\"text\"\n [showApplyButton]=\"true\"\n [showClearButton]=\"true\"\n (onClear)=\"onComposedColumnClear(col)\"\n >\n <ng-template\n pTemplate=\"filter\"\n let-filter=\"filterCallback\"\n let-filterModel=\"filterModel\"\n >\n <div *ngFor=\"let composedName of col.composedNames\">\n <ng-container\n *ngIf=\"\n getComposedFieldType(col, composedName) ===\n TableTypeEnum.STRING\n \"\n >\n <p-multiSelect\n [options]=\"filters[composedName]?.options\"\n [ngModel]=\"filters[composedName]?.value\"\n (ngModelChange)=\"\n onComposedFilterValueChange(\n col,\n composedName,\n $event,\n filterModel\n )\n \"\n [placeholder]=\"filters[composedName]?.placeholder\"\n display=\"chip\"\n >\n <ng-template let-item pTemplate=\"item\">\n <div class=\"custom-multiselect-item\">\n <img\n *ngIf=\"item.image\"\n [src]=\"item.image\"\n alt=\"icon\"\n class=\"filter-image\"\n />\n <span>{{ item.label }}</span>\n </div>\n </ng-template>\n </p-multiSelect>\n </ng-container>\n </div>\n </ng-template>\n </p-columnFilter>\n\n <!-- OTHER TYPES -->\n <p-columnFilter\n *ngIf=\"col.type !== TableTypeEnum.COMPOSED\"\n display=\"menu\"\n [field]=\"col.code\"\n [type]=\"getColumnFilterType(col)\"\n [showApplyButton]=\"true\"\n [showClearButton]=\"true\"\n (onClear)=\"onFilterClear(col.code!)\"\n >\n <!-- NUMBER / AMOUNT: use text input so '.' works -->\n <ng-template\n pTemplate=\"filter\"\n *ngIf=\"\n col.type === TableTypeEnum.NUMBER ||\n col.type === TableTypeEnum.AMOUNT\n \"\n let-value\n >\n <input\n pInputText\n type=\"text\"\n inputmode=\"decimal\"\n [ngModel]=\"latestFilterValues[col.code!] ?? value\"\n (ngModelChange)=\"\n onNumberFilterChange(col.code!, $event)\n \"\n placeholder=\"Enter a number\"\n />\n </ng-template>\n\n <!-- DATE -->\n <ng-template\n pTemplate=\"filter\"\n *ngIf=\"col.type === TableTypeEnum.DATE\"\n let-filterModel=\"filterModel\"\n >\n <p-calendar\n [ngModel]=\"\n latestFilterValues[col.code!] ?? filterModel?.value\n \"\n (ngModelChange)=\"\n onFilterValueChange(col.code!, filterModel, $event)\n \"\n dateFormat=\"dd/mm/yy\"\n placeholder=\"Choose a date\"\n ></p-calendar>\n </ng-template>\n\n <!-- MULTISELECT -->\n <ng-template\n pTemplate=\"filter\"\n *ngIf=\"\n col.type === TableTypeEnum.MULTISELECT &&\n col.filterOptions &&\n col.filterOptions.length > 0\n \"\n let-filterModel=\"filterModel\"\n >\n <p-multiSelect\n [options]=\"col.filterOptions\"\n [ngModel]=\"\n latestFilterValues[col.code!] ?? filterModel?.value\n \"\n (ngModelChange)=\"\n onFilterValueChange(col.code!, filterModel, $event)\n \"\n display=\"chip\"\n placeholder=\"Choose option\"\n class=\"custom-multiselect\"\n ></p-multiSelect>\n </ng-template>\n </p-columnFilter>\n </ng-container>\n </div>\n </div>\n </ng-container>\n\n <!-- NON-SORTABLE HEADER -->\n <ng-template #noSortHeader>\n <div\n class=\"header-container d-flex align-items-center justify-content-between\"\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [style.padding]=\"'0px'\"\n [style.margin]=\"'10px'\"\n >\n <span [ngClass]=\"getHeaderTitleClass(col)\">\n {{ col.title }}\n </span>\n\n <ng-container *ngIf=\"hasColumnFilter && col.isFilter !== false\">\n <!-- AMOUNT behaves like NUMBER -->\n <p-columnFilter\n *ngIf=\"col.type === 'AMOUNT'\"\n display=\"menu\"\n [field]=\"col.code\"\n [type]=\"getColumnFilterType(col)\"\n [currency]=\"getCurrencySymbol(col)\"\n [showApplyButton]=\"true\"\n [showClearButton]=\"true\"\n >\n <ng-template\n pTemplate=\"filter\"\n let-filterModel=\"filterModel\"\n >\n <input\n pInputText\n type=\"text\"\n inputmode=\"decimal\"\n [ngModel]=\"\n latestFilterValues[col.code!] ?? filterModel?.value\n \"\n (ngModelChange)=\"\n onFilterValueChange(col.code!, filterModel, $event)\n \"\n placeholder=\"Enter an amount\"\n />\n </ng-template>\n </p-columnFilter>\n\n <p-columnFilter\n *ngIf=\"col.type !== 'AMOUNT'\"\n display=\"menu\"\n [field]=\"col.code\"\n [type]=\"getColumnFilterType(col)\"\n [showApplyButton]=\"true\"\n [showClearButton]=\"true\"\n >\n <!-- DATE -->\n <ng-template\n pTemplate=\"filter\"\n let-filterModel=\"filterModel\"\n *ngIf=\"getColumnFilterType(col) === 'date'\"\n >\n <p-calendar\n [ngModel]=\"\n latestFilterValues[col.code!] ?? filterModel?.value\n \"\n (ngModelChange)=\"\n onFilterValueChange(col.code!, filterModel, $event)\n \"\n dateFormat=\"dd/mm/yy\"\n ></p-calendar>\n </ng-template>\n\n <!-- MULTISELECT -->\n <ng-template\n pTemplate=\"filter\"\n let-filterModel=\"filterModel\"\n *ngIf=\"getColumnFilterType(col) === 'multiSelect'\"\n >\n <p-multiSelect\n [options]=\"col.filterOptions\"\n [ngModel]=\"\n latestFilterValues[col.code!] ?? filterModel?.value\n \"\n (ngModelChange)=\"\n onFilterValueChange(col.code!, filterModel, $event)\n \"\n display=\"chip\"\n placeholder=\"Select\"\n class=\"custom-multiselect\"\n ></p-multiSelect>\n </ng-template>\n </p-columnFilter>\n </ng-container>\n </div>\n </ng-template>\n </th>\n\n <!-- GROUPED HEADER -->\n <ng-template #groupHeader>\n <th\n [attr.colspan]=\"col.children?.length\"\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [ngClass]=\"getHeaderAlignClass(col)\"\n >\n <span>{{ col.title }}</span>\n </th>\n </ng-template>\n </ng-container>\n </tr>\n\n <!-- CHILD HEADERS -->\n <tr *ngIf=\"hasGroupedColumns\">\n <ng-container *ngFor=\"let col of columns\">\n <ng-container *ngIf=\"col.children\">\n <th\n *ngFor=\"let child of col.children\"\n [style.width]=\"child.width || getHeaderWidth(child)\"\n [style.padding]=\"'0px'\"\n ></th>\n </ng-container>\n </ng-container>\n </tr>\n </ng-template>\n\n <!-- EMPTY MESSAGE -->\n <ng-template pTemplate=\"emptymessage\">\n <tr class=\"p-datatable-emptymessage\">\n <!-- span all columns -->\n <td class=\"empty-message-cell\" [attr.colspan]=\"columns.length || 1\">\n <div class=\"empty-message-wrapper\">\n <div class=\"empty-message\">\n <i class=\"pi pi-info-circle\"></i>\n <p>No records available to display.</p>\n </div>\n </div>\n </td>\n </tr>\n </ng-template>\n\n <!-- BODY -->\n <ng-template\n pTemplate=\"body\"\n let-data\n let-editing=\"editing\"\n let-ri=\"rowIndex\"\n >\n <tr *ngIf=\"!loading\" [pEditableRow]=\"isEdit ? data : null\">\n <ng-container *ngFor=\"let col of columns\">\n <!-- SIMPLE COLUMNS (no children) -->\n <ng-container *ngIf=\"!col.children; else childColumns\">\n <!-- EDITABLE CELL -->\n <td\n *ngIf=\"\n isEditable(col.code!) && col.type !== TableTypeEnum.ACTION;\n else normalTD\n \"\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [ngClass]=\"getDataAlignClass(col)\"\n >\n <!-- Editable input for NUMBER/DATE/STRING/MULTISELECT -->\n <ng-container *ngIf=\"isMultiSelect(col.code); else datePicker\">\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <p-multiSelect\n appendTo=\"body\"\n [ngModel]=\"data[col.code!]\"\n [style]=\"{ width: '100%' }\"\n (ngModelChange)=\"changeHandler(data.id, col.code, $event)\"\n [options]=\"optionValues\"\n ></p-multiSelect>\n </ng-template>\n <ng-template pTemplate=\"output\">\n <div class=\"multi-select-container\">\n <ng-container *ngFor=\"let rec of data[col.code!]\">\n <p-tag [value]=\"rec\"></p-tag>\n </ng-container>\n </div>\n </ng-template>\n </p-cellEditor>\n </ng-container>\n\n <ng-template #datePicker>\n <ng-container *ngIf=\"isDatePicker(col.code); else normalInput\">\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <p-calendar\n [inputId]=\"data[col.code!]\"\n [ngModel]=\"data[col.code!]\"\n (ngModelChange)=\"\n changeHandler(data.id, col.code, $event)\n \"\n [dateFormat]=\"'dd/mm/yy'\"\n ></p-calendar>\n </ng-template>\n <ng-template pTemplate=\"output\">\n {{ data[col.code!] | customDate }}\n </ng-template>\n </p-cellEditor>\n </ng-container>\n </ng-template>\n\n <ng-template #normalInput>\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <input\n pInputText\n type=\"text\"\n [ngModel]=\"data[col.code!]\"\n (change)=\"onChange($event, data.id, col.code)\"\n />\n </ng-template>\n <ng-template pTemplate=\"output\">\n <ng-container\n *ngIf=\"\n col.type === TableTypeEnum.AMOUNT;\n else normalOutput\n \"\n >\n {{\n data[col.code!]\n | customCurrency\n : getCurrencySymbol(col)\n : col.decimalPlaces\n : col.thousandSeparator\n : col.decimalSeparator\n }}\n </ng-container>\n <ng-template #normalOutput>\n {{ data[col.code!] }}\n </ng-template>\n </ng-template>\n </p-cellEditor>\n </ng-template>\n </td>\n\n <!-- NON-EDITABLE CELL (ALWAYS RENDERED) -->\n <ng-template #normalTD>\n <td\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [ngClass]=\"[\n getDataAlignClass(col),\n col.type === TableTypeEnum.ACTION ? 'action-column' : ''\n ]\"\n >\n <!-- ACTION column: built-in edit/delete + custom actions -->\n <ng-container\n *ngIf=\"col.type === TableTypeEnum.ACTION; else nonActionCell\"\n >\n <div class=\"action-buttons-container\">\n <!-- built-in delete -->\n <button\n *ngIf=\"isDelete\"\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-trash\"\n (click)=\"Delete(data.id)\"\n class=\"p-button-rounded p-button-text\"\n ></button>\n\n <!-- built-in inline edit -->\n <div *ngIf=\"isEdit\">\n <button\n pInitEditableRow\n *ngIf=\"!editing\"\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-pencil\"\n (click)=\"initEditableRow(data)\"\n class=\"p-button-rounded p-button-text\"\n ></button>\n <button\n *ngIf=\"editing\"\n pSaveEditableRow\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-check\"\n (click)=\"saveEditableRow(data)\"\n class=\"p-button-rounded p-button-text\"\n ></button>\n <button\n *ngIf=\"editing\"\n pCancelEditableRow\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-times\"\n (click)=\"cancelEditableRow(data)\"\n class=\"p-button-rounded p-button-text\"\n ></button>\n </div>\n\n <!-- custom actions -->\n <button\n *ngFor=\"let act of customActions\"\n pButton\n pRipple\n type=\"button\"\n class=\"p-button-rounded p-button-text\"\n [icon]=\"act.icon || 'pi pi-ellipsis-h'\"\n [ngClass]=\"act.styleClass\"\n (click)=\"onCustomActionClick(act, data)\"\n ></button>\n </div>\n </ng-container>\n\n <!-- NON-ACTION cells -->\n <ng-template #nonActionCell>\n <!-- COMPOSED -->\n <ng-container\n *ngIf=\"\n col.type === TableTypeEnum.COMPOSED;\n else nonComposed\n \"\n >\n <div class=\"composed-cell\">\n <ng-container\n *ngFor=\"\n let composedName of col.composedNames;\n let i = index\n \"\n >\n <!-- IMAGE -->\n <ng-container\n *ngIf=\"\n col.composedTypes &&\n col.composedTypes[i] === TableTypeEnum.IMAGE\n \"\n >\n <img\n [src]=\"data[col.code!]?.[composedName]\"\n alt=\"composed-img\"\n class=\"composed-image\"\n [ngStyle]=\"\n getImageStyle(col.composedStyles?.[composedName])\n \"\n />\n </ng-container>\n\n <!-- STRING -->\n <ng-container\n *ngIf=\"\n col.composedTypes &&\n col.composedTypes[i] === TableTypeEnum.STRING\n \"\n >\n <span\n class=\"composed-text\"\n [ngStyle]=\"\n getTitleStyle(\n col.composedStyles?.[composedName]\n )\n \"\n >\n {{ data[col.code!]?.[composedName] }}\n </span>\n </ng-container>\n </ng-container>\n </div>\n </ng-container>\n\n <ng-template #nonComposed>\n <!-- AMOUNT-->\n <ng-container\n *ngIf=\"col.type === TableTypeEnum.AMOUNT; else nonAmount\"\n >\n {{\n data[col.code!]\n | customCurrency\n : getCurrencySymbol(col)\n : col.decimalPlaces\n : col.thousandSeparator\n : col.decimalSeparator\n }}\n </ng-container>\n\n <ng-template #nonAmount>\n <!-- NUMBER-->\n <ng-container\n *ngIf=\"\n col.type === TableTypeEnum.NUMBER;\n else nonNumber\n \"\n >\n {{\n formatNumber(\n data[col.code!],\n col.decimalPlaces,\n col.thousandSeparator,\n col.decimalSeparator\n )\n }}\n </ng-container>\n\n <ng-template #nonNumber>\n <!-- DATE -->\n <ng-container\n *ngIf=\"\n col.type === TableTypeEnum.DATE;\n else normalTypes\n \"\n >\n {{ formatDate(data[col.code!]) }}\n </ng-container>\n\n <ng-template #normalTypes>\n <!-- STRING, MULTISELECT-->\n <ng-container\n *ngIf=\"\n [\n TableTypeEnum.STRING,\n TableTypeEnum.MULTISELECT\n ].includes(col.type!)\n \"\n >\n {{ data[col.code!] }}\n </ng-container>\n </ng-template>\n </ng-template>\n </ng-template>\n </ng-template>\n </ng-template>\n </td>\n </ng-template>\n </ng-container>\n\n <!-- CHILD COLUMNS -->\n <ng-template #childColumns>\n <ng-container *ngFor=\"let child of col.children\">\n <td\n [style.width]=\"child.width || getHeaderWidth(child)\"\n [ngClass]=\"getDataAlignClass(child)\"\n >\n <ng-container\n *ngIf=\"isEditable(child.code); else childNormalTD\"\n >\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <input\n pInputText\n type=\"text\"\n [ngModel]=\"child.code ? data[child.code] : null\"\n (change)=\"onChange($event, data.id, child.code)\"\n />\n </ng-template>\n <ng-template pTemplate=\"output\">\n {{ child.code ? data[child.code] : \"\" }}\n </ng-template>\n </p-cellEditor>\n </ng-container>\n\n <ng-template #childNormalTD>\n {{ child.code ? data[child.code] : \"\" }}\n </ng-template>\n </td>\n </ng-container>\n </ng-template>\n </ng-container>\n </tr>\n </ng-template>\n </p-table>\n</div>\n", styles: [".pt-advanced-prime-table .bread-crumb{margin-bottom:15px}.pt-advanced-prime-table .date{width:100%;height:5rem;display:grid;justify-items:start;align-items:center}.pt-advanced-prime-table .filter-container{width:100%;display:flex;justify-content:space-between;align-items:center}.pt-advanced-prime-table .settings{display:flex;gap:1rem}.pt-advanced-prime-table .multi-select-container{display:flex;justify-content:center;align-items:center;gap:.3rem}.pt-advanced-prime-table ::ng-deep p-table{min-width:50rem}.pt-advanced-prime-table ::ng-deep .custom-multiselect .p-hidden-accessible input{display:none}.pt-advanced-prime-table ::ng-deep .p-datatable .p-sortable-column.p-highlight:hover{background:none}.pt-advanced-prime-table ::ng-deep .p-datatable .p-sortable-column:focus{box-shadow:none;outline:0 none}.pt-advanced-prime-table ::ng-deep .header-container{display:flex;justify-content:space-between;align-items:center;width:100%}.pt-advanced-prime-table ::ng-deep .header-title-left,.pt-advanced-prime-table ::ng-deep .header-title-center,.pt-advanced-prime-table ::ng-deep .header-title-right{flex:1}.pt-advanced-prime-table ::ng-deep .header-title-left{text-align:left}.pt-advanced-prime-table ::ng-deep .header-title-center{text-align:center}.pt-advanced-prime-table ::ng-deep .header-title-right{text-align:right}.pt-advanced-prime-table ::ng-deep .header-align-left{text-align:left}.pt-advanced-prime-table ::ng-deep .header-align-center{text-align:center}.pt-advanced-prime-table ::ng-deep .header-align-right{text-align:right}.pt-advanced-prime-table ::ng-deep p-columnfilter.p-element.ng-star-inserted{margin-top:4px}.pt-advanced-prime-table .flex{display:flex;justify-content:space-between;align-items:center}.pt-advanced-prime-table .ml-auto{margin-left:auto}.pt-advanced-prime-table ::ng-deep p-inputicon{margin-right:-1.5rem;z-index:2;position:relative}.pt-advanced-prime-table ::ng-deep .p-inputtext{padding-left:1.7rem}.pt-advanced-prime-table ::ng-deep .bt-filter-btn button{cursor:pointer;margin-left:1rem}.pt-advanced-prime-table ::ng-deep .p-icon-field-left .p-input-icon:first-of-type{left:-1rem}.pt-advanced-prime-table .table-row{text-align:center;display:flex;gap:1rem;justify-content:center}.pt-advanced-prime-table ::ng-deep span.p-button-icon.pi.pi-file-excel{font-size:1.25em;color:green}.pt-advanced-prime-table ::ng-deep span.p-button-icon.pi.pi-file-pdf{font-size:1.25em;color:red}.pt-advanced-prime-table .table-container{display:block;width:100%}.pt-advanced-prime-table ::ng-deep .p-datatable-emptymessage>td.empty-message-cell{padding:0!important}.pt-advanced-prime-table .empty-message-wrapper{width:100%;height:100%;min-height:180px;display:flex;align-items:center;justify-content:center}.pt-advanced-prime-table .empty-message{text-align:center;color:#888;font-size:1.2rem}.pt-advanced-prime-table .empty-message i{display:block;font-size:2rem;margin-bottom:.5rem}.pt-advanced-prime-table th{white-space:normal;word-wrap:break-word}.filter-image{width:22px;height:14px;margin-right:5px}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr>td.cell-align-left{text-align:left!important}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr>td.cell-align-center{text-align:center!important}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr>td.cell-align-right{text-align:right!important}.pt-advanced-prime-table ::ng-deep th.action-column,.pt-advanced-prime-table ::ng-deep td.action-column{text-align:center!important;justify-content:center;align-items:center;overflow:hidden;white-space:nowrap;padding:0}.pt-advanced-prime-table ::ng-deep .action-buttons-container{width:100%;display:flex;justify-content:center!important;align-items:center!important;gap:.35rem}.pt-advanced-prime-table ::ng-deep .action-buttons-container .p-button.p-button-rounded.p-button-text{padding:.25rem!important;min-width:22px!important;height:22px!important}\n"] }]
|
|
826
871
|
}], ctorParameters: () => [], propDecorators: { data: [{
|
|
827
872
|
type: Input
|
|
828
873
|
}], columns: [{
|