mat-table-ext 0.0.11 → 1.0.0
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/README.md +63 -57
- package/assets/_theming.scss +7 -7
- package/assets/pinLeft.svg +11 -11
- package/assets/pinNone.svg +5 -5
- package/assets/pinRight.svg +11 -11
- package/assets/pinned.svg +6 -2
- package/fesm2022/mat-table-ext.mjs +3040 -0
- package/fesm2022/mat-table-ext.mjs.map +1 -0
- package/index.d.ts +858 -5
- package/package.json +16 -22
- package/esm2020/lib/components/column-pinning/column-pinning.component.mjs +0 -58
- package/esm2020/lib/components/editing/editing.component.mjs +0 -122
- package/esm2020/lib/components/filter-columns-component/filter-columns-component.component.mjs +0 -68
- package/esm2020/lib/directives/resize-column.directive.mjs +0 -99
- package/esm2020/lib/mat-table-ext.component.mjs +0 -1020
- package/esm2020/lib/mat-table-ext.module.mjs +0 -237
- package/esm2020/lib/mat-table-ext.service.mjs +0 -20
- package/esm2020/lib/models/tableExtModels.mjs +0 -2
- package/esm2020/mat-table-ext.mjs +0 -5
- package/esm2020/public-api.mjs +0 -11
- package/fesm2015/mat-table-ext.mjs +0 -1584
- package/fesm2015/mat-table-ext.mjs.map +0 -1
- package/fesm2020/mat-table-ext.mjs +0 -1581
- package/fesm2020/mat-table-ext.mjs.map +0 -1
- package/lib/components/column-pinning/column-pinning.component.d.ts +0 -27
- package/lib/components/editing/editing.component.d.ts +0 -42
- package/lib/components/filter-columns-component/filter-columns-component.component.d.ts +0 -26
- package/lib/directives/resize-column.directive.d.ts +0 -27
- package/lib/mat-table-ext.component.d.ts +0 -348
- package/lib/mat-table-ext.module.d.ts +0 -58
- package/lib/mat-table-ext.service.d.ts +0 -11
- package/lib/models/tableExtModels.d.ts +0 -76
- package/public-api.d.ts +0 -7
|
@@ -0,0 +1,3040 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { Injectable, Inject, Component, EventEmitter, Output, Input, inject, Renderer2, ElementRef, Directive, ViewChild, ViewEncapsulation, NgModule } from '@angular/core';
|
|
3
|
+
import * as i7$1 from '@angular/material/table';
|
|
4
|
+
import { MatTableDataSource, MatTableModule } from '@angular/material/table';
|
|
5
|
+
import * as i3 from '@angular/forms';
|
|
6
|
+
import { FormsModule, FormControl, ReactiveFormsModule } from '@angular/forms';
|
|
7
|
+
import { MatNativeDateModule, MatRippleModule } from '@angular/material/core';
|
|
8
|
+
import * as i5 from '@angular/material/form-field';
|
|
9
|
+
import { MatFormFieldModule } from '@angular/material/form-field';
|
|
10
|
+
import { trigger, state, transition, style, animate } from '@angular/animations';
|
|
11
|
+
import { SelectionModel } from '@angular/cdk/collections';
|
|
12
|
+
import * as i20 from '@angular/cdk/drag-drop';
|
|
13
|
+
import { moveItemInArray, DragDropModule } from '@angular/cdk/drag-drop';
|
|
14
|
+
import * as i1$1 from '@angular/material/dialog';
|
|
15
|
+
import { MAT_DIALOG_DATA, MatDialogModule, MatDialogConfig } from '@angular/material/dialog';
|
|
16
|
+
import * as i14 from '@angular/material/menu';
|
|
17
|
+
import { MatMenuModule, MatMenuTrigger } from '@angular/material/menu';
|
|
18
|
+
import * as i12 from '@angular/material/paginator';
|
|
19
|
+
import { MatPaginatorModule, MatPaginator } from '@angular/material/paginator';
|
|
20
|
+
import * as i13 from '@angular/material/sort';
|
|
21
|
+
import { MatSortModule, MatSort } from '@angular/material/sort';
|
|
22
|
+
import * as i6 from '@angular/common';
|
|
23
|
+
import { CommonModule, TitleCasePipe } from '@angular/common';
|
|
24
|
+
import * as i6$1 from '@angular/material/input';
|
|
25
|
+
import { MatInputModule } from '@angular/material/input';
|
|
26
|
+
import * as i7 from '@angular/material/select';
|
|
27
|
+
import { MatSelectModule } from '@angular/material/select';
|
|
28
|
+
import * as i8 from '@angular/material/checkbox';
|
|
29
|
+
import { MatCheckboxModule } from '@angular/material/checkbox';
|
|
30
|
+
import * as i9 from '@angular/material/button';
|
|
31
|
+
import { MatButtonModule } from '@angular/material/button';
|
|
32
|
+
import * as i10 from '@angular/material/datepicker';
|
|
33
|
+
import { MatDatepickerModule } from '@angular/material/datepicker';
|
|
34
|
+
import * as i5$1 from '@angular/material/icon';
|
|
35
|
+
import { MatIconModule } from '@angular/material/icon';
|
|
36
|
+
import { BehaviorSubject } from 'rxjs';
|
|
37
|
+
import * as i1 from '@angular/common/http';
|
|
38
|
+
import * as XLSX from 'xlsx';
|
|
39
|
+
import * as i2 from '@angular/material/tooltip';
|
|
40
|
+
import { MatTooltipModule } from '@angular/material/tooltip';
|
|
41
|
+
import * as i17 from '@angular/material/toolbar';
|
|
42
|
+
import { MatToolbarModule } from '@angular/material/toolbar';
|
|
43
|
+
import * as i18 from '@angular/material/progress-bar';
|
|
44
|
+
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
|
45
|
+
import * as i4 from '@angular/platform-browser';
|
|
46
|
+
import * as i1$2 from '@ngx-translate/core';
|
|
47
|
+
import { TranslateModule } from '@ngx-translate/core';
|
|
48
|
+
import { A11yModule } from '@angular/cdk/a11y';
|
|
49
|
+
import { CdkAccordionModule } from '@angular/cdk/accordion';
|
|
50
|
+
import { ClipboardModule } from '@angular/cdk/clipboard';
|
|
51
|
+
import { PortalModule } from '@angular/cdk/portal';
|
|
52
|
+
import { ScrollingModule } from '@angular/cdk/scrolling';
|
|
53
|
+
import { CdkStepperModule } from '@angular/cdk/stepper';
|
|
54
|
+
import { CdkTableModule } from '@angular/cdk/table';
|
|
55
|
+
import { CdkTreeModule } from '@angular/cdk/tree';
|
|
56
|
+
import { MatAutocompleteModule } from '@angular/material/autocomplete';
|
|
57
|
+
import { MatBadgeModule } from '@angular/material/badge';
|
|
58
|
+
import { MatBottomSheetModule } from '@angular/material/bottom-sheet';
|
|
59
|
+
import { MatButtonToggleModule } from '@angular/material/button-toggle';
|
|
60
|
+
import { MatCardModule } from '@angular/material/card';
|
|
61
|
+
import { MatChipsModule } from '@angular/material/chips';
|
|
62
|
+
import { MatStepperModule } from '@angular/material/stepper';
|
|
63
|
+
import { MatDividerModule } from '@angular/material/divider';
|
|
64
|
+
import { MatExpansionModule } from '@angular/material/expansion';
|
|
65
|
+
import { MatGridListModule } from '@angular/material/grid-list';
|
|
66
|
+
import { MatListModule } from '@angular/material/list';
|
|
67
|
+
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
|
68
|
+
import { MatRadioModule } from '@angular/material/radio';
|
|
69
|
+
import { MatSidenavModule } from '@angular/material/sidenav';
|
|
70
|
+
import { MatSliderModule } from '@angular/material/slider';
|
|
71
|
+
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
|
|
72
|
+
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
|
73
|
+
import { MatTabsModule } from '@angular/material/tabs';
|
|
74
|
+
import { MatTreeModule } from '@angular/material/tree';
|
|
75
|
+
|
|
76
|
+
class MatTableExtService {
|
|
77
|
+
constructor(http) {
|
|
78
|
+
this.http = http;
|
|
79
|
+
this.selectedRow = new BehaviorSubject(null);
|
|
80
|
+
}
|
|
81
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.5", ngImport: i0, type: MatTableExtService, deps: [{ token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
82
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.5", ngImport: i0, type: MatTableExtService, providedIn: 'root' }); }
|
|
83
|
+
}
|
|
84
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.5", ngImport: i0, type: MatTableExtService, decorators: [{
|
|
85
|
+
type: Injectable,
|
|
86
|
+
args: [{
|
|
87
|
+
providedIn: 'root'
|
|
88
|
+
}]
|
|
89
|
+
}], ctorParameters: () => [{ type: i1.HttpClient }] });
|
|
90
|
+
|
|
91
|
+
class EditingComponent {
|
|
92
|
+
constructor(dialogRef, dialogData, service) {
|
|
93
|
+
this.dialogRef = dialogRef;
|
|
94
|
+
this.dialogData = dialogData;
|
|
95
|
+
this.service = service;
|
|
96
|
+
this.keys = [];
|
|
97
|
+
this.templateKeys = [];
|
|
98
|
+
this.types = {};
|
|
99
|
+
this.templateTypes = {};
|
|
100
|
+
this.columns = [];
|
|
101
|
+
this.templateRow = {};
|
|
102
|
+
this.isCellEdit = false;
|
|
103
|
+
this.cellField = '';
|
|
104
|
+
}
|
|
105
|
+
ngOnInit() {
|
|
106
|
+
// Check if this is cell-level editing
|
|
107
|
+
if (this.dialogData.isCellEdit) {
|
|
108
|
+
this.isCellEdit = true;
|
|
109
|
+
this.cellColumn = this.dialogData.column;
|
|
110
|
+
this.cellField = this.cellColumn.field;
|
|
111
|
+
this.cellValue = this.dialogData.row[this.cellField];
|
|
112
|
+
// Handle selection type
|
|
113
|
+
if (this.cellColumn.type === 'selection') {
|
|
114
|
+
this.types[this.cellField] = 'selection';
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
this.types[this.cellField] = this.cellColumn.type;
|
|
118
|
+
}
|
|
119
|
+
this.templateRef = this.dialogData.templateRef;
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
this.setData(this.dialogData);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* @description This method is used to set data for editing.
|
|
127
|
+
* @param value dialog Data
|
|
128
|
+
*/
|
|
129
|
+
setData(value) {
|
|
130
|
+
let row = value.row;
|
|
131
|
+
let types = {};
|
|
132
|
+
this.keys = [];
|
|
133
|
+
this.columns = value.columns;
|
|
134
|
+
this.columns.forEach((column) => {
|
|
135
|
+
this.keys.push(column.field);
|
|
136
|
+
if (column.type == 'selection') {
|
|
137
|
+
types[column.field] = column.type;
|
|
138
|
+
let temp = row[column.field];
|
|
139
|
+
row[column.field] = {
|
|
140
|
+
value: temp,
|
|
141
|
+
options: column.options,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
types[column.field] = column.type;
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
this.types = types;
|
|
149
|
+
this.setTemplateRef(value);
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* @description This method is used to set the data when data comes in from cus template.
|
|
153
|
+
* @param value template value
|
|
154
|
+
*/
|
|
155
|
+
setTemplateRef(value) {
|
|
156
|
+
if (value.templateRef !== undefined) {
|
|
157
|
+
this.templateRow = { ...value.row };
|
|
158
|
+
let types = {};
|
|
159
|
+
this.templateKeys = [];
|
|
160
|
+
this.columns.forEach((column) => {
|
|
161
|
+
this.templateKeys.push(column.field);
|
|
162
|
+
if (column.type == 'selection') {
|
|
163
|
+
types[column.field] = column.type;
|
|
164
|
+
let temp = this.templateRow[column.field];
|
|
165
|
+
this.templateRow[column.field] = {
|
|
166
|
+
value: temp,
|
|
167
|
+
options: column.options,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
types[column.field] = column.type;
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
this.templateTypes = types;
|
|
175
|
+
this.templateRef = value.templateRef;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* @description This method is triggered when dialog is closed and also emits the dialog closed event data.
|
|
180
|
+
*/
|
|
181
|
+
closeDialog() {
|
|
182
|
+
if (this.isCellEdit) {
|
|
183
|
+
// Return single cell data
|
|
184
|
+
this.dialogRef.close({
|
|
185
|
+
field: this.cellField,
|
|
186
|
+
value: this.cellValue
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
// Return full row data
|
|
191
|
+
let rowData = { ...this.dialogData.row };
|
|
192
|
+
this.keys.forEach((key) => {
|
|
193
|
+
if (this.types[key] === 'selection') {
|
|
194
|
+
let temp = rowData[key].value;
|
|
195
|
+
rowData[key] = temp;
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
this.dialogRef.close(rowData);
|
|
199
|
+
}
|
|
200
|
+
} /**
|
|
201
|
+
* @description This method is called when the dialog is closed custom template action.
|
|
202
|
+
* @param row row to be edited.
|
|
203
|
+
* @param keys keys of columns
|
|
204
|
+
* @param types column types
|
|
205
|
+
*/
|
|
206
|
+
closeTemplateDialog(row, keys, types) {
|
|
207
|
+
let rowData = { ...row };
|
|
208
|
+
keys.forEach((key) => {
|
|
209
|
+
if (types[key] === 'selection') {
|
|
210
|
+
let temp = rowData[key].value;
|
|
211
|
+
rowData[key] = temp;
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
this.dialogRef.close(rowData);
|
|
215
|
+
}
|
|
216
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.5", ngImport: i0, type: EditingComponent, deps: [{ token: i1$1.MatDialogRef }, { token: MAT_DIALOG_DATA }, { token: MatTableExtService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
217
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.5", type: EditingComponent, isStandalone: true, selector: "app-editing", ngImport: i0, template: "@if (!templateRef) {\n <div style=\"height: 100%;\" class=\"main-dialog-container\">\n <div mat-dialog-title class=\"dialog-title-container\">\n <h4 style=\"margin: 0;\">{{ isCellEdit ? 'Edit Cell' : 'Edit Row' }}</h4>\n <span class=\"example-spacer\"></span>\n <button style=\"margin-right: -10px;\" mat-icon-button aria-label=\"Example icon button with a vertical three dot icon\">\n <mat-icon mat-dialog-close style=\"cursor: pointer;\" fxFlex=\"5\">close</mat-icon>\n </button>\n </div>\n <mat-dialog-content style=\"margin-right: 20px;\">\n <!-- Cell-level editing -->\n @if (isCellEdit) {\n <div style=\"display: flex; flex-direction: column;\">\n <!-- Number Type -->\n @if (types[cellField] == 'number') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-label>{{cellColumn.header || cellField | titlecase}}</mat-label>\n <input matInput type=\"number\" [(ngModel)]=\"cellValue\" [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n \n <!-- String Type -->\n @if (types[cellField] == 'string') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-label>{{cellColumn.header || cellField | titlecase}}</mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"cellValue\" [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n \n <!-- Textarea Type -->\n @if (types[cellField] == 'textarea') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-label>{{cellColumn.header || cellField | titlecase}}</mat-label>\n <textarea matInput rows=\"6\" [(ngModel)]=\"cellValue\" [ngModelOptions]=\"{standalone: true}\"></textarea>\n </mat-form-field>\n }\n \n @if (types[cellField] == 'date') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-label>{{cellColumn.header || cellField | titlecase}}</mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"cellValue\" [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n \n <!-- Datepicker Type -->\n @if (types[cellField] == 'datepicker') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-label>{{cellColumn.header || cellField | titlecase}}</mat-label>\n <input matInput [matDatepicker]=\"cellPopupPicker\" [(ngModel)]=\"cellValue\" [ngModelOptions]=\"{standalone: true}\">\n <mat-datepicker-toggle matIconSuffix [for]=\"cellPopupPicker\"></mat-datepicker-toggle>\n <mat-datepicker #cellPopupPicker></mat-datepicker>\n </mat-form-field>\n }\n \n <!-- Selection Type -->\n @if (types[cellField] == 'selection') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-label>{{cellColumn.header || cellField | titlecase}}</mat-label>\n <mat-select [(ngModel)]=\"cellValue\">\n @for (option of cellColumn.options; track option) {\n <mat-option [value]=\"option\">{{option}}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n \n <!-- Boolean Type -->\n @if (types[cellField] == 'boolean') {\n <p>\n <mat-checkbox color=\"primary\" [(ngModel)]=\"cellValue\">\n <mat-label>{{cellColumn.header || cellField | titlecase}}</mat-label>\n </mat-checkbox>\n </p>\n }\n </div>\n }\n \n <!-- Row-level editing -->\n @if (!isCellEdit) {\n <div style=\"display: flex; flex-direction: column;\">\\n @for (key of keys; track key) {\n <!-- Number Type -->\n @if (types[key] == 'number') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-label>{{key | titlecase}}</mat-label>\n <input matInput type=\"number\" [(ngModel)]=\"dialogData['row'][key]\" [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n \n <!-- String Type -->\n @if (types[key] == 'string') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-label>{{key | titlecase}}</mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"dialogData['row'][key]\" [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n <!-- Textarea Type -->\n @if (types[key] == 'textarea') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-label>{{key | titlecase}}</mat-label>\n <textarea matInput rows=\"4\" [(ngModel)]=\"dialogData['row'][key]\" [ngModelOptions]=\"{standalone: true}\"></textarea>\n </mat-form-field>\n }\n @if (types[key] == 'date') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-label>{{key | titlecase}}</mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"dialogData['row'][key]\" [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n <!-- Datepicker Type -->\n @if (types[key] == 'datepicker') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-label>{{key | titlecase}}</mat-label>\n <input matInput [matDatepicker]=\"popupPicker\" [(ngModel)]=\"dialogData['row'][key]\" [ngModelOptions]=\"{standalone: true}\">\n <mat-datepicker-toggle matIconSuffix [for]=\"popupPicker\"></mat-datepicker-toggle>\n <mat-datepicker #popupPicker></mat-datepicker>\n </mat-form-field>\n }\n <!-- Selection Type -->\n @if (types[key] == 'selection') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-label>{{key | titlecase}}</mat-label>\n <mat-select [value]=\"dialogData['row'][key].value\" [(ngModel)]=\"dialogData['row'][key].value\">\n @for (option of dialogData['row'][key].options; track option) {\n <mat-option [value]=\"option\">{{option}}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n <!-- Boolean Type -->\n @if (types[key] == 'boolean') {\n <p>\n <mat-checkbox color=\"primary\" [(ngModel)]=\"dialogData['row'][key]\">\n <mat-label>{{key | titlecase}}</mat-label>\n </mat-checkbox>\n </p>\n }\n }\n </div>\n }\n </mat-dialog-content>\n <div class=\"spacer\"></div>\n <mat-dialog-actions style=\"margin-top: 20px;\" align=\"end\">\n <button mat-raised-button color=\"warn\" mat-dialog-close>\n Cancel\n </button>\n <button mat-raised-button color=\"primary\" (click)=\"closeDialog()\">Save</button>\n </mat-dialog-actions>\n </div>\n}\n@if (templateRef) {\n <ng-container [ngTemplateOutlet]=\"templateRef\" [ngTemplateOutletContext]=\"{data:{row:templateRow,columns:columns,columnKeys:templateKeys,columnTypes:templateTypes,closeDialog:closeTemplateDialog}}\"></ng-container>\n}", styles: [".main-dialog-container{display:flex;flex-direction:column}.main-dialog-container mat-dialog-content{overflow-y:auto;margin:0;padding:10px 10px 10px 20px}.dialog-title-container{display:flex;align-items:center}.spacer{flex-grow:1}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i6.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.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: i3.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i5.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i5.MatLabel, selector: "mat-label" }, { kind: "directive", type: i5.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i6$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i7.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i7.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i8.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i9.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i9.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1$1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1$1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1$1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1$1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i10.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i10.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i10.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "ngmodule", type: MatNativeDateModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "pipe", type: i6.TitleCasePipe, name: "titlecase" }] }); }
|
|
218
|
+
}
|
|
219
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.5", ngImport: i0, type: EditingComponent, decorators: [{
|
|
220
|
+
type: Component,
|
|
221
|
+
args: [{ selector: 'app-editing', standalone: true, imports: [
|
|
222
|
+
CommonModule,
|
|
223
|
+
FormsModule,
|
|
224
|
+
MatFormFieldModule,
|
|
225
|
+
MatInputModule,
|
|
226
|
+
MatSelectModule,
|
|
227
|
+
MatCheckboxModule,
|
|
228
|
+
MatButtonModule,
|
|
229
|
+
MatDialogModule,
|
|
230
|
+
MatDatepickerModule,
|
|
231
|
+
MatNativeDateModule,
|
|
232
|
+
MatIconModule,
|
|
233
|
+
TitleCasePipe
|
|
234
|
+
], template: "@if (!templateRef) {\n <div style=\"height: 100%;\" class=\"main-dialog-container\">\n <div mat-dialog-title class=\"dialog-title-container\">\n <h4 style=\"margin: 0;\">{{ isCellEdit ? 'Edit Cell' : 'Edit Row' }}</h4>\n <span class=\"example-spacer\"></span>\n <button style=\"margin-right: -10px;\" mat-icon-button aria-label=\"Example icon button with a vertical three dot icon\">\n <mat-icon mat-dialog-close style=\"cursor: pointer;\" fxFlex=\"5\">close</mat-icon>\n </button>\n </div>\n <mat-dialog-content style=\"margin-right: 20px;\">\n <!-- Cell-level editing -->\n @if (isCellEdit) {\n <div style=\"display: flex; flex-direction: column;\">\n <!-- Number Type -->\n @if (types[cellField] == 'number') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-label>{{cellColumn.header || cellField | titlecase}}</mat-label>\n <input matInput type=\"number\" [(ngModel)]=\"cellValue\" [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n \n <!-- String Type -->\n @if (types[cellField] == 'string') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-label>{{cellColumn.header || cellField | titlecase}}</mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"cellValue\" [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n \n <!-- Textarea Type -->\n @if (types[cellField] == 'textarea') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-label>{{cellColumn.header || cellField | titlecase}}</mat-label>\n <textarea matInput rows=\"6\" [(ngModel)]=\"cellValue\" [ngModelOptions]=\"{standalone: true}\"></textarea>\n </mat-form-field>\n }\n \n @if (types[cellField] == 'date') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-label>{{cellColumn.header || cellField | titlecase}}</mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"cellValue\" [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n \n <!-- Datepicker Type -->\n @if (types[cellField] == 'datepicker') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-label>{{cellColumn.header || cellField | titlecase}}</mat-label>\n <input matInput [matDatepicker]=\"cellPopupPicker\" [(ngModel)]=\"cellValue\" [ngModelOptions]=\"{standalone: true}\">\n <mat-datepicker-toggle matIconSuffix [for]=\"cellPopupPicker\"></mat-datepicker-toggle>\n <mat-datepicker #cellPopupPicker></mat-datepicker>\n </mat-form-field>\n }\n \n <!-- Selection Type -->\n @if (types[cellField] == 'selection') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-label>{{cellColumn.header || cellField | titlecase}}</mat-label>\n <mat-select [(ngModel)]=\"cellValue\">\n @for (option of cellColumn.options; track option) {\n <mat-option [value]=\"option\">{{option}}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n \n <!-- Boolean Type -->\n @if (types[cellField] == 'boolean') {\n <p>\n <mat-checkbox color=\"primary\" [(ngModel)]=\"cellValue\">\n <mat-label>{{cellColumn.header || cellField | titlecase}}</mat-label>\n </mat-checkbox>\n </p>\n }\n </div>\n }\n \n <!-- Row-level editing -->\n @if (!isCellEdit) {\n <div style=\"display: flex; flex-direction: column;\">\\n @for (key of keys; track key) {\n <!-- Number Type -->\n @if (types[key] == 'number') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-label>{{key | titlecase}}</mat-label>\n <input matInput type=\"number\" [(ngModel)]=\"dialogData['row'][key]\" [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n \n <!-- String Type -->\n @if (types[key] == 'string') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-label>{{key | titlecase}}</mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"dialogData['row'][key]\" [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n <!-- Textarea Type -->\n @if (types[key] == 'textarea') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-label>{{key | titlecase}}</mat-label>\n <textarea matInput rows=\"4\" [(ngModel)]=\"dialogData['row'][key]\" [ngModelOptions]=\"{standalone: true}\"></textarea>\n </mat-form-field>\n }\n @if (types[key] == 'date') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-label>{{key | titlecase}}</mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"dialogData['row'][key]\" [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n <!-- Datepicker Type -->\n @if (types[key] == 'datepicker') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-label>{{key | titlecase}}</mat-label>\n <input matInput [matDatepicker]=\"popupPicker\" [(ngModel)]=\"dialogData['row'][key]\" [ngModelOptions]=\"{standalone: true}\">\n <mat-datepicker-toggle matIconSuffix [for]=\"popupPicker\"></mat-datepicker-toggle>\n <mat-datepicker #popupPicker></mat-datepicker>\n </mat-form-field>\n }\n <!-- Selection Type -->\n @if (types[key] == 'selection') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-label>{{key | titlecase}}</mat-label>\n <mat-select [value]=\"dialogData['row'][key].value\" [(ngModel)]=\"dialogData['row'][key].value\">\n @for (option of dialogData['row'][key].options; track option) {\n <mat-option [value]=\"option\">{{option}}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n <!-- Boolean Type -->\n @if (types[key] == 'boolean') {\n <p>\n <mat-checkbox color=\"primary\" [(ngModel)]=\"dialogData['row'][key]\">\n <mat-label>{{key | titlecase}}</mat-label>\n </mat-checkbox>\n </p>\n }\n }\n </div>\n }\n </mat-dialog-content>\n <div class=\"spacer\"></div>\n <mat-dialog-actions style=\"margin-top: 20px;\" align=\"end\">\n <button mat-raised-button color=\"warn\" mat-dialog-close>\n Cancel\n </button>\n <button mat-raised-button color=\"primary\" (click)=\"closeDialog()\">Save</button>\n </mat-dialog-actions>\n </div>\n}\n@if (templateRef) {\n <ng-container [ngTemplateOutlet]=\"templateRef\" [ngTemplateOutletContext]=\"{data:{row:templateRow,columns:columns,columnKeys:templateKeys,columnTypes:templateTypes,closeDialog:closeTemplateDialog}}\"></ng-container>\n}", styles: [".main-dialog-container{display:flex;flex-direction:column}.main-dialog-container mat-dialog-content{overflow-y:auto;margin:0;padding:10px 10px 10px 20px}.dialog-title-container{display:flex;align-items:center}.spacer{flex-grow:1}\n"] }]
|
|
235
|
+
}], ctorParameters: () => [{ type: i1$1.MatDialogRef }, { type: undefined, decorators: [{
|
|
236
|
+
type: Inject,
|
|
237
|
+
args: [MAT_DIALOG_DATA]
|
|
238
|
+
}] }, { type: MatTableExtService }] });
|
|
239
|
+
|
|
240
|
+
class ColumnPinningComponent {
|
|
241
|
+
constructor() {
|
|
242
|
+
this.columnsChanged = new EventEmitter();
|
|
243
|
+
this.icons = {
|
|
244
|
+
left: 'pinLeft',
|
|
245
|
+
right: 'pinRight',
|
|
246
|
+
none: 'pinNone',
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
ngOnInit() { }
|
|
250
|
+
/**
|
|
251
|
+
* @description This method is called when pin value changes for a column.
|
|
252
|
+
* @param column column of which to set the pin value
|
|
253
|
+
*/
|
|
254
|
+
changeValue(column) {
|
|
255
|
+
if (column.pinned) {
|
|
256
|
+
if (column.pinned == 'left') {
|
|
257
|
+
this.setColumnPinValue(column, 'right');
|
|
258
|
+
}
|
|
259
|
+
else if (column.pinned == 'right') {
|
|
260
|
+
this.setColumnPinValue(column, null);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
this.setColumnPinValue(column, 'left');
|
|
265
|
+
}
|
|
266
|
+
// Create a new array reference to trigger change detection
|
|
267
|
+
this.columnsChanged.emit([...this.columns]);
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* @description This method is used to set the column pin value.
|
|
271
|
+
* @param column column of which to set the pin value
|
|
272
|
+
* @param value pin value to set
|
|
273
|
+
*/
|
|
274
|
+
setColumnPinValue(column, value) {
|
|
275
|
+
// Create a new array with updated column
|
|
276
|
+
this.columns = this.columns.map(col => {
|
|
277
|
+
if (column?.field == col.field) {
|
|
278
|
+
return { ...col, pinned: value === null ? undefined : value };
|
|
279
|
+
}
|
|
280
|
+
return col;
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.5", ngImport: i0, type: ColumnPinningComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
284
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.5", type: ColumnPinningComponent, isStandalone: true, selector: "app-column-pinning", inputs: { columns: "columns" }, outputs: { columnsChanged: "columnsChanged" }, ngImport: i0, template: "@for (column of columns; track column.field) {\n <div class=\"pinning-list-item\">\n <button mat-icon-button (click)=\"changeValue(column)\">\n <mat-icon matTooltip=\"{{column['pinned'] ? (column['pinned'] | titlecase) : 'None'}}\"\n svgIcon=\"{{column['pinned'] == 'left' || column['pinned'] == 'right' ? icons[column['pinned']] : 'pinNone'}}\"\n class=\"pinning-icon\"></mat-icon>\n </button>\n <span class=\"column-headers\">{{column.header}}</span>\n </div>\n}", styles: [".pinning-list-item{display:flex;justify-content:flex-start;align-items:center;gap:12px;height:3em}.column-headers{font-family:Roboto,Helvetica Neue,sans-serif;font-size:14px}button[mat-icon-button]{background:none;border:none;outline:none;padding:0;line-height:normal;display:flex;align-items:center;justify-content:center}button[mat-icon-button]:focus{outline:none}.pinning-icon{font-size:24px;line-height:1}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i2.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "pipe", type: i6.TitleCasePipe, name: "titlecase" }] }); }
|
|
285
|
+
}
|
|
286
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.5", ngImport: i0, type: ColumnPinningComponent, decorators: [{
|
|
287
|
+
type: Component,
|
|
288
|
+
args: [{ selector: 'app-column-pinning', standalone: true, imports: [
|
|
289
|
+
CommonModule,
|
|
290
|
+
MatIconModule,
|
|
291
|
+
MatTooltipModule,
|
|
292
|
+
TitleCasePipe
|
|
293
|
+
], template: "@for (column of columns; track column.field) {\n <div class=\"pinning-list-item\">\n <button mat-icon-button (click)=\"changeValue(column)\">\n <mat-icon matTooltip=\"{{column['pinned'] ? (column['pinned'] | titlecase) : 'None'}}\"\n svgIcon=\"{{column['pinned'] == 'left' || column['pinned'] == 'right' ? icons[column['pinned']] : 'pinNone'}}\"\n class=\"pinning-icon\"></mat-icon>\n </button>\n <span class=\"column-headers\">{{column.header}}</span>\n </div>\n}", styles: [".pinning-list-item{display:flex;justify-content:flex-start;align-items:center;gap:12px;height:3em}.column-headers{font-family:Roboto,Helvetica Neue,sans-serif;font-size:14px}button[mat-icon-button]{background:none;border:none;outline:none;padding:0;line-height:normal;display:flex;align-items:center;justify-content:center}button[mat-icon-button]:focus{outline:none}.pinning-icon{font-size:24px;line-height:1}\n"] }]
|
|
294
|
+
}], ctorParameters: () => [], propDecorators: { columns: [{
|
|
295
|
+
type: Input
|
|
296
|
+
}], columnsChanged: [{
|
|
297
|
+
type: Output
|
|
298
|
+
}] } });
|
|
299
|
+
|
|
300
|
+
class FilterColumnsComponentComponent {
|
|
301
|
+
constructor() {
|
|
302
|
+
this.filterOutput = new EventEmitter();
|
|
303
|
+
this.stringCtrl = new FormControl();
|
|
304
|
+
this.numberCtrl = new FormControl();
|
|
305
|
+
this.dateCtrl = new FormControl();
|
|
306
|
+
this.textareaCtrl = new FormControl();
|
|
307
|
+
this.booleanCtrl = new FormControl();
|
|
308
|
+
this.selectionCtrl = new FormControl();
|
|
309
|
+
}
|
|
310
|
+
ngOnInit() {
|
|
311
|
+
this.stringCtrl.valueChanges.subscribe((value) => {
|
|
312
|
+
this.checkValue(value);
|
|
313
|
+
});
|
|
314
|
+
this.dateCtrl.valueChanges.subscribe((value) => {
|
|
315
|
+
this.checkValue(value);
|
|
316
|
+
});
|
|
317
|
+
this.textareaCtrl.valueChanges.subscribe((value) => {
|
|
318
|
+
this.checkValue(value);
|
|
319
|
+
});
|
|
320
|
+
this.numberCtrl.valueChanges.subscribe((value) => {
|
|
321
|
+
this.checkValue(value);
|
|
322
|
+
});
|
|
323
|
+
this.booleanCtrl.valueChanges.subscribe((value) => {
|
|
324
|
+
this.checkValue(value);
|
|
325
|
+
});
|
|
326
|
+
this.selectionCtrl.valueChanges.subscribe((value) => {
|
|
327
|
+
this.checkValue(value);
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* @description This method is make value is valid and not null.
|
|
332
|
+
* @param value value to check its type.
|
|
333
|
+
*/
|
|
334
|
+
checkValue(value) {
|
|
335
|
+
if (value || value == '') {
|
|
336
|
+
this.emitOutput(value);
|
|
337
|
+
}
|
|
338
|
+
else if (value == null) {
|
|
339
|
+
this.emitOutput('');
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* @description This method will emit seach value to parent component.
|
|
344
|
+
* @param value value on which base table rows are filtered.
|
|
345
|
+
*/
|
|
346
|
+
emitOutput(value) {
|
|
347
|
+
let obj = { [this.obj.field]: value };
|
|
348
|
+
this.filterOutput.emit(obj);
|
|
349
|
+
}
|
|
350
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.5", ngImport: i0, type: FilterColumnsComponentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
351
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.5", type: FilterColumnsComponentComponent, isStandalone: true, selector: "app-filter-columns-component", inputs: { obj: "obj" }, outputs: { filterOutput: "filterOutput" }, ngImport: i0, template: "\n@if (obj) {\n <!-- Number Type -->\n @if (obj.type == 'number') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\" >\n <input matInput type=\"number\" [formControl]=\"numberCtrl\">\n </mat-form-field>\n }\n \n <!-- String Type -->\n @if (obj.type == 'string') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"text\" [formControl]=\"stringCtrl\">\n </mat-form-field>\n }\n @if (obj.type == 'textarea') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <textarea matInput rows=\"3\" [formControl]=\"textareaCtrl\"></textarea>\n </mat-form-field>\n }\n @if (obj.type == 'date') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"date\" [formControl]=\"dateCtrl\">\n </mat-form-field>\n }\n @if (obj.type == 'datepicker') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput [matDatepicker]=\"cellPicker\" [formControl]=\"dateCtrl\">\n <mat-datepicker-toggle matIconSuffix [for]=\"cellPicker\"></mat-datepicker-toggle>\n <mat-datepicker #cellPicker></mat-datepicker>\n </mat-form-field>\n }\n <!-- Selection Type -->\n @if (obj.type == 'selection') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-select [value]=\"\" [formControl]=\"selectionCtrl\">\n @for (option of obj.options; track option) {\n <mat-option [value]=\"option\">{{option}}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n <!-- Boolean Type -->\n @if (obj.type == 'boolean') {\n <mat-checkbox (click)=\"$event.stopPropagation()\" color=\"primary\" [formControl]=\"booleanCtrl\"></mat-checkbox>\n }\n}", styles: [".inline-editing-field{width:100%;min-width:none!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.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: i3.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i5.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i5.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i6$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i7.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i7.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i8.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i10.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i10.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i10.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }] }); }
|
|
352
|
+
}
|
|
353
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.5", ngImport: i0, type: FilterColumnsComponentComponent, decorators: [{
|
|
354
|
+
type: Component,
|
|
355
|
+
args: [{ selector: 'app-filter-columns-component', standalone: true, imports: [
|
|
356
|
+
CommonModule,
|
|
357
|
+
ReactiveFormsModule,
|
|
358
|
+
MatFormFieldModule,
|
|
359
|
+
MatInputModule,
|
|
360
|
+
MatSelectModule,
|
|
361
|
+
MatCheckboxModule,
|
|
362
|
+
MatDatepickerModule
|
|
363
|
+
], template: "\n@if (obj) {\n <!-- Number Type -->\n @if (obj.type == 'number') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\" >\n <input matInput type=\"number\" [formControl]=\"numberCtrl\">\n </mat-form-field>\n }\n \n <!-- String Type -->\n @if (obj.type == 'string') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"text\" [formControl]=\"stringCtrl\">\n </mat-form-field>\n }\n @if (obj.type == 'textarea') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <textarea matInput rows=\"3\" [formControl]=\"textareaCtrl\"></textarea>\n </mat-form-field>\n }\n @if (obj.type == 'date') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"date\" [formControl]=\"dateCtrl\">\n </mat-form-field>\n }\n @if (obj.type == 'datepicker') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput [matDatepicker]=\"cellPicker\" [formControl]=\"dateCtrl\">\n <mat-datepicker-toggle matIconSuffix [for]=\"cellPicker\"></mat-datepicker-toggle>\n <mat-datepicker #cellPicker></mat-datepicker>\n </mat-form-field>\n }\n <!-- Selection Type -->\n @if (obj.type == 'selection') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-select [value]=\"\" [formControl]=\"selectionCtrl\">\n @for (option of obj.options; track option) {\n <mat-option [value]=\"option\">{{option}}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n <!-- Boolean Type -->\n @if (obj.type == 'boolean') {\n <mat-checkbox (click)=\"$event.stopPropagation()\" color=\"primary\" [formControl]=\"booleanCtrl\"></mat-checkbox>\n }\n}", styles: [".inline-editing-field{width:100%;min-width:none!important}\n"] }]
|
|
364
|
+
}], ctorParameters: () => [], propDecorators: { obj: [{
|
|
365
|
+
type: Input
|
|
366
|
+
}], filterOutput: [{
|
|
367
|
+
type: Output
|
|
368
|
+
}] } });
|
|
369
|
+
|
|
370
|
+
class ResizeColumnDirective {
|
|
371
|
+
set columnsResizable(val) {
|
|
372
|
+
this.columnsResizable$ = val;
|
|
373
|
+
}
|
|
374
|
+
get columnsResizable() {
|
|
375
|
+
return this.columnsResizable$;
|
|
376
|
+
}
|
|
377
|
+
constructor() {
|
|
378
|
+
this.renderer = inject(Renderer2);
|
|
379
|
+
this.elementRef = inject((ElementRef));
|
|
380
|
+
this.columnsResizable$ = false;
|
|
381
|
+
this.startX = 0;
|
|
382
|
+
this.startWidth = 0;
|
|
383
|
+
this.table = null;
|
|
384
|
+
this.pressed = false;
|
|
385
|
+
this.resizerElement = null;
|
|
386
|
+
this.onMouseDown = (event) => {
|
|
387
|
+
this.pressed = true;
|
|
388
|
+
this.startX = event.pageX;
|
|
389
|
+
this.startWidth = this.column.offsetWidth;
|
|
390
|
+
};
|
|
391
|
+
this.onMouseMove = (event) => {
|
|
392
|
+
const offset = 5;
|
|
393
|
+
if (this.pressed && event.buttons && this.table) {
|
|
394
|
+
this.renderer.addClass(this.table, "resizing");
|
|
395
|
+
// Calculate width of column
|
|
396
|
+
const width = this.startWidth + (event.pageX - this.startX - offset);
|
|
397
|
+
// Get table cells for this column index
|
|
398
|
+
const tableRows = this.table.querySelectorAll(".mat-mdc-row");
|
|
399
|
+
const tableCells = Array.from(tableRows).map((row) => row.querySelectorAll(".mat-mdc-cell").item(this.index));
|
|
400
|
+
// Set table header width
|
|
401
|
+
this.renderer.setStyle(this.column, "width", `${width}px`);
|
|
402
|
+
// Set table cells width
|
|
403
|
+
tableCells.forEach((cell) => {
|
|
404
|
+
if (cell instanceof HTMLElement) {
|
|
405
|
+
this.renderer.setStyle(cell, "width", `${width}px`);
|
|
406
|
+
}
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
};
|
|
410
|
+
this.onMouseUp = (event) => {
|
|
411
|
+
if (this.pressed && this.table) {
|
|
412
|
+
this.pressed = false;
|
|
413
|
+
this.renderer.removeClass(this.table, "resizing");
|
|
414
|
+
}
|
|
415
|
+
};
|
|
416
|
+
this.column = this.elementRef.nativeElement;
|
|
417
|
+
}
|
|
418
|
+
ngOnInit() {
|
|
419
|
+
this.setupResizing();
|
|
420
|
+
}
|
|
421
|
+
ngOnChanges() {
|
|
422
|
+
this.setupResizing();
|
|
423
|
+
}
|
|
424
|
+
ngOnDestroy() {
|
|
425
|
+
this.cleanup();
|
|
426
|
+
}
|
|
427
|
+
setupResizing() {
|
|
428
|
+
if (this.columnsResizable$) {
|
|
429
|
+
this.initializeResizer();
|
|
430
|
+
}
|
|
431
|
+
else {
|
|
432
|
+
this.removeDragElementFromDom();
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
initializeResizer() {
|
|
436
|
+
const row = this.renderer.parentNode(this.column);
|
|
437
|
+
const thead = this.renderer.parentNode(row);
|
|
438
|
+
this.table = this.renderer.parentNode(thead);
|
|
439
|
+
this.resizerElement = this.renderer.createElement("span");
|
|
440
|
+
this.renderer.addClass(this.resizerElement, "resize-holder");
|
|
441
|
+
this.renderer.setAttribute(this.resizerElement, 'id', `resizeHolderSpan-${this.index}`);
|
|
442
|
+
this.renderer.appendChild(this.column, this.resizerElement);
|
|
443
|
+
this.renderer.listen(this.resizerElement, "mousedown", this.onMouseDown);
|
|
444
|
+
this.renderer.listen(this.table, "mousemove", this.onMouseMove);
|
|
445
|
+
this.renderer.listen("document", "mouseup", this.onMouseUp);
|
|
446
|
+
}
|
|
447
|
+
cleanup() {
|
|
448
|
+
this.removeDragElementFromDom();
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* @description This method is used to remove resizing handlers from the table headers when column resizing is disabled.
|
|
452
|
+
*/
|
|
453
|
+
removeDragElementFromDom() {
|
|
454
|
+
if (this.resizerElement) {
|
|
455
|
+
this.renderer.removeChild(this.column, this.resizerElement);
|
|
456
|
+
this.resizerElement = null;
|
|
457
|
+
}
|
|
458
|
+
// Also remove any existing resizer elements with the old ID pattern
|
|
459
|
+
const existingElement = document.getElementById(`resizeHolderSpan-${this.index}`);
|
|
460
|
+
if (existingElement) {
|
|
461
|
+
this.renderer.removeChild(this.column, existingElement);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.5", ngImport: i0, type: ResizeColumnDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
465
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.5", type: ResizeColumnDirective, isStandalone: true, selector: "[columnsResizable]", inputs: { columnsResizable: "columnsResizable", index: "index" }, usesOnChanges: true, ngImport: i0 }); }
|
|
466
|
+
}
|
|
467
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.5", ngImport: i0, type: ResizeColumnDirective, decorators: [{
|
|
468
|
+
type: Directive,
|
|
469
|
+
args: [{
|
|
470
|
+
selector: "[columnsResizable]",
|
|
471
|
+
standalone: true
|
|
472
|
+
}]
|
|
473
|
+
}], ctorParameters: () => [], propDecorators: { columnsResizable: [{
|
|
474
|
+
type: Input
|
|
475
|
+
}], index: [{
|
|
476
|
+
type: Input
|
|
477
|
+
}] } });
|
|
478
|
+
|
|
479
|
+
class MatTableExtComponent {
|
|
480
|
+
constructor(dialog, service, formBuilder, domSanitizer, matIconRegistry, cdr) {
|
|
481
|
+
this.dialog = dialog;
|
|
482
|
+
this.service = service;
|
|
483
|
+
this.formBuilder = formBuilder;
|
|
484
|
+
this.domSanitizer = domSanitizer;
|
|
485
|
+
this.matIconRegistry = matIconRegistry;
|
|
486
|
+
this.cdr = cdr;
|
|
487
|
+
this.columns = [];
|
|
488
|
+
this.columnResizable = false;
|
|
489
|
+
this.stripedRows = false;
|
|
490
|
+
this.rowHover = false;
|
|
491
|
+
this.inlineRowEditing = false;
|
|
492
|
+
this.inCellEditing = false;
|
|
493
|
+
this.cellPopupEditing = false;
|
|
494
|
+
this.popupRowEditing = false;
|
|
495
|
+
this.enableDelete = false;
|
|
496
|
+
this.rowSelection = false;
|
|
497
|
+
this.multiRowSelection = false;
|
|
498
|
+
this.stickyFooter = false;
|
|
499
|
+
this.stickyHeader = false;
|
|
500
|
+
this.showFooterRow = false;
|
|
501
|
+
this.columnFilter = false;
|
|
502
|
+
this.loadingIndicator = false;
|
|
503
|
+
this.sorting = false;
|
|
504
|
+
this.showToolbar = false;
|
|
505
|
+
this.toolbarTitle = '';
|
|
506
|
+
this.tableHeight = '';
|
|
507
|
+
this.toolbarHeight = '50px';
|
|
508
|
+
this.tableWidth = '100%';
|
|
509
|
+
this.scrollbarH = false;
|
|
510
|
+
this.columnHidable = false;
|
|
511
|
+
this.columnPinnable = false;
|
|
512
|
+
this.globalSearch = false;
|
|
513
|
+
this.expandRows = false;
|
|
514
|
+
this.dndColumns = false;
|
|
515
|
+
this.showPaginator = true;
|
|
516
|
+
this.showFirstLastButtons = false;
|
|
517
|
+
this.exportButtonEnable = false;
|
|
518
|
+
this.printButtonEnable = false;
|
|
519
|
+
this.pageSizeOptions = [10, 50, 100];
|
|
520
|
+
this.cellTemplateRefMap = {};
|
|
521
|
+
this.tableClassName = '';
|
|
522
|
+
this.columnGroups = [];
|
|
523
|
+
this.hiddenRowIndices = [];
|
|
524
|
+
this.enableRowHiding = false;
|
|
525
|
+
this.enableRowPinning = false;
|
|
526
|
+
this.topPinnedMaxHeight = ''; // Max height for top pinned table (e.g., '200px', '20vh')
|
|
527
|
+
this.bottomPinnedMaxHeight = ''; // Max height for bottom pinned table (e.g., '200px', '20vh')
|
|
528
|
+
this.pdfOrientation = 'portrait';
|
|
529
|
+
// Table outputs
|
|
530
|
+
this.inlineChange = new EventEmitter();
|
|
531
|
+
this.cellChange = new EventEmitter();
|
|
532
|
+
this.popupChange = new EventEmitter();
|
|
533
|
+
this.rowDeleted = new EventEmitter();
|
|
534
|
+
this.scroll = new EventEmitter();
|
|
535
|
+
this.selectionChanged = new EventEmitter();
|
|
536
|
+
this.expansionChange = new EventEmitter();
|
|
537
|
+
this.rowPinningChange = new EventEmitter();
|
|
538
|
+
this.tableID = new Date().getTime();
|
|
539
|
+
this.columnPinningOptions = [];
|
|
540
|
+
this.exportMenuCtrl = false;
|
|
541
|
+
this.columnPinMenuCtrl = false;
|
|
542
|
+
this.hideShowMenuCtrl = false;
|
|
543
|
+
this.rowDataTemp = {};
|
|
544
|
+
this.inlineEditingTemplateRefData = {};
|
|
545
|
+
this.displayedColumns = [];
|
|
546
|
+
this.showHideColumnsArray = [];
|
|
547
|
+
this.columnsList = [];
|
|
548
|
+
this.columnsArray = [];
|
|
549
|
+
this.headersFiltersIds = [];
|
|
550
|
+
this.columnsToDisplayWithExpand = [];
|
|
551
|
+
this.selection = new SelectionModel(false, []);
|
|
552
|
+
this.hiddenCtrl = new SelectionModel(true, []);
|
|
553
|
+
this.tableData = [];
|
|
554
|
+
this.filterValues = {};
|
|
555
|
+
this.pinnedTopRows = [];
|
|
556
|
+
this.pinnedBottomRows = [];
|
|
557
|
+
this.rowPinMenuPosition = { x: '0px', y: '0px' };
|
|
558
|
+
this.rowPinMenuRow = null;
|
|
559
|
+
this.globalFilter = '';
|
|
560
|
+
this.showHideFilter = '';
|
|
561
|
+
this.individualFilter = '';
|
|
562
|
+
this.toggleFilters = false;
|
|
563
|
+
this.hideRows = false;
|
|
564
|
+
this.currentRowIndex = -1;
|
|
565
|
+
this.currentRow = {};
|
|
566
|
+
this.cellEditing = {};
|
|
567
|
+
// Store original sizes before entering edit mode
|
|
568
|
+
this.originalSizesBeforeEdit = null;
|
|
569
|
+
this.hideShowMenuGroup = this.formBuilder.group({});
|
|
570
|
+
this.menuX = 0;
|
|
571
|
+
this.menuY = 0;
|
|
572
|
+
this.dynamicDisplayedColumns = [
|
|
573
|
+
{ filter: false, name: 'select', show: false },
|
|
574
|
+
{ filter: false, name: 'edit', show: false },
|
|
575
|
+
{ filter: false, name: 'popup', show: false },
|
|
576
|
+
{ filter: false, name: 'delete', show: false },
|
|
577
|
+
{ filter: false, name: 'freeze', show: false },
|
|
578
|
+
{ filter: false, name: 'hide', show: false },
|
|
579
|
+
{ filter: false, name: 'pin', show: false },
|
|
580
|
+
{ filter: false, name: 'expand', show: false },
|
|
581
|
+
];
|
|
582
|
+
this.inputPropertyKeys = [
|
|
583
|
+
'dataSource',
|
|
584
|
+
'columns',
|
|
585
|
+
'inlineRowEditing',
|
|
586
|
+
'popupRowEditing',
|
|
587
|
+
'enableDelete',
|
|
588
|
+
'enableRowFreezing',
|
|
589
|
+
'enableRowHiding',
|
|
590
|
+
'enableRowPinning',
|
|
591
|
+
'rowSelection',
|
|
592
|
+
'multiRowSelection',
|
|
593
|
+
'stickyHeader',
|
|
594
|
+
'stickyFooter',
|
|
595
|
+
'columnFilter',
|
|
596
|
+
'globalSearch',
|
|
597
|
+
'expandRows',
|
|
598
|
+
'sorting',
|
|
599
|
+
'columnGroups',
|
|
600
|
+
];
|
|
601
|
+
this.onWindowResizeBound = () => {
|
|
602
|
+
this.updatePinnedRowOffsets();
|
|
603
|
+
this.syncColumnSizesFromTop();
|
|
604
|
+
};
|
|
605
|
+
/**
|
|
606
|
+
* @description This mapping is used to set and update changesin the table.
|
|
607
|
+
*/
|
|
608
|
+
this.setPropertiesMap = {
|
|
609
|
+
dataSource: (value) => this.setTableDataSource(value),
|
|
610
|
+
columns: (value) => this.setColumnsData(value.currentValue),
|
|
611
|
+
inlineRowEditing: (value) => this.showHideColumn('edit', value.currentValue),
|
|
612
|
+
popupRowEditing: (value) => this.showHideColumn('popup', value.currentValue),
|
|
613
|
+
enableDelete: (value) => this.showHideColumn('delete', value.currentValue),
|
|
614
|
+
enableRowFreezing: (value) => this.showHideColumn('freeze', value.currentValue),
|
|
615
|
+
enableRowHiding: (value) => this.showHideColumn('hide', value.currentValue),
|
|
616
|
+
enableRowPinning: (value) => {
|
|
617
|
+
this.showHideColumn('pin', value.currentValue);
|
|
618
|
+
if (value.currentValue) {
|
|
619
|
+
this.initializePinnedRows();
|
|
620
|
+
}
|
|
621
|
+
},
|
|
622
|
+
rowSelection: (value) => this.setRowSelection(value.currentValue),
|
|
623
|
+
multiRowSelection: (value) => {
|
|
624
|
+
this.selection = new SelectionModel(value.currentValue, []);
|
|
625
|
+
},
|
|
626
|
+
stickyHeader: (value) => {
|
|
627
|
+
this.stickyHeader = value.currentValue;
|
|
628
|
+
// Recalculate pinned row offsets when sticky header changes
|
|
629
|
+
setTimeout(() => this.updatePinnedRowOffsets(), 100);
|
|
630
|
+
},
|
|
631
|
+
stickyFooter: (value) => {
|
|
632
|
+
this.stickyFooter = value.currentValue;
|
|
633
|
+
// Recalculate pinned row offsets when sticky footer changes
|
|
634
|
+
setTimeout(() => this.updatePinnedRowOffsets(), 100);
|
|
635
|
+
},
|
|
636
|
+
columnFilter: (value) => this.setColumnFilter(value.currentValue),
|
|
637
|
+
globalSearch: (value) => (this.dataSource.filterPredicate = this.createFilter()),
|
|
638
|
+
expandRows: (value) => {
|
|
639
|
+
this.loadingIndicator = true;
|
|
640
|
+
this.dataSource = new MatTableDataSource(this.tableData);
|
|
641
|
+
if (value.currentValue == true) {
|
|
642
|
+
if (!this.displayedColumns.includes('expand')) {
|
|
643
|
+
this.displayedColumns.push('expand');
|
|
644
|
+
this.columnsToDisplayWithExpand = [...this.displayedColumns];
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
else {
|
|
648
|
+
this.columnsToDisplayWithExpand = [...this.displayedColumns];
|
|
649
|
+
if (this.displayedColumns.includes('expand')) {
|
|
650
|
+
let index = this.displayedColumns.indexOf('expand');
|
|
651
|
+
this.displayedColumns.splice(index, 1);
|
|
652
|
+
}
|
|
653
|
+
this.expandedElement = null;
|
|
654
|
+
}
|
|
655
|
+
setTimeout(() => {
|
|
656
|
+
this.loadingIndicator = false;
|
|
657
|
+
}, 200);
|
|
658
|
+
},
|
|
659
|
+
sorting: (value) => {
|
|
660
|
+
this.dataSource.sort = this.sort;
|
|
661
|
+
if (this.enableRowPinning) {
|
|
662
|
+
this.pinnedTopDataSource.sort = this.sort;
|
|
663
|
+
this.pinnedBtmDataSource.sort = this.sort;
|
|
664
|
+
}
|
|
665
|
+
},
|
|
666
|
+
columnGroups: (value) => {
|
|
667
|
+
this.columnGroups = value.currentValue || [];
|
|
668
|
+
this.cdr.detectChanges();
|
|
669
|
+
// When group headers change, re-sync column sizes for pinned tables
|
|
670
|
+
if (this.enableRowPinning) {
|
|
671
|
+
setTimeout(() => this.syncColumnSizesFromTop(), 80);
|
|
672
|
+
}
|
|
673
|
+
},
|
|
674
|
+
};
|
|
675
|
+
this.pinnedTopDataSource = new MatTableDataSource([]);
|
|
676
|
+
this.pinnedBtmDataSource = new MatTableDataSource([]);
|
|
677
|
+
/**
|
|
678
|
+
* @description Check if row is pinned to top (for CSS class binding)
|
|
679
|
+
*/
|
|
680
|
+
this.isRowPinnedTop = (row) => {
|
|
681
|
+
return this.pinnedTopRows.includes(row);
|
|
682
|
+
};
|
|
683
|
+
/**
|
|
684
|
+
* @description Check if row is pinned to bottom (for CSS class binding)
|
|
685
|
+
*/
|
|
686
|
+
this.isRowPinnedBottom = (row) => {
|
|
687
|
+
return this.pinnedBottomRows.includes(row);
|
|
688
|
+
};
|
|
689
|
+
/**
|
|
690
|
+
* @description This method will take data from inline editing template and update in table data source.
|
|
691
|
+
* @param row updated row from inline editing template.
|
|
692
|
+
*/
|
|
693
|
+
this.updateInlineTemplateData = (row) => {
|
|
694
|
+
this.service.selectedRow.next(row);
|
|
695
|
+
};
|
|
696
|
+
this.addIconsToRegistry();
|
|
697
|
+
if (this.dataSource) {
|
|
698
|
+
this.tableData = this.dataSource.data;
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
/**
|
|
702
|
+
*
|
|
703
|
+
* @param changes changes captured each time user changes property value.
|
|
704
|
+
*/
|
|
705
|
+
/**
|
|
706
|
+
* Handle column pinning changes from ColumnPinningComponent
|
|
707
|
+
* @param updatedColumns Updated columns array with new pinning states
|
|
708
|
+
*/
|
|
709
|
+
updateColumns(updatedColumns) {
|
|
710
|
+
// Create a completely new columnsArray to trigger change detection
|
|
711
|
+
this.columnsArray = updatedColumns.map(col => ({ ...col }));
|
|
712
|
+
// Update showHideColumnsArray to keep it in sync
|
|
713
|
+
this.showHideColumnsArray = [...this.columnsArray];
|
|
714
|
+
// Re-apply column configurations
|
|
715
|
+
this.setColumnsList(this.columnsArray);
|
|
716
|
+
// Force complete table re-render by recreating the data source
|
|
717
|
+
if (this.dataSource) {
|
|
718
|
+
const currentData = [...this.dataSource.data];
|
|
719
|
+
this.dataSource = new MatTableDataSource(currentData);
|
|
720
|
+
this.pinnedTopDataSource = new MatTableDataSource(this.pinnedTopRows);
|
|
721
|
+
this.pinnedBtmDataSource = new MatTableDataSource(this.pinnedBottomRows);
|
|
722
|
+
this.reCal(); // Re-apply paginator, sort, and filter
|
|
723
|
+
}
|
|
724
|
+
if (this.columnFilter) {
|
|
725
|
+
this.setColumnFilter(true);
|
|
726
|
+
}
|
|
727
|
+
// Force change detection
|
|
728
|
+
this.cdr.markForCheck();
|
|
729
|
+
this.cdr.detectChanges();
|
|
730
|
+
// Re-sync column sizes in case column ordering/visibility changed
|
|
731
|
+
if (this.enableRowPinning) {
|
|
732
|
+
setTimeout(() => this.syncColumnSizesFromTop(), 80);
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
ngOnChanges(changes) {
|
|
736
|
+
this.setPropertyValue(changes);
|
|
737
|
+
}
|
|
738
|
+
ngOnInit() {
|
|
739
|
+
if (this.dataSource) {
|
|
740
|
+
this.dataSource.filterPredicate = this.createFilter();
|
|
741
|
+
}
|
|
742
|
+
// Initialize FormGroup if not already initialized
|
|
743
|
+
if (!this.hideShowMenuGroup || Object.keys(this.hideShowMenuGroup.controls).length === 0) {
|
|
744
|
+
this.hideShowMenuGroup = this.formBuilder.group({});
|
|
745
|
+
}
|
|
746
|
+
// Initialize pinned rows if function provided
|
|
747
|
+
if (this.enableRowPinning) {
|
|
748
|
+
this.initializePinnedRows();
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
ngAfterViewInit() {
|
|
752
|
+
if (this.dataSource) {
|
|
753
|
+
this.dataSource.paginator = this.paginator;
|
|
754
|
+
this.dataSource.sort = this.sort;
|
|
755
|
+
this.setSorting();
|
|
756
|
+
}
|
|
757
|
+
// Calculate and set pinned row offsets
|
|
758
|
+
this.updatePinnedRowOffsets();
|
|
759
|
+
// Sync column sizes from top table to middle/bottom when pinning enabled
|
|
760
|
+
if (this.enableRowPinning) {
|
|
761
|
+
setTimeout(() => this.syncColumnSizesFromTop(), 150);
|
|
762
|
+
window.addEventListener('resize', this.onWindowResizeBound);
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
setSorting() {
|
|
766
|
+
if (this.enableRowPinning) {
|
|
767
|
+
if (this.pinnedTopDataSource) {
|
|
768
|
+
if (this.pinnedTopDataSource.sort) {
|
|
769
|
+
this.pinnedTopDataSource.sort = this.sort;
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
if (this.pinnedBtmDataSource) {
|
|
773
|
+
if (this.pinnedBtmDataSource.sort) {
|
|
774
|
+
this.pinnedBtmDataSource.sort = this.sort;
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
/**
|
|
780
|
+
* @description Calculate offsets for pinned rows based on sticky headers/footers
|
|
781
|
+
*/
|
|
782
|
+
updatePinnedRowOffsets() {
|
|
783
|
+
if (!this.tableElement?.nativeElement || !this.enableRowPinning)
|
|
784
|
+
return;
|
|
785
|
+
setTimeout(() => {
|
|
786
|
+
const table = this.tableElement.nativeElement;
|
|
787
|
+
// Calculate top offset (sticky header + group header + filter row)
|
|
788
|
+
let topOffset = 0;
|
|
789
|
+
if (this.stickyHeader) {
|
|
790
|
+
// Get all header rows that are sticky
|
|
791
|
+
const headerRows = table.querySelectorAll('.mat-mdc-header-row');
|
|
792
|
+
headerRows.forEach((header) => {
|
|
793
|
+
topOffset += header.offsetHeight;
|
|
794
|
+
});
|
|
795
|
+
}
|
|
796
|
+
// Calculate bottom offset (sticky footer + paginator)
|
|
797
|
+
let bottomOffset = 0;
|
|
798
|
+
if (this.stickyFooter) {
|
|
799
|
+
const footerRow = table.querySelector('.mat-mdc-footer-row');
|
|
800
|
+
if (footerRow) {
|
|
801
|
+
bottomOffset += footerRow.offsetHeight;
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
// Set base offsets
|
|
805
|
+
table.style.setProperty('--pinned-top-base-offset', `${topOffset}px`);
|
|
806
|
+
table.style.setProperty('--pinned-bottom-base-offset', `${bottomOffset}px`);
|
|
807
|
+
// Calculate and set individual row offsets for stacked pinned rows
|
|
808
|
+
this.updateStackedPinnedRowOffsets(table, topOffset, bottomOffset);
|
|
809
|
+
// After offsets are updated, ensure column sizes are re-synced
|
|
810
|
+
if (this.enableRowPinning) {
|
|
811
|
+
setTimeout(() => this.syncColumnSizesFromTop(), 10);
|
|
812
|
+
}
|
|
813
|
+
console.log('Pinned row offsets:', { topOffset, bottomOffset });
|
|
814
|
+
}, 100);
|
|
815
|
+
}
|
|
816
|
+
/**
|
|
817
|
+
* @description Update offsets for each individual pinned row to stack them
|
|
818
|
+
*/
|
|
819
|
+
updateStackedPinnedRowOffsets(table, baseTopOffset, baseBottomOffset) {
|
|
820
|
+
// Use setTimeout to ensure DOM is fully rendered with pinned classes
|
|
821
|
+
setTimeout(() => {
|
|
822
|
+
// Handle top pinned rows - stack them from top to bottom
|
|
823
|
+
const topPinnedRows = table.querySelectorAll('.pinned-top-row');
|
|
824
|
+
let currentTopOffset = baseTopOffset;
|
|
825
|
+
topPinnedRows.forEach((row, index) => {
|
|
826
|
+
const htmlRow = row;
|
|
827
|
+
htmlRow.style.setProperty('--pinned-row-top-offset', `${currentTopOffset}px`);
|
|
828
|
+
htmlRow.style.top = `${currentTopOffset}px`;
|
|
829
|
+
// Add current row height to offset for next row
|
|
830
|
+
if (index < topPinnedRows.length - 1) {
|
|
831
|
+
currentTopOffset += htmlRow.offsetHeight;
|
|
832
|
+
}
|
|
833
|
+
});
|
|
834
|
+
// Handle bottom pinned rows - stack them from bottom to top
|
|
835
|
+
const bottomPinnedRows = table.querySelectorAll('.pinned-bottom-row');
|
|
836
|
+
let currentBottomOffset = baseBottomOffset;
|
|
837
|
+
// Process bottom rows in reverse order (from bottom to top)
|
|
838
|
+
for (let i = bottomPinnedRows.length - 1; i >= 0; i--) {
|
|
839
|
+
const htmlRow = bottomPinnedRows[i];
|
|
840
|
+
htmlRow.style.setProperty('--pinned-row-bottom-offset', `${currentBottomOffset}px`);
|
|
841
|
+
htmlRow.style.bottom = `${currentBottomOffset}px`;
|
|
842
|
+
// Add current row height to offset for next row (going upward)
|
|
843
|
+
if (i > 0) {
|
|
844
|
+
currentBottomOffset += htmlRow.offsetHeight;
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
// After stacking offsets are applied, re-sync column sizes to handle any layout changes
|
|
848
|
+
if (this.enableRowPinning) {
|
|
849
|
+
setTimeout(() => this.syncColumnSizesFromTop(), 60);
|
|
850
|
+
}
|
|
851
|
+
}, 50);
|
|
852
|
+
}
|
|
853
|
+
/**
|
|
854
|
+
* Copy header cell widths/heights from the top table and apply them to middle and bottom tables.
|
|
855
|
+
* This ensures columns line up when the middle/bottom tables don't render headers.
|
|
856
|
+
*/
|
|
857
|
+
syncColumnSizesFromTop() {
|
|
858
|
+
if (!this.enableRowPinning)
|
|
859
|
+
return;
|
|
860
|
+
try {
|
|
861
|
+
const topId = `matTableExtTop${this.tableID}`;
|
|
862
|
+
const bottomId = `matTableExtBtm${this.tableID}`;
|
|
863
|
+
const topTable = document.getElementById(topId);
|
|
864
|
+
const middleTable = document.getElementById(`matTableExt${this.tableID}`);
|
|
865
|
+
const bottomTable = document.getElementById(bottomId);
|
|
866
|
+
if (!topTable)
|
|
867
|
+
return;
|
|
868
|
+
const headerRow = topTable.querySelector('tr.mat-mdc-header-row:not(.group-header-row), tr.mat-header-row:not(.group-header-row), thead tr:not(.group-header-row)');
|
|
869
|
+
if (!headerRow)
|
|
870
|
+
return;
|
|
871
|
+
const headerCells = Array.from(headerRow.querySelectorAll('th, .mat-header-cell'));
|
|
872
|
+
if (!headerCells.length)
|
|
873
|
+
return;
|
|
874
|
+
const topTableWidth = topTable.getBoundingClientRect().width;
|
|
875
|
+
[middleTable, bottomTable].forEach(tbl => {
|
|
876
|
+
if (!tbl)
|
|
877
|
+
return;
|
|
878
|
+
tbl.style.width = topTable.style.width && topTable.style.width !== '' ? topTable.style.width : `${topTableWidth}px`;
|
|
879
|
+
});
|
|
880
|
+
// Use the header row height as the canonical row height to apply
|
|
881
|
+
const headerRowHeight = Math.round(headerRow.getBoundingClientRect().height);
|
|
882
|
+
headerCells.forEach((hc, index) => {
|
|
883
|
+
const rect = hc.getBoundingClientRect();
|
|
884
|
+
const w = Math.round(rect.width);
|
|
885
|
+
[middleTable, bottomTable].forEach(tbl => {
|
|
886
|
+
if (!tbl)
|
|
887
|
+
return;
|
|
888
|
+
// If a placeholder header exists in the target table, set its cell sizes
|
|
889
|
+
const placeholderHeader = tbl.querySelector('tr.mat-mdc-header-row, tr.mat-header-row');
|
|
890
|
+
if (placeholderHeader) {
|
|
891
|
+
const phCells = placeholderHeader.querySelectorAll('th, .mat-header-cell');
|
|
892
|
+
if (phCells && phCells[index]) {
|
|
893
|
+
const el = phCells[index];
|
|
894
|
+
el.style.minWidth = `${w}px`;
|
|
895
|
+
el.style.maxWidth = `${w}px`;
|
|
896
|
+
el.style.boxSizing = 'border-box';
|
|
897
|
+
el.style.height = `${headerRowHeight}px`;
|
|
898
|
+
el.style.minHeight = `${headerRowHeight}px`;
|
|
899
|
+
el.style.maxHeight = `${headerRowHeight}px`;
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
// Apply widths/heights directly to data cells (in case header placeholder is not present)
|
|
903
|
+
const dataRow = tbl.querySelector('tr.mat-mdc-row, tr.mat-row');
|
|
904
|
+
if (dataRow) {
|
|
905
|
+
const dataCells = dataRow.querySelectorAll('td, .mat-cell');
|
|
906
|
+
if (dataCells && dataCells[index]) {
|
|
907
|
+
const cel = dataCells[index];
|
|
908
|
+
cel.style.minWidth = `${w}px`;
|
|
909
|
+
cel.style.maxWidth = `${w}px`;
|
|
910
|
+
cel.style.boxSizing = 'border-box';
|
|
911
|
+
cel.style.height = `${headerRowHeight}px`;
|
|
912
|
+
cel.style.minHeight = `${headerRowHeight}px`;
|
|
913
|
+
cel.style.maxHeight = `${headerRowHeight}px`;
|
|
914
|
+
}
|
|
915
|
+
// Set every data row's height to match the header row height for visual alignment
|
|
916
|
+
const rows = tbl.querySelectorAll('tr.mat-mdc-row, tr.mat-row');
|
|
917
|
+
rows.forEach((r) => {
|
|
918
|
+
const reh = r;
|
|
919
|
+
reh.style.height = `${headerRowHeight}px`;
|
|
920
|
+
reh.style.minHeight = `${headerRowHeight}px`;
|
|
921
|
+
reh.style.maxHeight = `${headerRowHeight}px`;
|
|
922
|
+
});
|
|
923
|
+
}
|
|
924
|
+
});
|
|
925
|
+
});
|
|
926
|
+
}
|
|
927
|
+
catch (err) {
|
|
928
|
+
console.warn('syncColumnSizesFromTop failed', err);
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
/**
|
|
932
|
+
* Sync column sizes from the currently edited row in the middle table to top/bottom tables.
|
|
933
|
+
* This ensures proper alignment when a row is in edit mode with different height.
|
|
934
|
+
*/
|
|
935
|
+
syncColumnSizesFromEditedRow(editedRowIndex) {
|
|
936
|
+
if (!this.enableRowPinning)
|
|
937
|
+
return;
|
|
938
|
+
try {
|
|
939
|
+
const topTable = document.getElementById(`matTableExtTop${this.tableID}`);
|
|
940
|
+
if (!topTable)
|
|
941
|
+
return;
|
|
942
|
+
// Capture original sizes from the top table header before modifying
|
|
943
|
+
if (!this.originalSizesBeforeEdit) {
|
|
944
|
+
const headerRow = topTable.querySelector('tr.mat-mdc-header-row:not(.group-header-row), tr.mat-header-row:not(.group-header-row)');
|
|
945
|
+
if (headerRow) {
|
|
946
|
+
const headerCells = Array.from(headerRow.querySelectorAll('th, .mat-header-cell'));
|
|
947
|
+
const headerRowHeight = Math.round(headerRow.getBoundingClientRect().height);
|
|
948
|
+
const columnWidths = headerCells.map(cell => Math.round(cell.getBoundingClientRect().width));
|
|
949
|
+
this.originalSizesBeforeEdit = {
|
|
950
|
+
columnWidths,
|
|
951
|
+
rowHeight: headerRowHeight
|
|
952
|
+
};
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
const middleTable = document.getElementById(`matTableExt${this.tableID}`);
|
|
956
|
+
const bottomTable = document.getElementById(`matTableExtBtm${this.tableID}`);
|
|
957
|
+
if (!middleTable || !topTable)
|
|
958
|
+
return;
|
|
959
|
+
// Find the edited row in the middle table
|
|
960
|
+
const editedRow = middleTable.querySelector(`tr.mat-mdc-row:nth-child(${editedRowIndex + 1})`);
|
|
961
|
+
if (!editedRow) {
|
|
962
|
+
// Fallback to normal sync if edited row not found
|
|
963
|
+
this.syncColumnSizesFromTop();
|
|
964
|
+
return;
|
|
965
|
+
}
|
|
966
|
+
const editedCells = Array.from(editedRow.querySelectorAll('td, .mat-cell'));
|
|
967
|
+
if (!editedCells.length)
|
|
968
|
+
return;
|
|
969
|
+
// Get the height of the edited row
|
|
970
|
+
const editedRowHeight = Math.round(editedRow.getBoundingClientRect().height);
|
|
971
|
+
// Sync widths and heights from edited row to top and bottom tables
|
|
972
|
+
// First, collect all widths in a single pass (layout read)
|
|
973
|
+
const cellWidths = editedCells.map(cell => Math.round(cell.getBoundingClientRect().width));
|
|
974
|
+
// Then, apply style changes in a separate pass (layout write)
|
|
975
|
+
cellWidths.forEach((w, index) => {
|
|
976
|
+
[topTable, bottomTable].forEach(tbl => {
|
|
977
|
+
if (!tbl)
|
|
978
|
+
return;
|
|
979
|
+
// Update header cells in top table
|
|
980
|
+
if (tbl === topTable) {
|
|
981
|
+
const headerRow = tbl.querySelector('tr.mat-mdc-header-row:not(.group-header-row), tr.mat-header-row:not(.group-header-row)');
|
|
982
|
+
if (headerRow) {
|
|
983
|
+
const headerCells = headerRow.querySelectorAll('th, .mat-header-cell');
|
|
984
|
+
if (headerCells && headerCells[index]) {
|
|
985
|
+
const hc = headerCells[index];
|
|
986
|
+
hc.style.minWidth = `${w}px`;
|
|
987
|
+
hc.style.maxWidth = `${w}px`;
|
|
988
|
+
hc.style.boxSizing = 'border-box';
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
// Update data cells in both tables
|
|
993
|
+
const dataRow = tbl.querySelector('tr.mat-mdc-row, tr.mat-row');
|
|
994
|
+
if (dataRow) {
|
|
995
|
+
const dataCells = dataRow.querySelectorAll('td, .mat-cell');
|
|
996
|
+
if (dataCells && dataCells[index]) {
|
|
997
|
+
const dc = dataCells[index];
|
|
998
|
+
dc.style.minWidth = `${w}px`;
|
|
999
|
+
dc.style.maxWidth = `${w}px`;
|
|
1000
|
+
dc.style.boxSizing = 'border-box';
|
|
1001
|
+
}
|
|
1002
|
+
// Set all data rows' height to match the edited row height
|
|
1003
|
+
// const rows = tbl.querySelectorAll('tr.mat-mdc-row, tr.mat-row');
|
|
1004
|
+
// rows.forEach((r: Element) => {
|
|
1005
|
+
// const reh = r as HTMLElement;
|
|
1006
|
+
// reh.style.height = `${editedRowHeight}px`;
|
|
1007
|
+
// reh.style.minHeight = `${editedRowHeight}px`;
|
|
1008
|
+
// reh.style.maxHeight = `${editedRowHeight}px`;
|
|
1009
|
+
// });
|
|
1010
|
+
}
|
|
1011
|
+
});
|
|
1012
|
+
});
|
|
1013
|
+
}
|
|
1014
|
+
catch (err) {
|
|
1015
|
+
console.warn('syncColumnSizesFromEditedRow failed', err);
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
/**
|
|
1019
|
+
* Restore original column widths and row heights from before edit mode.
|
|
1020
|
+
*/
|
|
1021
|
+
restoreOriginalSizes() {
|
|
1022
|
+
if (!this.enableRowPinning || !this.originalSizesBeforeEdit)
|
|
1023
|
+
return;
|
|
1024
|
+
try {
|
|
1025
|
+
const topTable = document.getElementById(`matTableExtTop${this.tableID}`);
|
|
1026
|
+
const middleTable = document.getElementById(`matTableExt${this.tableID}`);
|
|
1027
|
+
const bottomTable = document.getElementById(`matTableExtBtm${this.tableID}`);
|
|
1028
|
+
if (!topTable)
|
|
1029
|
+
return;
|
|
1030
|
+
const { columnWidths, rowHeight } = this.originalSizesBeforeEdit;
|
|
1031
|
+
[topTable, middleTable, bottomTable].forEach(tbl => {
|
|
1032
|
+
if (!tbl)
|
|
1033
|
+
return;
|
|
1034
|
+
// Restore header cells in top table
|
|
1035
|
+
if (tbl === topTable) {
|
|
1036
|
+
const headerRow = tbl.querySelector('tr.mat-mdc-header-row:not(.group-header-row), tr.mat-header-row:not(.group-header-row)');
|
|
1037
|
+
if (headerRow) {
|
|
1038
|
+
const headerCells = Array.from(headerRow.querySelectorAll('th, .mat-header-cell'));
|
|
1039
|
+
headerCells.forEach((cell, index) => {
|
|
1040
|
+
if (columnWidths[index] !== undefined) {
|
|
1041
|
+
const w = columnWidths[index];
|
|
1042
|
+
cell.style.minWidth = `${w}px`;
|
|
1043
|
+
cell.style.maxWidth = `${w}px`;
|
|
1044
|
+
cell.style.boxSizing = 'border-box';
|
|
1045
|
+
cell.style.height = `${rowHeight}px`;
|
|
1046
|
+
cell.style.minHeight = `${rowHeight}px`;
|
|
1047
|
+
cell.style.maxHeight = `${rowHeight}px`;
|
|
1048
|
+
}
|
|
1049
|
+
});
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
// Restore data cells
|
|
1053
|
+
const dataRow = tbl.querySelector('tr.mat-mdc-row, tr.mat-row');
|
|
1054
|
+
if (dataRow) {
|
|
1055
|
+
const dataCells = Array.from(dataRow.querySelectorAll('td, .mat-cell'));
|
|
1056
|
+
dataCells.forEach((cell, index) => {
|
|
1057
|
+
if (columnWidths[index] !== undefined) {
|
|
1058
|
+
const w = columnWidths[index];
|
|
1059
|
+
cell.style.minWidth = `${w}px`;
|
|
1060
|
+
cell.style.maxWidth = `${w}px`;
|
|
1061
|
+
cell.style.boxSizing = 'border-box';
|
|
1062
|
+
cell.style.height = `${rowHeight}px`;
|
|
1063
|
+
cell.style.minHeight = `${rowHeight}px`;
|
|
1064
|
+
cell.style.maxHeight = `${rowHeight}px`;
|
|
1065
|
+
}
|
|
1066
|
+
});
|
|
1067
|
+
// Restore all data rows' height
|
|
1068
|
+
const rows = tbl.querySelectorAll('tr.mat-mdc-row, tr.mat-row');
|
|
1069
|
+
rows.forEach((r) => {
|
|
1070
|
+
const reh = r;
|
|
1071
|
+
reh.style.height = `${rowHeight}px`;
|
|
1072
|
+
reh.style.minHeight = `${rowHeight}px`;
|
|
1073
|
+
reh.style.maxHeight = `${rowHeight}px`;
|
|
1074
|
+
});
|
|
1075
|
+
}
|
|
1076
|
+
});
|
|
1077
|
+
// Clear the stored sizes
|
|
1078
|
+
this.originalSizesBeforeEdit = null;
|
|
1079
|
+
}
|
|
1080
|
+
catch (err) {
|
|
1081
|
+
console.warn('restoreOriginalSizes failed', err);
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
ngOnDestroy() {
|
|
1085
|
+
window.removeEventListener('resize', this.onWindowResizeBound);
|
|
1086
|
+
}
|
|
1087
|
+
/**
|
|
1088
|
+
* @description checks and updates the the column's hide and show properties.
|
|
1089
|
+
*/
|
|
1090
|
+
setColumnHideShow() {
|
|
1091
|
+
if (this.hideShowMenuGroup !== undefined &&
|
|
1092
|
+
this.hideShowMenuGroup !== null) {
|
|
1093
|
+
this.updateColumnsHideShow(this.hideShowMenuGroup.value);
|
|
1094
|
+
}
|
|
1095
|
+
}
|
|
1096
|
+
/**
|
|
1097
|
+
* @description set the properties of the table.
|
|
1098
|
+
* @param changes changes captured each time user changes property value.
|
|
1099
|
+
*/
|
|
1100
|
+
setPropertyValue(changes) {
|
|
1101
|
+
let keys = Object.keys(changes);
|
|
1102
|
+
keys.forEach((property) => {
|
|
1103
|
+
if (this.inputPropertyKeys.includes(property)) {
|
|
1104
|
+
this.setPropertiesMap[property](changes[property]);
|
|
1105
|
+
setTimeout(() => this.syncColumnSizesFromTop(), 80);
|
|
1106
|
+
}
|
|
1107
|
+
else if (property == 'showToolbar') {
|
|
1108
|
+
if (changes['columns']) {
|
|
1109
|
+
this.setToolbarMenuControls(changes['columns'].currentValue);
|
|
1110
|
+
}
|
|
1111
|
+
else {
|
|
1112
|
+
this.setToolbarMenuControls(this.columnsArray);
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
});
|
|
1116
|
+
}
|
|
1117
|
+
/**
|
|
1118
|
+
* @description used set data source for table.
|
|
1119
|
+
* @param value data source value from user.
|
|
1120
|
+
*/
|
|
1121
|
+
setTableDataSource(value) {
|
|
1122
|
+
if (value.currentValue) {
|
|
1123
|
+
this.tableData = value.currentValue.data;
|
|
1124
|
+
this.dataSource = value.currentValue;
|
|
1125
|
+
this.reCal();
|
|
1126
|
+
}
|
|
1127
|
+
else {
|
|
1128
|
+
this.dataSource = new MatTableDataSource([{}]);
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
/**
|
|
1132
|
+
* @description used create seletion model and set selection column visibility.
|
|
1133
|
+
* @param value boolean value to show or hide selection Column from table.
|
|
1134
|
+
*/
|
|
1135
|
+
setRowSelection(value) {
|
|
1136
|
+
this.selection = new SelectionModel(true, []);
|
|
1137
|
+
this.updateSelectionColumnVisibility(value);
|
|
1138
|
+
}
|
|
1139
|
+
/**
|
|
1140
|
+
* @description create filter header row and assigns filter predicate to table data source.
|
|
1141
|
+
* @param value boolean value to change visibility of column filter row.
|
|
1142
|
+
*/
|
|
1143
|
+
setColumnFilter(value) {
|
|
1144
|
+
if (value) {
|
|
1145
|
+
let array = [];
|
|
1146
|
+
this.columnsArray.forEach((column, i) => {
|
|
1147
|
+
if (this.dynamicDisplayedColumns.filter((a) => a.name == column?.field)[0]
|
|
1148
|
+
.show) {
|
|
1149
|
+
array.push(column?.field + '_' + i);
|
|
1150
|
+
}
|
|
1151
|
+
});
|
|
1152
|
+
this.headersFiltersIds = array;
|
|
1153
|
+
this.dataSource.filterPredicate = this.createFilter();
|
|
1154
|
+
}
|
|
1155
|
+
else {
|
|
1156
|
+
this.headersFiltersIds = [];
|
|
1157
|
+
this.dataSource.filter = '';
|
|
1158
|
+
}
|
|
1159
|
+
this.toggleFilters = value;
|
|
1160
|
+
setTimeout(() => this.syncColumnSizesFromTop(), 150);
|
|
1161
|
+
}
|
|
1162
|
+
/**
|
|
1163
|
+
* @description This method returns the list of visible column names.
|
|
1164
|
+
* @returns list of visible column names.
|
|
1165
|
+
*/
|
|
1166
|
+
getDisplayedColumns() {
|
|
1167
|
+
if (this.columnGroups.length === 0) {
|
|
1168
|
+
// No groups, place select at start and other action columns at the end
|
|
1169
|
+
const actionColumns = ['select', 'edit', 'popup', 'delete', 'freeze', 'hide', 'pin'];
|
|
1170
|
+
const visibleColumns = this.dynamicDisplayedColumns.filter((cd) => cd.show);
|
|
1171
|
+
const dataColumns = visibleColumns.filter((cd) => !actionColumns.includes(cd.name)).map((cd) => cd.name);
|
|
1172
|
+
const selectCol = visibleColumns.find((cd) => cd.name === 'select');
|
|
1173
|
+
const otherActionCols = visibleColumns.filter((cd) => actionColumns.includes(cd.name) && cd.name !== 'select').map((cd) => cd.name);
|
|
1174
|
+
const result = [];
|
|
1175
|
+
if (selectCol)
|
|
1176
|
+
result.push('select');
|
|
1177
|
+
result.push(...dataColumns);
|
|
1178
|
+
result.push(...otherActionCols);
|
|
1179
|
+
return result;
|
|
1180
|
+
}
|
|
1181
|
+
// When groups exist, reorder: select first, grouped columns, ungrouped columns, then other action columns
|
|
1182
|
+
const actionColumns = ['select', 'edit', 'popup', 'delete', 'freeze', 'hide', 'pin'];
|
|
1183
|
+
const groupedFields = new Set();
|
|
1184
|
+
// Collect all fields that belong to groups
|
|
1185
|
+
this.columnGroups.forEach(group => {
|
|
1186
|
+
group.columns.forEach(colField => groupedFields.add(colField));
|
|
1187
|
+
});
|
|
1188
|
+
const result = [];
|
|
1189
|
+
const visibleColumns = this.dynamicDisplayedColumns.filter((cd) => cd.show);
|
|
1190
|
+
// Add select column first if visible
|
|
1191
|
+
const selectCol = visibleColumns.find(c => c.name === 'select');
|
|
1192
|
+
if (selectCol) {
|
|
1193
|
+
result.push('select');
|
|
1194
|
+
}
|
|
1195
|
+
// Add grouped columns in the order they appear in groups
|
|
1196
|
+
this.columnGroups.forEach(group => {
|
|
1197
|
+
group.columns.forEach(colField => {
|
|
1198
|
+
const col = visibleColumns.find(c => c.name === colField);
|
|
1199
|
+
if (col && !result.includes(col.name)) {
|
|
1200
|
+
result.push(col.name);
|
|
1201
|
+
}
|
|
1202
|
+
});
|
|
1203
|
+
});
|
|
1204
|
+
// Add ungrouped data columns
|
|
1205
|
+
visibleColumns.forEach(col => {
|
|
1206
|
+
if (!actionColumns.includes(col.name) && !groupedFields.has(col.name) && !result.includes(col.name)) {
|
|
1207
|
+
result.push(col.name);
|
|
1208
|
+
}
|
|
1209
|
+
});
|
|
1210
|
+
// Add other action columns at the end (excluding select which is already at start)
|
|
1211
|
+
visibleColumns.forEach(col => {
|
|
1212
|
+
if (actionColumns.includes(col.name) && col.name !== 'select' && !result.includes(col.name)) {
|
|
1213
|
+
result.push(col.name);
|
|
1214
|
+
}
|
|
1215
|
+
});
|
|
1216
|
+
return result;
|
|
1217
|
+
}
|
|
1218
|
+
/**
|
|
1219
|
+
* @description This method returns the grouped column header definitions.
|
|
1220
|
+
* @returns list of grouped column definitions for header row.
|
|
1221
|
+
*/
|
|
1222
|
+
getGroupedColumns() {
|
|
1223
|
+
if (this.columnGroups.length === 0)
|
|
1224
|
+
return [];
|
|
1225
|
+
const grouped = [];
|
|
1226
|
+
const groupedFields = new Set();
|
|
1227
|
+
const actionColumns = ['select', 'edit', 'popup', 'delete', 'freeze', 'hide', 'pin'];
|
|
1228
|
+
// Collect all fields that belong to groups
|
|
1229
|
+
this.columnGroups.forEach(group => {
|
|
1230
|
+
group.columns.forEach(colField => groupedFields.add(colField));
|
|
1231
|
+
});
|
|
1232
|
+
// Add group headers for groups with visible columns
|
|
1233
|
+
this.columnGroups.forEach(group => {
|
|
1234
|
+
const visibleColumnsInGroup = group.columns.filter(colField => {
|
|
1235
|
+
const displayCol = this.dynamicDisplayedColumns.find(dc => dc.name === colField);
|
|
1236
|
+
return displayCol && displayCol.show;
|
|
1237
|
+
});
|
|
1238
|
+
if (visibleColumnsInGroup.length > 0) {
|
|
1239
|
+
grouped.push('group-' + group.name);
|
|
1240
|
+
}
|
|
1241
|
+
});
|
|
1242
|
+
// Add empty header placeholders for ungrouped columns at the end
|
|
1243
|
+
this.columnsArray.forEach(col => {
|
|
1244
|
+
if (!groupedFields.has(col.field) && !actionColumns.includes(col.field)) {
|
|
1245
|
+
const displayCol = this.dynamicDisplayedColumns.find(dc => dc.name === col.field);
|
|
1246
|
+
if (displayCol && displayCol.show) {
|
|
1247
|
+
grouped.push('ungrouped-' + col.field);
|
|
1248
|
+
}
|
|
1249
|
+
}
|
|
1250
|
+
});
|
|
1251
|
+
// Add placeholders for visible action columns so group header row has cells to align with action columns
|
|
1252
|
+
const actionPlaceholders = ['select', 'edit', 'popup', 'delete', 'freeze', 'hide', 'pin'];
|
|
1253
|
+
actionPlaceholders.forEach(act => {
|
|
1254
|
+
const display = this.dynamicDisplayedColumns.find(dc => dc.name === act);
|
|
1255
|
+
if (display && display.show) {
|
|
1256
|
+
grouped.push('ungrouped-' + act);
|
|
1257
|
+
}
|
|
1258
|
+
});
|
|
1259
|
+
return grouped;
|
|
1260
|
+
}
|
|
1261
|
+
/**
|
|
1262
|
+
* @description Returns filter column IDs including placeholders for action columns
|
|
1263
|
+
* @returns Array of filter column IDs with action column placeholders
|
|
1264
|
+
*/
|
|
1265
|
+
getFilterColumns() {
|
|
1266
|
+
const filters = [];
|
|
1267
|
+
const actionColumns = ['select', 'edit', 'popup', 'delete', 'freeze', 'hide', 'pin'];
|
|
1268
|
+
// Get visible columns in display order
|
|
1269
|
+
const displayedCols = this.getDisplayedColumns();
|
|
1270
|
+
displayedCols.forEach(colName => {
|
|
1271
|
+
if (actionColumns.includes(colName)) {
|
|
1272
|
+
// Add filter placeholder for action column
|
|
1273
|
+
filters.push('filter-' + colName);
|
|
1274
|
+
}
|
|
1275
|
+
else {
|
|
1276
|
+
// Find the actual filter ID from headersFiltersIds
|
|
1277
|
+
const filterCol = this.headersFiltersIds.find(id => id.startsWith(colName + '_'));
|
|
1278
|
+
if (filterCol) {
|
|
1279
|
+
filters.push(filterCol);
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
});
|
|
1283
|
+
return this.columnFilter ? filters : [];
|
|
1284
|
+
}
|
|
1285
|
+
/**
|
|
1286
|
+
* @param menuType type of menu to open from toolbar.
|
|
1287
|
+
* @param event mouse event to open menu on that location.
|
|
1288
|
+
*/
|
|
1289
|
+
openMenu(menuType, event) {
|
|
1290
|
+
this.menuX = event.clientX;
|
|
1291
|
+
this.menuY = event.clientY;
|
|
1292
|
+
switch (menuType) {
|
|
1293
|
+
case 'export': {
|
|
1294
|
+
this.exportMenuCtrl = true;
|
|
1295
|
+
this.menuTrigger.openMenu();
|
|
1296
|
+
break;
|
|
1297
|
+
}
|
|
1298
|
+
case 'hideShow': {
|
|
1299
|
+
this.hideShowMenuCtrl = true;
|
|
1300
|
+
this.openHideShowMenu(this.columnsArray);
|
|
1301
|
+
break;
|
|
1302
|
+
}
|
|
1303
|
+
case 'columnPin': {
|
|
1304
|
+
this.columnPinMenuCtrl = true;
|
|
1305
|
+
this.openHideShowMenu(this.columnsArray);
|
|
1306
|
+
break;
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1309
|
+
}
|
|
1310
|
+
/**
|
|
1311
|
+
* @description triggers when menu is closed and reset the required controls.
|
|
1312
|
+
*/
|
|
1313
|
+
menuClosed() {
|
|
1314
|
+
this.exportMenuCtrl = false;
|
|
1315
|
+
}
|
|
1316
|
+
/**
|
|
1317
|
+
* @description set list of columns to display in table.
|
|
1318
|
+
* @param columns columns array from user input.
|
|
1319
|
+
*/
|
|
1320
|
+
setColumnsData(columns) {
|
|
1321
|
+
if (columns.length) {
|
|
1322
|
+
this.columnsArray = [...columns];
|
|
1323
|
+
this.setColumnsList(columns);
|
|
1324
|
+
this.setToolbarMenuControls(columns);
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
/**
|
|
1328
|
+
* @description set list of columns to display in table.
|
|
1329
|
+
* @param columns columns array from user input with configurations.
|
|
1330
|
+
*/
|
|
1331
|
+
setColumnsList(columns) {
|
|
1332
|
+
this.columnsList = [];
|
|
1333
|
+
this.displayedColumns = ['select', 'edit', 'popup', 'delete', 'freeze', 'hide', 'pin'];
|
|
1334
|
+
let columnsArray = [];
|
|
1335
|
+
columns.forEach((col) => {
|
|
1336
|
+
if (typeof col?.header == 'string') {
|
|
1337
|
+
this.columnsList.push(col?.header);
|
|
1338
|
+
this.displayedColumns.push(col?.field);
|
|
1339
|
+
columnsArray.push({ filter: true, name: col?.field, show: !col.hide });
|
|
1340
|
+
}
|
|
1341
|
+
});
|
|
1342
|
+
// Preserve the current state of action columns before resetting
|
|
1343
|
+
const currentActionColumns = this.dynamicDisplayedColumns.filter(dc => ['select', 'edit', 'popup', 'delete', 'freeze', 'hide', 'pin'].includes(dc.name));
|
|
1344
|
+
// Create new action columns array, preserving existing states
|
|
1345
|
+
const newActionColumns = [
|
|
1346
|
+
{ filter: false, name: 'select', show: false },
|
|
1347
|
+
{ filter: false, name: 'edit', show: false },
|
|
1348
|
+
{ filter: false, name: 'popup', show: false },
|
|
1349
|
+
{ filter: false, name: 'delete', show: false },
|
|
1350
|
+
{ filter: false, name: 'freeze', show: false },
|
|
1351
|
+
{ filter: false, name: 'hide', show: false },
|
|
1352
|
+
{ filter: false, name: 'pin', show: false },
|
|
1353
|
+
].map(actionCol => {
|
|
1354
|
+
const existing = currentActionColumns.find(c => c.name === actionCol.name);
|
|
1355
|
+
return existing ? { ...existing } : actionCol;
|
|
1356
|
+
});
|
|
1357
|
+
this.dynamicDisplayedColumns = columnsArray.concat(newActionColumns);
|
|
1358
|
+
// After updating columns, ensure sizes match the top header (if pinning enabled)
|
|
1359
|
+
if (this.enableRowPinning) {
|
|
1360
|
+
setTimeout(() => this.syncColumnSizesFromTop(), 80);
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
/**
|
|
1364
|
+
* @description Take boolean value and name column and update its visibility status in table.
|
|
1365
|
+
* @param name name of the column to set visibility.
|
|
1366
|
+
* @param value boolean value to set visibility of the column.
|
|
1367
|
+
*/
|
|
1368
|
+
showHideColumn(name, value) {
|
|
1369
|
+
const column = this.dynamicDisplayedColumns.filter((a) => a.name == name)[0];
|
|
1370
|
+
if (column) {
|
|
1371
|
+
column.show = value;
|
|
1372
|
+
if (this.enableRowPinning) {
|
|
1373
|
+
this.syncColumnSizesFromTop();
|
|
1374
|
+
}
|
|
1375
|
+
}
|
|
1376
|
+
if (this.columnFilter) {
|
|
1377
|
+
this.setColumnFilter(true);
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
/**
|
|
1381
|
+
* @description Toggle hide state for a specific row
|
|
1382
|
+
* @param index The row index to hide/unhide
|
|
1383
|
+
*/
|
|
1384
|
+
toggleRowHide(index) {
|
|
1385
|
+
const hiddenIndex = this.hiddenRowIndices.indexOf(index);
|
|
1386
|
+
if (hiddenIndex > -1) {
|
|
1387
|
+
// Unhide the row
|
|
1388
|
+
this.hiddenRowIndices.splice(hiddenIndex, 1);
|
|
1389
|
+
}
|
|
1390
|
+
else {
|
|
1391
|
+
// Hide the row
|
|
1392
|
+
this.hiddenRowIndices.push(index);
|
|
1393
|
+
}
|
|
1394
|
+
// Trigger change detection
|
|
1395
|
+
this.hiddenRowIndices = [...this.hiddenRowIndices];
|
|
1396
|
+
}
|
|
1397
|
+
/**
|
|
1398
|
+
* @description Check if a row index is in the hidden rows list or matches the filter function.
|
|
1399
|
+
* @param index The row index to check
|
|
1400
|
+
* @returns True if the row is hidden
|
|
1401
|
+
*/
|
|
1402
|
+
isRowHidden(index) {
|
|
1403
|
+
// Check explicit hidden indices
|
|
1404
|
+
if (this.hiddenRowIndices.includes(index)) {
|
|
1405
|
+
return true;
|
|
1406
|
+
}
|
|
1407
|
+
// Check filter function if provided
|
|
1408
|
+
if (this.rowHidingFilterFn && this.dataSource?.data?.[index]) {
|
|
1409
|
+
return this.rowHidingFilterFn(this.dataSource.data[index], index);
|
|
1410
|
+
}
|
|
1411
|
+
return false;
|
|
1412
|
+
}
|
|
1413
|
+
/**
|
|
1414
|
+
* @description Unhide all hidden rows
|
|
1415
|
+
*/
|
|
1416
|
+
unhideAllRows() {
|
|
1417
|
+
this.hiddenRowIndices = [];
|
|
1418
|
+
}
|
|
1419
|
+
/**
|
|
1420
|
+
* @description Open row pin menu
|
|
1421
|
+
* @param event Mouse event
|
|
1422
|
+
* @param row The row to pin
|
|
1423
|
+
*/
|
|
1424
|
+
openRowPinMenu(event, row) {
|
|
1425
|
+
event.stopPropagation();
|
|
1426
|
+
this.rowPinMenuPosition = {
|
|
1427
|
+
x: event.clientX + 'px',
|
|
1428
|
+
y: event.clientY + 'px'
|
|
1429
|
+
};
|
|
1430
|
+
this.rowPinMenuRow = row;
|
|
1431
|
+
}
|
|
1432
|
+
/**
|
|
1433
|
+
* @description Close row pin menu
|
|
1434
|
+
*/
|
|
1435
|
+
closeRowPinMenu() {
|
|
1436
|
+
this.rowPinMenuRow = null;
|
|
1437
|
+
}
|
|
1438
|
+
/**
|
|
1439
|
+
* @description Pin row to top or bottom
|
|
1440
|
+
* @param row The row to pin
|
|
1441
|
+
* @param position 'top' or 'bottom'
|
|
1442
|
+
*/
|
|
1443
|
+
pinRow(row, position) {
|
|
1444
|
+
console.log('pinRow called:', { row, position, enableRowPinning: this.enableRowPinning });
|
|
1445
|
+
// Remove from other position if exists
|
|
1446
|
+
this.unpinRow(row);
|
|
1447
|
+
// Mark the row with pinning metadata
|
|
1448
|
+
row._pinnedPosition = position;
|
|
1449
|
+
// Add to the selected position
|
|
1450
|
+
if (position === 'top') {
|
|
1451
|
+
if (!this.pinnedTopRows.includes(row)) {
|
|
1452
|
+
this.pinnedTopRows.push(row);
|
|
1453
|
+
}
|
|
1454
|
+
this.pinnedTopDataSource = new MatTableDataSource(this.pinnedTopRows);
|
|
1455
|
+
}
|
|
1456
|
+
else {
|
|
1457
|
+
if (!this.pinnedBottomRows.includes(row)) {
|
|
1458
|
+
this.pinnedBottomRows.push(row);
|
|
1459
|
+
}
|
|
1460
|
+
this.pinnedBtmDataSource = new MatTableDataSource(this.pinnedBottomRows);
|
|
1461
|
+
}
|
|
1462
|
+
console.log('After pinning:', {
|
|
1463
|
+
pinnedTopRows: this.pinnedTopRows,
|
|
1464
|
+
pinnedBottomRows: this.pinnedBottomRows,
|
|
1465
|
+
topLength: this.pinnedTopRows.length,
|
|
1466
|
+
bottomLength: this.pinnedBottomRows.length
|
|
1467
|
+
});
|
|
1468
|
+
this.rowPinningChange.emit({ row, position });
|
|
1469
|
+
this.closeRowPinMenu();
|
|
1470
|
+
this.updateDataSourceForPinning();
|
|
1471
|
+
}
|
|
1472
|
+
/**
|
|
1473
|
+
* @description Unpin row from any position
|
|
1474
|
+
* @param row The row to unpin
|
|
1475
|
+
*/
|
|
1476
|
+
unpinRow(row) {
|
|
1477
|
+
const topIndex = this.pinnedTopRows.indexOf(row);
|
|
1478
|
+
if (topIndex > -1) {
|
|
1479
|
+
this.pinnedTopRows.splice(topIndex, 1);
|
|
1480
|
+
this.pinnedTopDataSource = new MatTableDataSource(this.pinnedTopRows);
|
|
1481
|
+
}
|
|
1482
|
+
const bottomIndex = this.pinnedBottomRows.indexOf(row);
|
|
1483
|
+
if (bottomIndex > -1) {
|
|
1484
|
+
this.pinnedBottomRows.splice(bottomIndex, 1);
|
|
1485
|
+
this.pinnedBtmDataSource = new MatTableDataSource(this.pinnedBottomRows);
|
|
1486
|
+
}
|
|
1487
|
+
// Clear pinning metadata
|
|
1488
|
+
delete row._pinnedPosition;
|
|
1489
|
+
// Update the data source to trigger re-render
|
|
1490
|
+
this.updateDataSourceForPinning();
|
|
1491
|
+
this.rowPinningChange.emit({ row, position: null });
|
|
1492
|
+
this.closeRowPinMenu();
|
|
1493
|
+
}
|
|
1494
|
+
/**
|
|
1495
|
+
* @description Check if a row is pinned
|
|
1496
|
+
* @param row The row to check
|
|
1497
|
+
* @returns true if pinned
|
|
1498
|
+
*/
|
|
1499
|
+
isRowPinned(row) {
|
|
1500
|
+
return this.pinnedTopRows.includes(row) || this.pinnedBottomRows.includes(row);
|
|
1501
|
+
}
|
|
1502
|
+
/**
|
|
1503
|
+
* @description Get row pin position
|
|
1504
|
+
* @param row The row to check
|
|
1505
|
+
* @returns 'top', 'bottom', or null
|
|
1506
|
+
*/
|
|
1507
|
+
getRowPinPosition(row) {
|
|
1508
|
+
if (this.pinnedTopRows.includes(row))
|
|
1509
|
+
return 'top';
|
|
1510
|
+
if (this.pinnedBottomRows.includes(row))
|
|
1511
|
+
return 'bottom';
|
|
1512
|
+
return null;
|
|
1513
|
+
}
|
|
1514
|
+
/**
|
|
1515
|
+
* @description Get rows for main data section (excluding pinned rows)
|
|
1516
|
+
* @returns Array of non-pinned rows
|
|
1517
|
+
*/
|
|
1518
|
+
getUnpinnedRows() {
|
|
1519
|
+
if (!this.dataSource?.data)
|
|
1520
|
+
return [];
|
|
1521
|
+
return this.dataSource.data.filter(row => !this.pinnedTopRows.includes(row) && !this.pinnedBottomRows.includes(row));
|
|
1522
|
+
}
|
|
1523
|
+
/**
|
|
1524
|
+
* @description Get combined data source with pinned rows
|
|
1525
|
+
*/
|
|
1526
|
+
getCombinedDataSource() {
|
|
1527
|
+
if (!this.enableRowPinning || !this.dataSource?.data) {
|
|
1528
|
+
return this.dataSource?.data || [];
|
|
1529
|
+
}
|
|
1530
|
+
// Combine: pinnedTop + regular + pinnedBottom
|
|
1531
|
+
return [
|
|
1532
|
+
...this.pinnedTopRows,
|
|
1533
|
+
...this.dataSource.data.filter(row => !this.isRowPinned(row)),
|
|
1534
|
+
...this.pinnedBottomRows
|
|
1535
|
+
];
|
|
1536
|
+
}
|
|
1537
|
+
/**
|
|
1538
|
+
* @description Initialize pinned rows based on function
|
|
1539
|
+
*/
|
|
1540
|
+
initializePinnedRows() {
|
|
1541
|
+
if (!this.rowPinningFn || !this.dataSource?.data)
|
|
1542
|
+
return;
|
|
1543
|
+
this.pinnedTopRows = [];
|
|
1544
|
+
this.pinnedBottomRows = [];
|
|
1545
|
+
this.dataSource.data.forEach((row, index) => {
|
|
1546
|
+
const position = this.rowPinningFn(row, index);
|
|
1547
|
+
if (position === 'top') {
|
|
1548
|
+
row._pinnedPosition = 'top';
|
|
1549
|
+
this.pinnedTopRows.push(row);
|
|
1550
|
+
}
|
|
1551
|
+
else if (position === 'bottom') {
|
|
1552
|
+
row._pinnedPosition = 'bottom';
|
|
1553
|
+
this.pinnedBottomRows.push(row);
|
|
1554
|
+
}
|
|
1555
|
+
});
|
|
1556
|
+
this.cdr.detectChanges();
|
|
1557
|
+
}
|
|
1558
|
+
/**
|
|
1559
|
+
* @description Update data source and recalculate pinned row offsets
|
|
1560
|
+
*/
|
|
1561
|
+
updateDataSourceForPinning() {
|
|
1562
|
+
// Trigger change detection
|
|
1563
|
+
this.cdr.detectChanges();
|
|
1564
|
+
// Force table to re-render rows
|
|
1565
|
+
if (this.table) {
|
|
1566
|
+
this.table.renderRows();
|
|
1567
|
+
}
|
|
1568
|
+
// Update offsets for sticky positioning
|
|
1569
|
+
this.updatePinnedRowOffsets();
|
|
1570
|
+
}
|
|
1571
|
+
/**
|
|
1572
|
+
* @description This method will position the selection column to first and also update its visibility.
|
|
1573
|
+
* @param value value used to set visibility of the selection column.
|
|
1574
|
+
*/
|
|
1575
|
+
updateSelectionColumnVisibility(value) {
|
|
1576
|
+
let columnName = 'select';
|
|
1577
|
+
let column = this.dynamicDisplayedColumns.filter((a) => a.name == columnName)[0];
|
|
1578
|
+
let index = this.dynamicDisplayedColumns.findIndex((column) => column.name == columnName);
|
|
1579
|
+
if (index > -1) {
|
|
1580
|
+
this.dynamicDisplayedColumns.splice(index, 1);
|
|
1581
|
+
this.dynamicDisplayedColumns.unshift(column);
|
|
1582
|
+
this.dynamicDisplayedColumns.filter((column) => column.name == columnName)[0].show = value;
|
|
1583
|
+
}
|
|
1584
|
+
}
|
|
1585
|
+
/**
|
|
1586
|
+
* @description This method is used to update the position of column in columns array according to its dropped position.
|
|
1587
|
+
* @param event CdkDragDrop used to update column position in columns array.
|
|
1588
|
+
*/
|
|
1589
|
+
onDrop(event) {
|
|
1590
|
+
if (this.dndColumns) {
|
|
1591
|
+
let adjustedValue = 0;
|
|
1592
|
+
if (this.dynamicDisplayedColumns[0].name == 'select' &&
|
|
1593
|
+
this.dynamicDisplayedColumns[0].show == false) {
|
|
1594
|
+
adjustedValue = 1;
|
|
1595
|
+
}
|
|
1596
|
+
moveItemInArray(this.dynamicDisplayedColumns, event.previousIndex + adjustedValue, event.currentIndex + adjustedValue);
|
|
1597
|
+
if (this.enableRowPinning) {
|
|
1598
|
+
setTimeout(() => this.syncColumnSizesFromTop(), 80);
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1601
|
+
}
|
|
1602
|
+
/**
|
|
1603
|
+
* @description This method create filter predicate function which will set search value to table filters
|
|
1604
|
+
* for both global and individual colum filtering.
|
|
1605
|
+
* @returns returns boolean value to filter rows in table.
|
|
1606
|
+
*/
|
|
1607
|
+
createFilter() {
|
|
1608
|
+
const tableFilterPredicate = (data, filter) => {
|
|
1609
|
+
let result = true;
|
|
1610
|
+
// search all column fields
|
|
1611
|
+
if (this.globalFilter) {
|
|
1612
|
+
let expression = '';
|
|
1613
|
+
let keys = Object.keys(data);
|
|
1614
|
+
keys.forEach((key) => {
|
|
1615
|
+
expression =
|
|
1616
|
+
expression +
|
|
1617
|
+
`data.${key}.toString().trim().toLowerCase().indexOf(this.globalFilter.toLowerCase()) !== -1 ||`;
|
|
1618
|
+
});
|
|
1619
|
+
if (expression.charAt(expression.length - 2) +
|
|
1620
|
+
expression.charAt(expression.length - 1) ==
|
|
1621
|
+
'||') {
|
|
1622
|
+
expression = expression.substring(0, expression.length - 2);
|
|
1623
|
+
}
|
|
1624
|
+
result = eval(expression);
|
|
1625
|
+
}
|
|
1626
|
+
if (!result) {
|
|
1627
|
+
return false;
|
|
1628
|
+
}
|
|
1629
|
+
let searchString = JSON.parse(filter);
|
|
1630
|
+
//search single column field
|
|
1631
|
+
if (this.individualFilter) {
|
|
1632
|
+
return (data[this.individualFilter]
|
|
1633
|
+
.toString()
|
|
1634
|
+
.trim()
|
|
1635
|
+
.toLowerCase()
|
|
1636
|
+
.indexOf(searchString[this.individualFilter].toString().toLowerCase()) !== -1);
|
|
1637
|
+
}
|
|
1638
|
+
return true;
|
|
1639
|
+
};
|
|
1640
|
+
return tableFilterPredicate;
|
|
1641
|
+
}
|
|
1642
|
+
/**
|
|
1643
|
+
* @description assigns the search value to mat table data source to apply the filter.
|
|
1644
|
+
* @param searchValue value to be searched from table rows.
|
|
1645
|
+
*/
|
|
1646
|
+
applyGlobalFilter(searchValue) {
|
|
1647
|
+
this.globalFilter = searchValue;
|
|
1648
|
+
let columns = {};
|
|
1649
|
+
this.columnsArray.forEach((column) => {
|
|
1650
|
+
if (column.field)
|
|
1651
|
+
columns[column.field] = searchValue;
|
|
1652
|
+
});
|
|
1653
|
+
this.dataSource.filter = JSON.stringify(columns);
|
|
1654
|
+
}
|
|
1655
|
+
/**
|
|
1656
|
+
* @description This method is used to apply column based filtering
|
|
1657
|
+
* @param searchValue value to be searched from table rows.
|
|
1658
|
+
* @param column filter will be applied based on this column field.
|
|
1659
|
+
*/
|
|
1660
|
+
applyColumnFilter(searchValue, column) {
|
|
1661
|
+
this.individualFilter = column.field;
|
|
1662
|
+
this.filterValues[column.field] = searchValue[column.field];
|
|
1663
|
+
this.dataSource.filter = JSON.stringify(this.filterValues);
|
|
1664
|
+
if (this.enableRowPinning) {
|
|
1665
|
+
setTimeout(() => this.syncColumnSizesFromTop(), 80);
|
|
1666
|
+
}
|
|
1667
|
+
}
|
|
1668
|
+
/**
|
|
1669
|
+
* @description This method will take row and its index enable inline editing tools on that row.
|
|
1670
|
+
* @param row row on which user wants to do edit.
|
|
1671
|
+
* @param index index of the row where inline editing will be enabled.
|
|
1672
|
+
*/
|
|
1673
|
+
enableInlineEditing(row, index) {
|
|
1674
|
+
// Check if another row is currently in edit mode
|
|
1675
|
+
const currentEditIndex = this.tableData.findIndex((r) => r.editable === true);
|
|
1676
|
+
if (currentEditIndex !== -1 && currentEditIndex !== index) {
|
|
1677
|
+
// Disable the previous row's edit mode
|
|
1678
|
+
this.tableData[currentEditIndex]['editable'] = false;
|
|
1679
|
+
// Clear the temporary data for the previous row
|
|
1680
|
+
this.rowDataTemp['e' + currentEditIndex] = {};
|
|
1681
|
+
// Restore original sizes when switching rows
|
|
1682
|
+
if (this.enableRowPinning && this.originalSizesBeforeEdit) {
|
|
1683
|
+
this.restoreOriginalSizes();
|
|
1684
|
+
}
|
|
1685
|
+
}
|
|
1686
|
+
const rowData = {};
|
|
1687
|
+
rowData['e' + index] = { ...row };
|
|
1688
|
+
this.rowDataTemp = rowData;
|
|
1689
|
+
setTimeout(() => {
|
|
1690
|
+
const wasEditable = this.tableData[index]['editable'];
|
|
1691
|
+
this.tableData[index]['editable'] = !this.tableData[index]['editable'];
|
|
1692
|
+
// If row is now in edit mode, sync sizes from this edited row
|
|
1693
|
+
if (this.tableData[index]['editable'] && this.enableRowPinning) {
|
|
1694
|
+
// Wait for DOM to update with edit controls
|
|
1695
|
+
setTimeout(() => {
|
|
1696
|
+
this.syncColumnSizesFromEditedRow(index);
|
|
1697
|
+
}, 100);
|
|
1698
|
+
}
|
|
1699
|
+
else if (!this.tableData[index]['editable'] && this.enableRowPinning) {
|
|
1700
|
+
// Row was disabled, restore original sizes
|
|
1701
|
+
this.restoreOriginalSizes();
|
|
1702
|
+
}
|
|
1703
|
+
}, 0);
|
|
1704
|
+
}
|
|
1705
|
+
/**
|
|
1706
|
+
* @description This method will create and return data to inline editing template.
|
|
1707
|
+
* @param row row on which user wants to do edit.
|
|
1708
|
+
* @param index index of the row where inline editing will be enabled.
|
|
1709
|
+
* @param column current column of the table.
|
|
1710
|
+
*/
|
|
1711
|
+
getInlineEditingData(row, index, column) {
|
|
1712
|
+
this.inlineEditingTemplateRefData = {
|
|
1713
|
+
row: { ...row },
|
|
1714
|
+
column: { ...column },
|
|
1715
|
+
index: index,
|
|
1716
|
+
updateFunc: this.updateInlineTemplateData,
|
|
1717
|
+
};
|
|
1718
|
+
return this.inlineEditingTemplateRefData;
|
|
1719
|
+
}
|
|
1720
|
+
/**
|
|
1721
|
+
* @description This method set data for in-cell editing.
|
|
1722
|
+
* @param row row on which user wants to do edit.
|
|
1723
|
+
* @param index index of the row where inline editing will be enabled.
|
|
1724
|
+
*/
|
|
1725
|
+
setCellData(row, index) {
|
|
1726
|
+
// If there's already an inline edit in progress, cancel it first
|
|
1727
|
+
if (this.currentRowIndex !== -1 && this.currentRowIndex !== index) {
|
|
1728
|
+
// Find and cancel the previous inline editing row
|
|
1729
|
+
const previousEditableRow = this.tableData.find((r, i) => i === this.currentRowIndex && r.editable);
|
|
1730
|
+
if (previousEditableRow) {
|
|
1731
|
+
previousEditableRow['editable'] = false;
|
|
1732
|
+
}
|
|
1733
|
+
// Clear previous cell editing states
|
|
1734
|
+
Object.keys(this.cellEditing).forEach(key => {
|
|
1735
|
+
if (key.startsWith(this.currentRowIndex + '_')) {
|
|
1736
|
+
delete this.cellEditing[key];
|
|
1737
|
+
}
|
|
1738
|
+
});
|
|
1739
|
+
this.rowDataTemp['e' + this.currentRowIndex] = {};
|
|
1740
|
+
// Restore sizes when switching from previous cell editing
|
|
1741
|
+
if (this.enableRowPinning) {
|
|
1742
|
+
this.restoreOriginalSizes();
|
|
1743
|
+
}
|
|
1744
|
+
}
|
|
1745
|
+
this.currentRow = { ...row };
|
|
1746
|
+
this.currentRowIndex = index;
|
|
1747
|
+
this.rowDataTemp['e' + index] = { ...row };
|
|
1748
|
+
// Sync column sizes from the edited row when cell editing starts
|
|
1749
|
+
if (this.enableRowPinning) {
|
|
1750
|
+
setTimeout(() => {
|
|
1751
|
+
this.syncColumnSizesFromEditedRow(index);
|
|
1752
|
+
}, 50);
|
|
1753
|
+
}
|
|
1754
|
+
}
|
|
1755
|
+
/**
|
|
1756
|
+
* @description This will restore the data and cencel the inline editing.
|
|
1757
|
+
* @param row row on which user wants to do edit.
|
|
1758
|
+
* @param index index of the row where inline editing will be enabled.
|
|
1759
|
+
*/
|
|
1760
|
+
cancelInlineEditing(row, index) {
|
|
1761
|
+
this.tableData.filter((a, i) => i == index)[0]['editable'] =
|
|
1762
|
+
!this.tableData.filter((a, i) => i == index)[0]['editable'];
|
|
1763
|
+
this.dataSource = new MatTableDataSource(this.tableData);
|
|
1764
|
+
this.rowDataTemp['e' + index] = {};
|
|
1765
|
+
this.service.selectedRow.next(undefined);
|
|
1766
|
+
// Restore original sizes after canceling edit mode
|
|
1767
|
+
if (this.enableRowPinning) {
|
|
1768
|
+
this.restoreOriginalSizes();
|
|
1769
|
+
}
|
|
1770
|
+
}
|
|
1771
|
+
/**
|
|
1772
|
+
* @description This method will save and update the inline editing data and emit the update row and index.
|
|
1773
|
+
* @param row row on which user wants to do edit.
|
|
1774
|
+
* @param index index of the row where inline editing will be enabled.
|
|
1775
|
+
*/
|
|
1776
|
+
saveInlineEditing(row, index) {
|
|
1777
|
+
if (!this.inlineEditingTemplateRef) {
|
|
1778
|
+
this.tableData[index] = { ...this.rowDataTemp['e' + index] };
|
|
1779
|
+
row = { ...this.rowDataTemp['e' + index] };
|
|
1780
|
+
}
|
|
1781
|
+
else {
|
|
1782
|
+
let changedData = this.service.selectedRow.value;
|
|
1783
|
+
if (changedData) {
|
|
1784
|
+
this.tableData[index] = { ...changedData };
|
|
1785
|
+
}
|
|
1786
|
+
}
|
|
1787
|
+
this.dataSource = new MatTableDataSource(this.tableData);
|
|
1788
|
+
this.rowDataTemp['e' + index] = {};
|
|
1789
|
+
let data = {
|
|
1790
|
+
row: row,
|
|
1791
|
+
index: index,
|
|
1792
|
+
};
|
|
1793
|
+
this.inlineChange.emit(data);
|
|
1794
|
+
this.tableData[index]['editable'] = false;
|
|
1795
|
+
// Restore original sizes after saving edit mode
|
|
1796
|
+
if (this.enableRowPinning) {
|
|
1797
|
+
this.restoreOriginalSizes();
|
|
1798
|
+
}
|
|
1799
|
+
}
|
|
1800
|
+
/**
|
|
1801
|
+
* @description This method will save and update the cell editing data and emit the update row and index.
|
|
1802
|
+
*/
|
|
1803
|
+
saveCellEditing() {
|
|
1804
|
+
this.cellEditing = {};
|
|
1805
|
+
let index = this.currentRowIndex;
|
|
1806
|
+
if (index > -1) {
|
|
1807
|
+
if (this.cellEditingTemplateRef) {
|
|
1808
|
+
let changedData = this.service.selectedRow.value;
|
|
1809
|
+
if (changedData) {
|
|
1810
|
+
this.tableData[index] = { ...changedData };
|
|
1811
|
+
}
|
|
1812
|
+
}
|
|
1813
|
+
else {
|
|
1814
|
+
this.tableData[index] = { ...this.rowDataTemp['e' + index] };
|
|
1815
|
+
}
|
|
1816
|
+
this.dataSource = new MatTableDataSource(this.tableData);
|
|
1817
|
+
this.rowDataTemp['e' + index] = {};
|
|
1818
|
+
let data = {
|
|
1819
|
+
row: { ...this.tableData[index] },
|
|
1820
|
+
index: index,
|
|
1821
|
+
};
|
|
1822
|
+
this.currentRowIndex = -1;
|
|
1823
|
+
this.cellChange.emit(data);
|
|
1824
|
+
// Restore original sizes after saving cell edits
|
|
1825
|
+
if (this.enableRowPinning) {
|
|
1826
|
+
this.restoreOriginalSizes();
|
|
1827
|
+
}
|
|
1828
|
+
}
|
|
1829
|
+
}
|
|
1830
|
+
/**
|
|
1831
|
+
* @description This method will delete the row from the given index and emit the deleted row and index.
|
|
1832
|
+
* @param row row to be deleted.
|
|
1833
|
+
* @param index index of the row to be deleted.
|
|
1834
|
+
*/
|
|
1835
|
+
deleteRow(row, index) {
|
|
1836
|
+
// this.tableData.splice(index, 1);
|
|
1837
|
+
// this.dataSource = new MatTableDataSource(this.tableData);
|
|
1838
|
+
// this.dataSource.paginator = this.paginator;
|
|
1839
|
+
// this.dataSource.sort = this.sort;
|
|
1840
|
+
this.rowDeleted.emit({ removedRow: row, fromIndex: index });
|
|
1841
|
+
}
|
|
1842
|
+
/**
|
|
1843
|
+
* @description This method will expand or collapse the row and emit expand event.
|
|
1844
|
+
* @param row row to be expanded or collapsed.
|
|
1845
|
+
* @param expand value used to expand or collapse the row.
|
|
1846
|
+
* @param index index of the row.
|
|
1847
|
+
*/
|
|
1848
|
+
expandRow(row, expand, index) {
|
|
1849
|
+
if (this.expandRows) {
|
|
1850
|
+
this.expansionChange.emit({ data: row, expanded: expand, index: index });
|
|
1851
|
+
this.expandedElement = this.expandedElement === row ? null : row;
|
|
1852
|
+
}
|
|
1853
|
+
}
|
|
1854
|
+
/**
|
|
1855
|
+
* @description This method is used to set data for popup component and open editing dialog.
|
|
1856
|
+
* @param row row which used want to edit.
|
|
1857
|
+
*/
|
|
1858
|
+
openEditingDialog(row) {
|
|
1859
|
+
const dialogConfig = new MatDialogConfig();
|
|
1860
|
+
dialogConfig.disableClose = true;
|
|
1861
|
+
dialogConfig.width = '40%';
|
|
1862
|
+
dialogConfig.height = '70%';
|
|
1863
|
+
dialogConfig.maxWidth = '100%';
|
|
1864
|
+
let rowData = { ...row };
|
|
1865
|
+
dialogConfig.data = {
|
|
1866
|
+
row: rowData,
|
|
1867
|
+
columns: [...this.columnsArray],
|
|
1868
|
+
templateRef: this.popupEditingTemplateRef,
|
|
1869
|
+
};
|
|
1870
|
+
this.dialog
|
|
1871
|
+
.open(EditingComponent, dialogConfig)
|
|
1872
|
+
.afterClosed()
|
|
1873
|
+
.subscribe((data) => {
|
|
1874
|
+
let index = this.tableData.indexOf(row);
|
|
1875
|
+
if (data && index > -1) {
|
|
1876
|
+
this.tableData[index] = data;
|
|
1877
|
+
this.dataSource = new MatTableDataSource(this.tableData);
|
|
1878
|
+
let dataChange = {
|
|
1879
|
+
row: data,
|
|
1880
|
+
index: index,
|
|
1881
|
+
};
|
|
1882
|
+
this.popupChange.emit(dataChange);
|
|
1883
|
+
if (this.enableRowPinning) {
|
|
1884
|
+
setTimeout(() => this.syncColumnSizesFromTop(), 80);
|
|
1885
|
+
}
|
|
1886
|
+
}
|
|
1887
|
+
});
|
|
1888
|
+
}
|
|
1889
|
+
/**
|
|
1890
|
+
* @description This method is used to open cell popup editing dialog for a single cell.
|
|
1891
|
+
* @param row row which contains the cell to edit.
|
|
1892
|
+
* @param column column definition of the cell to edit.
|
|
1893
|
+
* @param rowIndex index of the row.
|
|
1894
|
+
*/
|
|
1895
|
+
openCellPopupDialog(row, column, rowIndex) {
|
|
1896
|
+
const dialogConfig = new MatDialogConfig();
|
|
1897
|
+
dialogConfig.disableClose = true;
|
|
1898
|
+
dialogConfig.width = '400px';
|
|
1899
|
+
dialogConfig.height = 'auto';
|
|
1900
|
+
dialogConfig.maxWidth = '100%';
|
|
1901
|
+
dialogConfig.data = {
|
|
1902
|
+
row: { ...row },
|
|
1903
|
+
column: column,
|
|
1904
|
+
rowIndex: rowIndex,
|
|
1905
|
+
isCellEdit: true,
|
|
1906
|
+
templateRef: this.cellPopupEditingTemplateRef,
|
|
1907
|
+
};
|
|
1908
|
+
this.dialog
|
|
1909
|
+
.open(EditingComponent, dialogConfig)
|
|
1910
|
+
.afterClosed()
|
|
1911
|
+
.subscribe((data) => {
|
|
1912
|
+
if (data && data.field && rowIndex > -1) {
|
|
1913
|
+
this.tableData[rowIndex][data.field] = data.value;
|
|
1914
|
+
this.dataSource = new MatTableDataSource(this.tableData);
|
|
1915
|
+
let dataChange = {
|
|
1916
|
+
row: { ...this.tableData[rowIndex] },
|
|
1917
|
+
index: rowIndex,
|
|
1918
|
+
};
|
|
1919
|
+
this.cellChange.emit(dataChange);
|
|
1920
|
+
if (this.enableRowPinning) {
|
|
1921
|
+
setTimeout(() => this.syncColumnSizesFromTop(), 80);
|
|
1922
|
+
}
|
|
1923
|
+
}
|
|
1924
|
+
});
|
|
1925
|
+
}
|
|
1926
|
+
/**
|
|
1927
|
+
* @description used to check whether all rows are selected.
|
|
1928
|
+
*/
|
|
1929
|
+
isAllSelected() {
|
|
1930
|
+
const numSelected = this.selection.selected.length;
|
|
1931
|
+
const numRows = this.dataSource.data.length;
|
|
1932
|
+
return numSelected === numRows;
|
|
1933
|
+
}
|
|
1934
|
+
/**
|
|
1935
|
+
* @description this method is used to toggle the all and no rows selection.
|
|
1936
|
+
*/
|
|
1937
|
+
toggleAllRows() {
|
|
1938
|
+
if (this.isAllSelected()) {
|
|
1939
|
+
this.selection.clear();
|
|
1940
|
+
return;
|
|
1941
|
+
}
|
|
1942
|
+
this.selection.select(...this.dataSource.data);
|
|
1943
|
+
}
|
|
1944
|
+
/**
|
|
1945
|
+
* @description This method is used return aria-label for selection column checkboxs.
|
|
1946
|
+
* @param row row from table.
|
|
1947
|
+
* @returns labels for selection column checkboxs.
|
|
1948
|
+
*/
|
|
1949
|
+
checkboxLabel(row) {
|
|
1950
|
+
if (!row) {
|
|
1951
|
+
return `${this.isAllSelected() ? 'deselect' : 'select'} all`;
|
|
1952
|
+
}
|
|
1953
|
+
return `${this.selection.isSelected(row) ? 'deselect' : 'select'} row ${row.position + 1}`;
|
|
1954
|
+
}
|
|
1955
|
+
/**
|
|
1956
|
+
* @description create form control for columns for hiding and and pinning purpose
|
|
1957
|
+
* @param columns list of columns to be displayed
|
|
1958
|
+
*/
|
|
1959
|
+
setToolbarMenuControls(columns) {
|
|
1960
|
+
if (columns.length > 0 && this.showToolbar) {
|
|
1961
|
+
const group = this.formBuilder.group({});
|
|
1962
|
+
columns.forEach((column) => {
|
|
1963
|
+
const control = this.formBuilder.control(true);
|
|
1964
|
+
group.addControl(column.field, control);
|
|
1965
|
+
});
|
|
1966
|
+
this.hideShowMenuGroup = group;
|
|
1967
|
+
}
|
|
1968
|
+
}
|
|
1969
|
+
/**
|
|
1970
|
+
* @param column current column
|
|
1971
|
+
* @param event mouse event used to set the menu position
|
|
1972
|
+
*/
|
|
1973
|
+
openPinnablePropertyMenu(column, event) {
|
|
1974
|
+
this.menuX = event.clientX;
|
|
1975
|
+
this.menuY = event.clientY;
|
|
1976
|
+
let options = [
|
|
1977
|
+
{
|
|
1978
|
+
label: 'Pin Left',
|
|
1979
|
+
value: 'left',
|
|
1980
|
+
selected: false,
|
|
1981
|
+
field: column.field,
|
|
1982
|
+
},
|
|
1983
|
+
{
|
|
1984
|
+
label: 'Pin Right',
|
|
1985
|
+
value: 'right',
|
|
1986
|
+
selected: false,
|
|
1987
|
+
field: column.field,
|
|
1988
|
+
},
|
|
1989
|
+
{ label: 'No Pin', value: null, selected: false, field: column.field },
|
|
1990
|
+
];
|
|
1991
|
+
if (column.pinned && column.pinned !== null) {
|
|
1992
|
+
options.forEach((opt) => {
|
|
1993
|
+
if (opt.value === column.pinned) {
|
|
1994
|
+
opt.selected = true;
|
|
1995
|
+
}
|
|
1996
|
+
});
|
|
1997
|
+
}
|
|
1998
|
+
else if (column.pinned == null || column.pinned == 'null') {
|
|
1999
|
+
options[2].selected = true;
|
|
2000
|
+
}
|
|
2001
|
+
this.columnPinningOptions = options;
|
|
2002
|
+
this.columnMenuTrigger.openMenu();
|
|
2003
|
+
}
|
|
2004
|
+
/**
|
|
2005
|
+
* @description This method is used to reset menu checks when required.
|
|
2006
|
+
*/
|
|
2007
|
+
resetMenuChecks() {
|
|
2008
|
+
this.hideShowMenuCtrl = false;
|
|
2009
|
+
this.showHideColumnsArray = [];
|
|
2010
|
+
this.columnPinMenuCtrl = false;
|
|
2011
|
+
this.columnPinningOptions = [];
|
|
2012
|
+
}
|
|
2013
|
+
/**
|
|
2014
|
+
* @description This method is used to filter columns for menus like pinning or hide show menu.
|
|
2015
|
+
* @param value search value to filter colunms
|
|
2016
|
+
*/
|
|
2017
|
+
filterColumns(value) {
|
|
2018
|
+
if (value !== '') {
|
|
2019
|
+
this.showHideColumnsArray = this.columnsArray.filter((col) => {
|
|
2020
|
+
return col.header.toLowerCase().includes(value.toLowerCase());
|
|
2021
|
+
});
|
|
2022
|
+
}
|
|
2023
|
+
else {
|
|
2024
|
+
this.showHideColumnsArray = this.columnsArray;
|
|
2025
|
+
}
|
|
2026
|
+
}
|
|
2027
|
+
/**
|
|
2028
|
+
* @description This method is used to open hide show column menu.
|
|
2029
|
+
* @param columns columns array to display in hide show menu.
|
|
2030
|
+
*/
|
|
2031
|
+
openHideShowMenu(columns) {
|
|
2032
|
+
this.showHideColumnsArray = [...columns];
|
|
2033
|
+
this.columnMenuTrigger.openMenu();
|
|
2034
|
+
}
|
|
2035
|
+
/**
|
|
2036
|
+
* @param values columns
|
|
2037
|
+
*/
|
|
2038
|
+
updateColumnsHideShow(values) {
|
|
2039
|
+
let keys = Object.keys(values);
|
|
2040
|
+
keys.forEach((key) => {
|
|
2041
|
+
this.showHideColumn(key, values[key]);
|
|
2042
|
+
});
|
|
2043
|
+
}
|
|
2044
|
+
/**
|
|
2045
|
+
* @description This method is called when the table rows are scrolled.
|
|
2046
|
+
* @param event scroll event
|
|
2047
|
+
*/
|
|
2048
|
+
onScroll(event) {
|
|
2049
|
+
this.scroll.emit(event);
|
|
2050
|
+
}
|
|
2051
|
+
/**
|
|
2052
|
+
* @param row row to be toggled
|
|
2053
|
+
* @param index index of toggled row
|
|
2054
|
+
*/
|
|
2055
|
+
setSelectedRows(row, index) {
|
|
2056
|
+
this.selection.toggle(row);
|
|
2057
|
+
if (this.selection.isSelected(row)) {
|
|
2058
|
+
this.selectionChanged.emit({ row: row, index: index, isSelected: true });
|
|
2059
|
+
}
|
|
2060
|
+
else {
|
|
2061
|
+
this.selectionChanged.emit({ row: row, index: index, isSelected: false });
|
|
2062
|
+
}
|
|
2063
|
+
}
|
|
2064
|
+
/**
|
|
2065
|
+
* @description This method is used to display all hidden rows.
|
|
2066
|
+
*/
|
|
2067
|
+
showHiddenRows() {
|
|
2068
|
+
this.hideRows = false;
|
|
2069
|
+
this.selection.clear();
|
|
2070
|
+
this.hiddenCtrl.clear();
|
|
2071
|
+
}
|
|
2072
|
+
/**
|
|
2073
|
+
* @description This method is used to hide all selected rows.
|
|
2074
|
+
*/
|
|
2075
|
+
hideSelectedRows() {
|
|
2076
|
+
if (!this.selection.isEmpty()) {
|
|
2077
|
+
let values = [...this.selection.selected];
|
|
2078
|
+
values.forEach((value) => {
|
|
2079
|
+
if (!this.hiddenCtrl.isSelected(value)) {
|
|
2080
|
+
this.hiddenCtrl.toggle(value);
|
|
2081
|
+
}
|
|
2082
|
+
});
|
|
2083
|
+
this.selection.clear();
|
|
2084
|
+
this.hideRows = true;
|
|
2085
|
+
}
|
|
2086
|
+
}
|
|
2087
|
+
/**
|
|
2088
|
+
* @description This method is used to recalculate the required values for table.
|
|
2089
|
+
*/
|
|
2090
|
+
reCal() {
|
|
2091
|
+
if (this.showPaginator) {
|
|
2092
|
+
this.dataSource.paginator = this.paginator;
|
|
2093
|
+
}
|
|
2094
|
+
if (this.sorting) {
|
|
2095
|
+
this.dataSource.sort = this.sort;
|
|
2096
|
+
if (this.enableRowPinning) {
|
|
2097
|
+
this.pinnedTopDataSource.sort = this.sort;
|
|
2098
|
+
this.pinnedBtmDataSource.sort = this.sort;
|
|
2099
|
+
}
|
|
2100
|
+
}
|
|
2101
|
+
if (this.columnFilter) {
|
|
2102
|
+
this.dataSource.filterPredicate = this.createFilter();
|
|
2103
|
+
if (this.pinnedTopDataSource) {
|
|
2104
|
+
if (this.pinnedTopDataSource.filterPredicate) {
|
|
2105
|
+
this.pinnedTopDataSource.filterPredicate = this.createFilter();
|
|
2106
|
+
}
|
|
2107
|
+
}
|
|
2108
|
+
if (this.pinnedBtmDataSource) {
|
|
2109
|
+
if (this.pinnedBtmDataSource.filterPredicate) {
|
|
2110
|
+
this.pinnedBtmDataSource.filterPredicate = this.createFilter();
|
|
2111
|
+
}
|
|
2112
|
+
}
|
|
2113
|
+
}
|
|
2114
|
+
this.cdr.detectChanges();
|
|
2115
|
+
}
|
|
2116
|
+
/**
|
|
2117
|
+
* @description This method is called in constructor method to add SVGs into icon registration.
|
|
2118
|
+
*/
|
|
2119
|
+
addIconsToRegistry() {
|
|
2120
|
+
let y = this.domSanitizer.bypassSecurityTrustResourceUrl(`assets/pinRight.svg`);
|
|
2121
|
+
let iconNames = ['pinLeft', 'pinRight', 'pinNone', 'pinned', 'pinIcon'];
|
|
2122
|
+
iconNames.forEach((icon) => {
|
|
2123
|
+
this.matIconRegistry.addSvgIcon(icon, this.domSanitizer.bypassSecurityTrustResourceUrl(`assets/${icon}.svg`));
|
|
2124
|
+
});
|
|
2125
|
+
}
|
|
2126
|
+
/**
|
|
2127
|
+
* @description This method is used to export table data.
|
|
2128
|
+
* @param type type of file to be exported.
|
|
2129
|
+
*/
|
|
2130
|
+
exportTable(type) {
|
|
2131
|
+
const actionColumns = ['select', 'edit', 'popup', 'delete', 'freeze', 'hide', 'pin'];
|
|
2132
|
+
// Get visible columns in the correct order (grouped first, ungrouped at end)
|
|
2133
|
+
let visibleColumns = [];
|
|
2134
|
+
if (this.columnGroups.length > 0) {
|
|
2135
|
+
const groupedFields = new Set();
|
|
2136
|
+
// Collect all fields that belong to groups
|
|
2137
|
+
this.columnGroups.forEach(group => {
|
|
2138
|
+
group.columns.forEach(colField => groupedFields.add(colField));
|
|
2139
|
+
});
|
|
2140
|
+
// Add grouped columns first (in group order)
|
|
2141
|
+
this.columnGroups.forEach(group => {
|
|
2142
|
+
group.columns.forEach(colField => {
|
|
2143
|
+
const col = this.columnsArray.find(c => c.field === colField);
|
|
2144
|
+
const displayCol = this.dynamicDisplayedColumns.find(dc => dc.name === colField);
|
|
2145
|
+
if (col && displayCol && displayCol.show && !visibleColumns.includes(col)) {
|
|
2146
|
+
visibleColumns.push(col);
|
|
2147
|
+
}
|
|
2148
|
+
});
|
|
2149
|
+
});
|
|
2150
|
+
// Add ungrouped columns at the end
|
|
2151
|
+
this.columnsArray.forEach(col => {
|
|
2152
|
+
const displayCol = this.dynamicDisplayedColumns.find(dc => dc.name === col.field);
|
|
2153
|
+
if (!groupedFields.has(col.field) && displayCol && displayCol.show &&
|
|
2154
|
+
!actionColumns.includes(col.field) && !visibleColumns.includes(col)) {
|
|
2155
|
+
visibleColumns.push(col);
|
|
2156
|
+
}
|
|
2157
|
+
});
|
|
2158
|
+
}
|
|
2159
|
+
else {
|
|
2160
|
+
// No groups, use default order
|
|
2161
|
+
visibleColumns = this.columnsArray.filter(col => {
|
|
2162
|
+
const displayCol = this.dynamicDisplayedColumns.find(dc => dc.name === col.field);
|
|
2163
|
+
return displayCol && displayCol.show && !actionColumns.includes(col.field);
|
|
2164
|
+
});
|
|
2165
|
+
}
|
|
2166
|
+
const data = [];
|
|
2167
|
+
// Add group headers if they exist
|
|
2168
|
+
if (this.columnGroups.length > 0) {
|
|
2169
|
+
const groupRow = [];
|
|
2170
|
+
const columnIndexMap = {};
|
|
2171
|
+
visibleColumns.forEach((col, idx) => {
|
|
2172
|
+
columnIndexMap[col.field] = idx;
|
|
2173
|
+
});
|
|
2174
|
+
// Initialize group row with empty strings
|
|
2175
|
+
for (let i = 0; i < visibleColumns.length; i++) {
|
|
2176
|
+
groupRow.push('');
|
|
2177
|
+
}
|
|
2178
|
+
// Fill in group labels
|
|
2179
|
+
this.columnGroups.forEach(group => {
|
|
2180
|
+
const groupCols = group.columns.filter(colField => visibleColumns.find(vc => vc.field === colField));
|
|
2181
|
+
if (groupCols.length > 0) {
|
|
2182
|
+
const firstColIndex = columnIndexMap[groupCols[0]];
|
|
2183
|
+
groupRow[firstColIndex] = group.label;
|
|
2184
|
+
}
|
|
2185
|
+
});
|
|
2186
|
+
data.push(groupRow);
|
|
2187
|
+
}
|
|
2188
|
+
// Add column headers
|
|
2189
|
+
data.push(visibleColumns.map(col => col.header || col.field));
|
|
2190
|
+
// Add data rows (exclude hidden rows)
|
|
2191
|
+
this.dataSource.data.forEach((row, index) => {
|
|
2192
|
+
// Skip hidden rows
|
|
2193
|
+
if (this.hiddenRowIndices.includes(index)) {
|
|
2194
|
+
return;
|
|
2195
|
+
}
|
|
2196
|
+
const rowData = visibleColumns.map(col => {
|
|
2197
|
+
const value = row[col.field];
|
|
2198
|
+
if (value === null || value === undefined)
|
|
2199
|
+
return '';
|
|
2200
|
+
if (typeof value === 'boolean')
|
|
2201
|
+
return value ? 'Yes' : 'No';
|
|
2202
|
+
if (value instanceof Date)
|
|
2203
|
+
return new Intl.DateTimeFormat('en-US').format(value);
|
|
2204
|
+
return value;
|
|
2205
|
+
});
|
|
2206
|
+
data.push(rowData);
|
|
2207
|
+
});
|
|
2208
|
+
const ws = XLSX.utils.aoa_to_sheet(data);
|
|
2209
|
+
// Add merge cells for group headers if they exist
|
|
2210
|
+
if (this.columnGroups.length > 0) {
|
|
2211
|
+
if (!ws['!merges']) {
|
|
2212
|
+
ws['!merges'] = [];
|
|
2213
|
+
}
|
|
2214
|
+
const columnIndexMap = {};
|
|
2215
|
+
visibleColumns.forEach((col, idx) => {
|
|
2216
|
+
columnIndexMap[col.field] = idx;
|
|
2217
|
+
});
|
|
2218
|
+
this.columnGroups.forEach(group => {
|
|
2219
|
+
const groupCols = group.columns.filter(colField => visibleColumns.find(vc => vc.field === colField));
|
|
2220
|
+
if (groupCols.length > 1 && ws['!merges']) {
|
|
2221
|
+
const firstColIndex = columnIndexMap[groupCols[0]];
|
|
2222
|
+
const lastColIndex = columnIndexMap[groupCols[groupCols.length - 1]];
|
|
2223
|
+
ws['!merges'].push({
|
|
2224
|
+
s: { r: 0, c: firstColIndex },
|
|
2225
|
+
e: { r: 0, c: lastColIndex }
|
|
2226
|
+
});
|
|
2227
|
+
}
|
|
2228
|
+
});
|
|
2229
|
+
}
|
|
2230
|
+
const wb = XLSX.utils.book_new();
|
|
2231
|
+
XLSX.utils.book_append_sheet(wb, ws, 'Sheet1');
|
|
2232
|
+
XLSX.writeFile(wb, `tablesheets.${type}`);
|
|
2233
|
+
}
|
|
2234
|
+
/**
|
|
2235
|
+
* @description This method is used to print the table with proper styling.
|
|
2236
|
+
*/
|
|
2237
|
+
printTable() {
|
|
2238
|
+
const printContent = document.getElementById('matTableExt' + this.tableID);
|
|
2239
|
+
if (!printContent)
|
|
2240
|
+
return;
|
|
2241
|
+
const windowPrint = window.open('', '', 'width=900,height=650');
|
|
2242
|
+
if (!windowPrint)
|
|
2243
|
+
return;
|
|
2244
|
+
windowPrint.document.write('<html><head><title>Print Table</title>');
|
|
2245
|
+
windowPrint.document.write('<style>');
|
|
2246
|
+
windowPrint.document.write(`
|
|
2247
|
+
table { border-collapse: collapse; width: 100%; font-family: Arial, sans-serif; }
|
|
2248
|
+
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
|
|
2249
|
+
th { background-color: #f2f2f2; font-weight: bold; }
|
|
2250
|
+
tr:nth-child(even) { background-color: #f9f9f9; }
|
|
2251
|
+
.mat-sort-header-container { display: inline; }
|
|
2252
|
+
.mat-sort-header-arrow, .mat-sort-header-indicator { display: none !important; }
|
|
2253
|
+
button, .mat-icon { display: none !important; }
|
|
2254
|
+
@media print {
|
|
2255
|
+
.mat-mdc-table { page-break-inside: auto; }
|
|
2256
|
+
tr { page-break-inside: avoid; page-break-after: auto; }
|
|
2257
|
+
thead { display: table-header-group; }
|
|
2258
|
+
}
|
|
2259
|
+
`);
|
|
2260
|
+
windowPrint.document.write('</style></head><body>');
|
|
2261
|
+
// Clone the table and remove all action columns
|
|
2262
|
+
const tableClone = printContent.cloneNode(true);
|
|
2263
|
+
// Define action column class selectors
|
|
2264
|
+
const actionColumnSelectors = [
|
|
2265
|
+
'th.action-column-cells',
|
|
2266
|
+
'td.inline-edit-column-cell',
|
|
2267
|
+
// Remove columns by checking for action column names
|
|
2268
|
+
'[matColumnDef="select"]',
|
|
2269
|
+
'[matColumnDef="edit"]',
|
|
2270
|
+
'[matColumnDef="popup"]',
|
|
2271
|
+
'[matColumnDef="delete"]',
|
|
2272
|
+
'[matColumnDef="freeze"]',
|
|
2273
|
+
'[matColumnDef="hide"]',
|
|
2274
|
+
];
|
|
2275
|
+
// Remove all matching elements
|
|
2276
|
+
actionColumnSelectors.forEach(selector => {
|
|
2277
|
+
const elements = tableClone.querySelectorAll(selector);
|
|
2278
|
+
elements.forEach(el => el.remove());
|
|
2279
|
+
});
|
|
2280
|
+
// Also remove cells by index for action columns
|
|
2281
|
+
const actionColumnIndices = [];
|
|
2282
|
+
const headerRow = tableClone.querySelector('tr.mat-mdc-header-row');
|
|
2283
|
+
if (headerRow) {
|
|
2284
|
+
const headers = Array.from(headerRow.querySelectorAll('th'));
|
|
2285
|
+
headers.forEach((th, index) => {
|
|
2286
|
+
if (th.classList.contains('action-column-cells')) {
|
|
2287
|
+
actionColumnIndices.push(index);
|
|
2288
|
+
}
|
|
2289
|
+
});
|
|
2290
|
+
}
|
|
2291
|
+
// Remove cells at action column indices from all rows
|
|
2292
|
+
const rows = tableClone.querySelectorAll('tr');
|
|
2293
|
+
rows.forEach((row, rowIndex) => {
|
|
2294
|
+
// Remove hidden rows (accounting for header rows)
|
|
2295
|
+
const dataIndex = rowIndex - 1; // Subtract 1 for header row
|
|
2296
|
+
if (dataIndex >= 0 && this.hiddenRowIndices.includes(dataIndex)) {
|
|
2297
|
+
row.remove();
|
|
2298
|
+
return;
|
|
2299
|
+
}
|
|
2300
|
+
const cells = Array.from(row.querySelectorAll('th, td'));
|
|
2301
|
+
// Remove in reverse order to maintain correct indices
|
|
2302
|
+
for (let i = actionColumnIndices.length - 1; i >= 0; i--) {
|
|
2303
|
+
const index = actionColumnIndices[i];
|
|
2304
|
+
if (cells[index]) {
|
|
2305
|
+
cells[index].remove();
|
|
2306
|
+
}
|
|
2307
|
+
}
|
|
2308
|
+
});
|
|
2309
|
+
windowPrint.document.write(tableClone.outerHTML);
|
|
2310
|
+
windowPrint.document.write('</body></html>');
|
|
2311
|
+
windowPrint.document.close();
|
|
2312
|
+
setTimeout(() => {
|
|
2313
|
+
windowPrint.print();
|
|
2314
|
+
windowPrint.close();
|
|
2315
|
+
}, 250);
|
|
2316
|
+
}
|
|
2317
|
+
async exportToPDF() {
|
|
2318
|
+
try {
|
|
2319
|
+
// Correct jsPDF import
|
|
2320
|
+
const JsPDF = (await import('jspdf')).default;
|
|
2321
|
+
// Correct AutoTable import
|
|
2322
|
+
const autoTableModule = await import('jspdf-autotable');
|
|
2323
|
+
const autoTable = autoTableModule.autoTable || autoTableModule.default;
|
|
2324
|
+
// Create PDF with user-specified orientation
|
|
2325
|
+
const doc = new JsPDF({
|
|
2326
|
+
orientation: this.pdfOrientation,
|
|
2327
|
+
unit: 'mm',
|
|
2328
|
+
format: 'a4'
|
|
2329
|
+
});
|
|
2330
|
+
const actionColumns = ['select', 'edit', 'popup', 'delete', 'freeze', 'hide', 'pin'];
|
|
2331
|
+
// Get visible columns in the correct order (grouped first, ungrouped at end)
|
|
2332
|
+
let visibleColumns = [];
|
|
2333
|
+
if (this.columnGroups.length > 0) {
|
|
2334
|
+
const groupedFields = new Set();
|
|
2335
|
+
// Collect all fields that belong to groups
|
|
2336
|
+
this.columnGroups.forEach(group => {
|
|
2337
|
+
group.columns.forEach(colField => groupedFields.add(colField));
|
|
2338
|
+
});
|
|
2339
|
+
// Add grouped columns first (in group order)
|
|
2340
|
+
this.columnGroups.forEach(group => {
|
|
2341
|
+
group.columns.forEach(colField => {
|
|
2342
|
+
const col = this.columnsArray.find(c => c.field === colField);
|
|
2343
|
+
const displayCol = this.dynamicDisplayedColumns.find(dc => dc.name === colField);
|
|
2344
|
+
if (col && displayCol && displayCol.show && !visibleColumns.includes(col)) {
|
|
2345
|
+
visibleColumns.push(col);
|
|
2346
|
+
}
|
|
2347
|
+
});
|
|
2348
|
+
});
|
|
2349
|
+
// Add ungrouped columns at the end
|
|
2350
|
+
this.columnsArray.forEach(col => {
|
|
2351
|
+
const displayCol = this.dynamicDisplayedColumns.find(dc => dc.name === col.field);
|
|
2352
|
+
if (!groupedFields.has(col.field) && displayCol && displayCol.show &&
|
|
2353
|
+
!actionColumns.includes(col.field) && !visibleColumns.includes(col)) {
|
|
2354
|
+
visibleColumns.push(col);
|
|
2355
|
+
}
|
|
2356
|
+
});
|
|
2357
|
+
}
|
|
2358
|
+
else {
|
|
2359
|
+
// No groups, use default order
|
|
2360
|
+
visibleColumns = this.columnsArray.filter(col => {
|
|
2361
|
+
const displayCol = this.dynamicDisplayedColumns.find(dc => dc.name === col.field);
|
|
2362
|
+
return displayCol && displayCol.show && !actionColumns.includes(col.field);
|
|
2363
|
+
});
|
|
2364
|
+
}
|
|
2365
|
+
// Prepare group headers if column groups exist
|
|
2366
|
+
let groupHeaders = [];
|
|
2367
|
+
let columnIndexMap = {};
|
|
2368
|
+
let groupColSpans = {};
|
|
2369
|
+
if (this.columnGroups.length > 0) {
|
|
2370
|
+
// Build column index map
|
|
2371
|
+
visibleColumns.forEach((col, idx) => {
|
|
2372
|
+
columnIndexMap[col.field] = idx;
|
|
2373
|
+
});
|
|
2374
|
+
// Create group header row
|
|
2375
|
+
const groupRow = [];
|
|
2376
|
+
let currentIndex = 0;
|
|
2377
|
+
this.columnGroups.forEach(group => {
|
|
2378
|
+
const groupCols = group.columns.filter(colField => visibleColumns.find(vc => vc.field === colField));
|
|
2379
|
+
if (groupCols.length > 0) {
|
|
2380
|
+
const firstColIndex = columnIndexMap[groupCols[0]];
|
|
2381
|
+
// Add the group header cell with content and colspan
|
|
2382
|
+
groupRow.push({
|
|
2383
|
+
content: group.label,
|
|
2384
|
+
colSpan: groupCols.length,
|
|
2385
|
+
styles: { halign: 'center' }
|
|
2386
|
+
});
|
|
2387
|
+
groupColSpans[firstColIndex] = groupCols.length;
|
|
2388
|
+
currentIndex = firstColIndex + groupCols.length;
|
|
2389
|
+
}
|
|
2390
|
+
});
|
|
2391
|
+
// Add empty cells for ungrouped columns
|
|
2392
|
+
const groupedFields = new Set();
|
|
2393
|
+
this.columnGroups.forEach(group => {
|
|
2394
|
+
group.columns.forEach(colField => groupedFields.add(colField));
|
|
2395
|
+
});
|
|
2396
|
+
const ungroupedCount = visibleColumns.filter(col => !groupedFields.has(col.field)).length;
|
|
2397
|
+
for (let i = 0; i < ungroupedCount; i++) {
|
|
2398
|
+
groupRow.push({
|
|
2399
|
+
content: '',
|
|
2400
|
+
styles: { halign: 'center' }
|
|
2401
|
+
});
|
|
2402
|
+
}
|
|
2403
|
+
groupHeaders = [groupRow];
|
|
2404
|
+
}
|
|
2405
|
+
const headers = visibleColumns.map(col => col.header || col.field);
|
|
2406
|
+
const rows = this.dataSource.data
|
|
2407
|
+
.map((row, index) => ({
|
|
2408
|
+
row,
|
|
2409
|
+
index
|
|
2410
|
+
}))
|
|
2411
|
+
.filter(({ index }) => !this.hiddenRowIndices.includes(index))
|
|
2412
|
+
.map(({ row }) => visibleColumns.map(col => {
|
|
2413
|
+
const value = row[col.field];
|
|
2414
|
+
if (value === null || value === undefined)
|
|
2415
|
+
return '';
|
|
2416
|
+
if (typeof value === 'boolean')
|
|
2417
|
+
return value ? 'Yes' : 'No';
|
|
2418
|
+
if (value instanceof Date)
|
|
2419
|
+
return new Intl.DateTimeFormat('en-US').format(value);
|
|
2420
|
+
return String(value);
|
|
2421
|
+
}));
|
|
2422
|
+
let startY = 10;
|
|
2423
|
+
if (this.toolbarTitle) {
|
|
2424
|
+
doc.text(this.toolbarTitle, 14, 15);
|
|
2425
|
+
startY = 20;
|
|
2426
|
+
}
|
|
2427
|
+
// Extract header styles from actual mat-table
|
|
2428
|
+
let headerStyles = {
|
|
2429
|
+
fillColor: [245, 245, 245], // Default Material table header background (#f5f5f5)
|
|
2430
|
+
textColor: [0, 0, 0], // Default Material table header text (black)
|
|
2431
|
+
fontStyle: 'bold'
|
|
2432
|
+
};
|
|
2433
|
+
// If headerTemplateRef is defined, extract styles from the actual header cells
|
|
2434
|
+
if (this.headerTemplateRef) {
|
|
2435
|
+
const headerCells = this.tableElement?.nativeElement?.querySelectorAll('.mat-mdc-header-cell');
|
|
2436
|
+
if (headerCells && headerCells.length > 0) {
|
|
2437
|
+
const firstHeader = headerCells[0];
|
|
2438
|
+
const computedStyles = window.getComputedStyle(firstHeader);
|
|
2439
|
+
// Extract background color
|
|
2440
|
+
const bgColor = computedStyles.backgroundColor;
|
|
2441
|
+
if (bgColor && bgColor !== 'rgba(0, 0, 0, 0)' && bgColor !== 'transparent') {
|
|
2442
|
+
const rgb = bgColor.match(/\d+/g);
|
|
2443
|
+
if (rgb && rgb.length >= 3) {
|
|
2444
|
+
headerStyles.fillColor = [parseInt(rgb[0]), parseInt(rgb[1]), parseInt(rgb[2])];
|
|
2445
|
+
}
|
|
2446
|
+
}
|
|
2447
|
+
// Extract text color
|
|
2448
|
+
const textColor = computedStyles.color;
|
|
2449
|
+
if (textColor) {
|
|
2450
|
+
const rgb = textColor.match(/\d+/g);
|
|
2451
|
+
if (rgb && rgb.length >= 3) {
|
|
2452
|
+
headerStyles.textColor = [parseInt(rgb[0]), parseInt(rgb[1]), parseInt(rgb[2])];
|
|
2453
|
+
}
|
|
2454
|
+
}
|
|
2455
|
+
// Extract font weight
|
|
2456
|
+
const fontWeight = computedStyles.fontWeight;
|
|
2457
|
+
if (fontWeight && (fontWeight === 'bold' || parseInt(fontWeight) >= 600)) {
|
|
2458
|
+
headerStyles.fontStyle = 'bold';
|
|
2459
|
+
}
|
|
2460
|
+
else {
|
|
2461
|
+
headerStyles.fontStyle = 'normal';
|
|
2462
|
+
}
|
|
2463
|
+
}
|
|
2464
|
+
}
|
|
2465
|
+
// Extract group header styles if groups exist
|
|
2466
|
+
let groupHeaderStyles = null;
|
|
2467
|
+
if (groupHeaders.length > 0) {
|
|
2468
|
+
// Extract from group-header-cell elements
|
|
2469
|
+
const groupHeaderCells = this.tableElement?.nativeElement?.querySelectorAll('.group-header-cell');
|
|
2470
|
+
if (groupHeaderCells && groupHeaderCells.length > 0) {
|
|
2471
|
+
const firstGroupHeader = groupHeaderCells[0];
|
|
2472
|
+
const computedStyles = window.getComputedStyle(firstGroupHeader);
|
|
2473
|
+
groupHeaderStyles = {};
|
|
2474
|
+
// Extract background color
|
|
2475
|
+
const bgColor = computedStyles.backgroundColor;
|
|
2476
|
+
if (bgColor && bgColor !== 'rgba(0, 0, 0, 0)' && bgColor !== 'transparent') {
|
|
2477
|
+
const rgb = bgColor.match(/\d+/g);
|
|
2478
|
+
if (rgb && rgb.length >= 3) {
|
|
2479
|
+
groupHeaderStyles.fillColor = [parseInt(rgb[0]), parseInt(rgb[1]), parseInt(rgb[2])];
|
|
2480
|
+
}
|
|
2481
|
+
}
|
|
2482
|
+
else {
|
|
2483
|
+
// Default to same as header background
|
|
2484
|
+
groupHeaderStyles.fillColor = headerStyles.fillColor;
|
|
2485
|
+
}
|
|
2486
|
+
// Extract text color
|
|
2487
|
+
const textColor = computedStyles.color;
|
|
2488
|
+
if (textColor) {
|
|
2489
|
+
const rgb = textColor.match(/\d+/g);
|
|
2490
|
+
if (rgb && rgb.length >= 3) {
|
|
2491
|
+
groupHeaderStyles.textColor = [parseInt(rgb[0]), parseInt(rgb[1]), parseInt(rgb[2])];
|
|
2492
|
+
}
|
|
2493
|
+
}
|
|
2494
|
+
else {
|
|
2495
|
+
// Default to same as header text
|
|
2496
|
+
groupHeaderStyles.textColor = headerStyles.textColor;
|
|
2497
|
+
}
|
|
2498
|
+
// Extract font weight
|
|
2499
|
+
const fontWeight = computedStyles.fontWeight;
|
|
2500
|
+
if (fontWeight && (fontWeight === 'bold' || parseInt(fontWeight) >= 600)) {
|
|
2501
|
+
groupHeaderStyles.fontStyle = 'bold';
|
|
2502
|
+
}
|
|
2503
|
+
else {
|
|
2504
|
+
groupHeaderStyles.fontStyle = 'normal';
|
|
2505
|
+
}
|
|
2506
|
+
}
|
|
2507
|
+
else {
|
|
2508
|
+
// No group header cells found, use same as regular headers
|
|
2509
|
+
groupHeaderStyles = { ...headerStyles };
|
|
2510
|
+
}
|
|
2511
|
+
}
|
|
2512
|
+
// Build table config without default grid borders. We'll draw only
|
|
2513
|
+
// bottom dividers manually in `didDrawCell` so there are no left/right borders.
|
|
2514
|
+
const tableConfig = {
|
|
2515
|
+
head: groupHeaders.length > 0 ? [...groupHeaders, headers] : [headers],
|
|
2516
|
+
body: rows,
|
|
2517
|
+
startY: startY,
|
|
2518
|
+
// Use 'plain' so autowire doesn't draw full grid borders
|
|
2519
|
+
theme: 'plain',
|
|
2520
|
+
styles: {
|
|
2521
|
+
fontSize: 9,
|
|
2522
|
+
cellPadding: 3,
|
|
2523
|
+
// ensure autTable doesn't draw default lines
|
|
2524
|
+
lineWidth: 0
|
|
2525
|
+
},
|
|
2526
|
+
headStyles: headerStyles
|
|
2527
|
+
};
|
|
2528
|
+
// didParseCell: apply header/group header visual styles (background/text/font)
|
|
2529
|
+
tableConfig.didParseCell = (data) => {
|
|
2530
|
+
// Group header row styling (if present)
|
|
2531
|
+
if (data.section === 'head' && groupHeaders.length > 0 && data.row.index === 0 && groupHeaderStyles) {
|
|
2532
|
+
if (groupHeaderStyles.fillColor)
|
|
2533
|
+
data.cell.styles.fillColor = groupHeaderStyles.fillColor;
|
|
2534
|
+
if (groupHeaderStyles.textColor)
|
|
2535
|
+
data.cell.styles.textColor = groupHeaderStyles.textColor;
|
|
2536
|
+
if (groupHeaderStyles.fontStyle)
|
|
2537
|
+
data.cell.styles.fontStyle = groupHeaderStyles.fontStyle;
|
|
2538
|
+
data.cell.styles.halign = 'center';
|
|
2539
|
+
}
|
|
2540
|
+
// Final header row (column labels) should use headerStyles
|
|
2541
|
+
if (data.section === 'head' && data.row.index === (groupHeaders.length > 0 ? groupHeaders.length : 0)) {
|
|
2542
|
+
if (headerStyles.fillColor)
|
|
2543
|
+
data.cell.styles.fillColor = headerStyles.fillColor;
|
|
2544
|
+
if (headerStyles.textColor)
|
|
2545
|
+
data.cell.styles.textColor = headerStyles.textColor;
|
|
2546
|
+
if (headerStyles.fontStyle)
|
|
2547
|
+
data.cell.styles.fontStyle = headerStyles.fontStyle;
|
|
2548
|
+
}
|
|
2549
|
+
};
|
|
2550
|
+
// didDrawCell: draw only the bottom divider line for each cell
|
|
2551
|
+
tableConfig.didDrawCell = (data) => {
|
|
2552
|
+
try {
|
|
2553
|
+
const cell = data.cell;
|
|
2554
|
+
const docRef = doc;
|
|
2555
|
+
// Determine stroke color and width for divider
|
|
2556
|
+
const lineColor = [200, 200, 200];
|
|
2557
|
+
const lineWidth = 0.5;
|
|
2558
|
+
// Coordinates: draw a horizontal line across the bottom of the cell
|
|
2559
|
+
const x1 = cell.x;
|
|
2560
|
+
const x2 = cell.x + cell.width;
|
|
2561
|
+
const y = cell.y + cell.height;
|
|
2562
|
+
docRef.setDrawColor(lineColor[0], lineColor[1], lineColor[2]);
|
|
2563
|
+
docRef.setLineWidth(lineWidth);
|
|
2564
|
+
docRef.line(x1, y, x2, y);
|
|
2565
|
+
}
|
|
2566
|
+
catch (err) {
|
|
2567
|
+
// don't block export on draw errors
|
|
2568
|
+
}
|
|
2569
|
+
};
|
|
2570
|
+
autoTable(doc, tableConfig);
|
|
2571
|
+
doc.save(`${this.toolbarTitle || 'table-export'}.pdf`);
|
|
2572
|
+
}
|
|
2573
|
+
catch (error) {
|
|
2574
|
+
console.error('Error exporting to PDF:', error);
|
|
2575
|
+
}
|
|
2576
|
+
}
|
|
2577
|
+
/**
|
|
2578
|
+
* @description This method is used to split name of filter row header to get index.
|
|
2579
|
+
* @param value value to be splited for index.
|
|
2580
|
+
* @returns Will return index of column from value.
|
|
2581
|
+
*/
|
|
2582
|
+
returnIndex(value) {
|
|
2583
|
+
return Number(value.split('_')[1]);
|
|
2584
|
+
}
|
|
2585
|
+
/**
|
|
2586
|
+
* @description This method is used to manage column filtering, expanded data for exporting.
|
|
2587
|
+
* @param ws work sheet
|
|
2588
|
+
* @returns custom generated worksheet to be used in export.
|
|
2589
|
+
*/
|
|
2590
|
+
writeSheetData(ws) {
|
|
2591
|
+
let displayedColumns = this.getDisplayedColumns();
|
|
2592
|
+
var nMerges = this.getMergeIndex(ws['!merges'] || []);
|
|
2593
|
+
var merges = ws['!merges'] || [];
|
|
2594
|
+
let data = {
|
|
2595
|
+
'!cols': [],
|
|
2596
|
+
'!rows': [],
|
|
2597
|
+
'!merges': nMerges,
|
|
2598
|
+
};
|
|
2599
|
+
var range = XLSX.utils.decode_range(ws['!ref'] || '');
|
|
2600
|
+
let extracolumns = ['popup', 'delete', 'select', 'edit'];
|
|
2601
|
+
let keys = Object.keys(ws);
|
|
2602
|
+
let nKey = 'A';
|
|
2603
|
+
keys.forEach((key, i) => {
|
|
2604
|
+
if (ws[key]?.v && typeof ws[key]?.v === 'string') {
|
|
2605
|
+
if (!extracolumns.includes(ws[key].v.toLowerCase()) &&
|
|
2606
|
+
displayedColumns.includes(ws[key].v.toLowerCase())) {
|
|
2607
|
+
let lastRowIndex = range?.e?.r;
|
|
2608
|
+
data[key] = ws[key];
|
|
2609
|
+
let chr = key.charAt(0);
|
|
2610
|
+
for (let j = 2; j <= lastRowIndex; j++) {
|
|
2611
|
+
if (ws[chr + (j + 1)] !== undefined &&
|
|
2612
|
+
(typeof ws[chr + (j + 1)].v === 'string' ||
|
|
2613
|
+
typeof ws[chr + (j + 1)].v === 'number')) {
|
|
2614
|
+
data[nKey + j] = ws[chr + (j + 1)];
|
|
2615
|
+
}
|
|
2616
|
+
}
|
|
2617
|
+
nKey = String.fromCharCode(nKey.charCodeAt(0) + 1);
|
|
2618
|
+
}
|
|
2619
|
+
}
|
|
2620
|
+
});
|
|
2621
|
+
if (this.rowSelection) {
|
|
2622
|
+
let chr = 'A';
|
|
2623
|
+
for (let i = 1; i < range.e.c + 1; i++) {
|
|
2624
|
+
data[chr + 1] = data[String.fromCharCode(chr.charCodeAt(0) + 1) + 1];
|
|
2625
|
+
chr = String.fromCharCode(chr.charCodeAt(0) + 1);
|
|
2626
|
+
if (i == range.e.c) {
|
|
2627
|
+
data[chr + 1] = undefined;
|
|
2628
|
+
}
|
|
2629
|
+
}
|
|
2630
|
+
}
|
|
2631
|
+
if (this.rowSelection && this.expandRows) {
|
|
2632
|
+
merges.forEach((merge) => {
|
|
2633
|
+
data['A' + merge.s.r] = ws['A' + (merge.s.r + 1)];
|
|
2634
|
+
});
|
|
2635
|
+
}
|
|
2636
|
+
range.e.r--;
|
|
2637
|
+
let nRef = XLSX.utils.encode_range(range);
|
|
2638
|
+
data['!ref'] = nRef;
|
|
2639
|
+
data['!fullref'] = nRef;
|
|
2640
|
+
return data;
|
|
2641
|
+
}
|
|
2642
|
+
getMergeIndex(merges) {
|
|
2643
|
+
var arr = [];
|
|
2644
|
+
merges.forEach((element) => {
|
|
2645
|
+
arr.push({
|
|
2646
|
+
e: {
|
|
2647
|
+
r: element.e.r == 0 ? element.e.r : element.e.r - 1,
|
|
2648
|
+
c: element.e.c,
|
|
2649
|
+
},
|
|
2650
|
+
s: {
|
|
2651
|
+
r: element.s.r == 0 ? element.s.r : element.s.r - 1,
|
|
2652
|
+
c: element.s.c,
|
|
2653
|
+
},
|
|
2654
|
+
});
|
|
2655
|
+
});
|
|
2656
|
+
return arr;
|
|
2657
|
+
}
|
|
2658
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.5", ngImport: i0, type: MatTableExtComponent, deps: [{ token: i1$1.MatDialog }, { token: MatTableExtService }, { token: i3.FormBuilder }, { token: i4.DomSanitizer }, { token: i5$1.MatIconRegistry }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2659
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.5", type: MatTableExtComponent, isStandalone: true, selector: "mat-table-ext", inputs: { dataSource: "dataSource", columns: "columns", columnResizable: "columnResizable", stripedRows: "stripedRows", rowHover: "rowHover", inlineRowEditing: "inlineRowEditing", inCellEditing: "inCellEditing", cellPopupEditing: "cellPopupEditing", popupRowEditing: "popupRowEditing", enableDelete: "enableDelete", rowSelection: "rowSelection", multiRowSelection: "multiRowSelection", stickyFooter: "stickyFooter", stickyHeader: "stickyHeader", showFooterRow: "showFooterRow", columnFilter: "columnFilter", loadingIndicator: "loadingIndicator", sorting: "sorting", showToolbar: "showToolbar", toolbarTitle: "toolbarTitle", tableHeight: "tableHeight", toolbarHeight: "toolbarHeight", tableWidth: "tableWidth", scrollbarH: "scrollbarH", toolbarTemplate: "toolbarTemplate", columnHidable: "columnHidable", columnPinnable: "columnPinnable", globalSearch: "globalSearch", expandRows: "expandRows", dndColumns: "dndColumns", showPaginator: "showPaginator", showFirstLastButtons: "showFirstLastButtons", exportButtonEnable: "exportButtonEnable", printButtonEnable: "printButtonEnable", pageSizeOptions: "pageSizeOptions", toolbarTemplateRef: "toolbarTemplateRef", headerTemplateRef: "headerTemplateRef", cellTemplateRef: "cellTemplateRef", expansionTemplateRef: "expansionTemplateRef", popupEditingTemplateRef: "popupEditingTemplateRef", inlineEditingTemplateRef: "inlineEditingTemplateRef", cellEditingTemplateRef: "cellEditingTemplateRef", cellPopupEditingTemplateRef: "cellPopupEditingTemplateRef", cellTemplateRefMap: "cellTemplateRefMap", tableClassName: "tableClassName", columnGroups: "columnGroups", hiddenRowIndices: "hiddenRowIndices", enableRowHiding: "enableRowHiding", enableRowPinning: "enableRowPinning", topPinnedMaxHeight: "topPinnedMaxHeight", bottomPinnedMaxHeight: "bottomPinnedMaxHeight", rowPinningFn: "rowPinningFn", rowHidingFilterFn: "rowHidingFilterFn", pdfOrientation: "pdfOrientation" }, outputs: { inlineChange: "inlineChange", cellChange: "cellChange", popupChange: "popupChange", rowDeleted: "rowDeleted", scroll: "scroll", selectionChanged: "selectionChanged", expansionChange: "expansionChange", rowPinningChange: "rowPinningChange" }, viewQueries: [{ propertyName: "menuTrigger", first: true, predicate: MatMenuTrigger, descendants: true }, { propertyName: "columnMenuTrigger", first: true, predicate: ["columnMenuTrigger"], descendants: true }, { propertyName: "paginator", first: true, predicate: MatPaginator, descendants: true }, { propertyName: "sort", first: true, predicate: MatSort, descendants: true }, { propertyName: "matTableRef", first: true, predicate: ["matTable"], descendants: true, read: ElementRef }, { propertyName: "table", first: true, predicate: ["MyTable"], descendants: true }, { propertyName: "tableElement", first: true, predicate: ["MyTable"], descendants: true, read: ElementRef }], usesOnChanges: true, ngImport: i0, template: "<div [style.width]=\"tableWidth\">\n @if (globalSearch) {\n <mat-form-field class=\"global-search-field\" appearance=\"fill\">\n <mat-label>Search</mat-label>\n <input matInput [ngModel]=\"globalFilter\" (ngModelChange)=\"applyGlobalFilter($event)\" placeholder=\"Ex. Mia\"\n #input>\n </mat-form-field>\n }\n @if (showToolbar) {\n <mat-toolbar class=\"toolbar-container\" [style.height]=\"toolbarHeight?toolbarHeight:'50px'\">\n @if (toolbarTitle) {\n <span class=\"toolbar-title\">{{toolbarTitle}}</span>\n }\n @if (toolbarTemplateRef) {\n <ng-container [ngTemplateOutlet]=\"toolbarTemplateRef\"></ng-container>\n }\n <span class=\"example-spacer\"></span>\n @if (rowSelection || multiRowSelection) {\n <button class=\"hide-button\" mat-stroked-button color=\"primary\" (click)=\"hideSelectedRows()\">\n Hide Rows\n </button>\n <button class=\"hide-button\" mat-stroked-button color=\"primary\" (click)=\"showHiddenRows()\">\n Show All Rows\n </button>\n }\n @if (enableRowHiding && hiddenRowIndices.length > 0) {\n <button class=\"hide-button custom-primary-color\" mat-stroked-button color=\"accent\" (click)=\"unhideAllRows()\"\n matTooltip=\"Unhide all hidden rows\" matTooltipPosition=\"above\">\n <mat-icon>visibility</mat-icon>\n <span>Unhide All ({{hiddenRowIndices.length}})</span>\n </button>\n }\n @if (columnHidable) {\n <button class=\"hide-button\" mat-stroked-button color=\"primary\"\n (click)=\"openMenu('hideShow',$event)\" matTooltip=\"Column Visibility\" matTooltipPosition=\"above\">\n <mat-icon>visibility</mat-icon>\n </button>\n }\n @if (columnPinnable) {\n <button class=\"pin-button\" mat-stroked-button color=\"primary\"\n (click)=\"openMenu('columnPin',$event)\" matTooltip=\"Column Pinning\">\n <mat-icon svgIcon=\"pinIcon\"></mat-icon>\n </button>\n }\n @if (exportButtonEnable) {\n <button class=\"export-button\" mat-stroked-button color=\"primary\"\n (click)=\"openMenu('export',$event)\" matTooltip=\"Table Data Export\">\n <mat-icon>import_export</mat-icon>\n <span>Export</span>\n <mat-icon iconPositionEnd>expand_more</mat-icon>\n </button>\n }\n @if (printButtonEnable) {\n <button class=\"print-button\" mat-stroked-button color=\"primary\"\n (click)=\"printTable()\" matTooltip=\"Print Table\">\n <mat-icon style=\"margin:unset;\">print</mat-icon>\n </button>\n }\n <div style=\"visibility: hidden; position:fixed\" [matMenuTriggerFor]=\"menu\" [style.left.px]=\"menuX\"\n [style.top.px]=\"menuY\"></div>\n </mat-toolbar>\n }\n <mat-menu #menu=\"matMenu\" (closed)=\"menuClosed()\" id=\"exportMenu\">\n @if (exportMenuCtrl) {\n <mat-option (click)=\"exportTable('xlsx')\">Export to Excel</mat-option>\n <mat-option (click)=\"exportTable('csv')\">Export to CSV</mat-option>\n <mat-option (click)=\"exportToPDF()\">Export to PDF</mat-option>\n }\n </mat-menu>\n <div style=\"visibility: hidden; position:fixed\" #columnMenuTrigger=\"matMenuTrigger\" [matMenuTriggerFor]=\"columnMenu\"\n [style.left.px]=\"menuX\" [style.top.px]=\"menuY\">\n </div>\n <mat-menu #columnMenu=\"matMenu\" (closed)=\"resetMenuChecks()\">\n @if (hideShowMenuCtrl) {\n <div class=\"toolbar-menu-container\" [formGroup]=\"hideShowMenuGroup\"\n (click)=\"$event.stopPropagation()\">\n <h4 class=\"column-headers\">Visible Columns</h4>\n <mat-form-field appearance=\"fill\" style=\"width: -webkit-fill-available;\">\n <mat-label>Filter Columns</mat-label>\n <input matInput [(ngModel)]=\"showHideFilter\" (ngModelChange)=\"filterColumns($event)\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n <div class=\"showHide-menu-columns-list\">\n @for (column of showHideColumnsArray; track column.field) {\n <div class=\"toolbar-menu-item\">\n <mat-checkbox color=\"primary\" class=\"toolbar-menu-checkbox\" style=\"width: max-content;\"\n [formControlName]=\"column.field\" (change)=\"setColumnHideShow()\">{{column.header}}</mat-checkbox>\n </div>\n }\n </div>\n </div>\n }\n @if (columnPinMenuCtrl) {\n <div class=\"toolbar-menu-container\" (click)=\"$event.stopPropagation()\">\n <h4 class=\"column-headers\">Pin Columns</h4>\n <form class=\"example-form\">\n <mat-form-field appearance=\"fill\" style=\"width: -webkit-fill-available;\">\n <mat-label>Filter Columns</mat-label>\n <input matInput [(ngModel)]=\"showHideFilter\" (ngModelChange)=\"filterColumns($event)\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n </form>\n <div class=\"showHide-menu-columns-list\">\n <app-column-pinning [columns]=\"showHideColumnsArray\" (columnsChanged)=\"updateColumns($event)\"></app-column-pinning>\n </div>\n </div>\n }\n </mat-menu>\n\n <!-- Row Pin Menu -->\n <mat-menu #pinMenu=\"matMenu\" (closed)=\"closeRowPinMenu()\">\n @if (rowPinMenuRow) {\n @if (!isRowPinned(rowPinMenuRow)) {\n <button mat-menu-item (click)=\"pinRow(rowPinMenuRow, 'top')\">\n <mat-icon>vertical_align_top</mat-icon>\n <span>Pin to Top</span>\n </button>\n <button mat-menu-item (click)=\"pinRow(rowPinMenuRow, 'bottom')\">\n <mat-icon>vertical_align_bottom</mat-icon>\n <span>Pin to Bottom</span>\n </button>\n }\n @if (isRowPinned(rowPinMenuRow)) {\n <button mat-menu-item (click)=\"unpinRow(rowPinMenuRow)\">\n <mat-icon>close</mat-icon>\n <span>Unpin Row</span>\n </button>\n }\n }\n </mat-menu>\n\n @if (loadingIndicator) {\n <mat-progress-bar mode=\"indeterminate\"></mat-progress-bar>\n }\n <section id=\"tableContainer\" class=\"mat-table-ext-container\" (scroll)=\"onScroll($event)\"\n [style.height]=\"tableHeight ? tableHeight :'max-content'\">\n \n @if(enableRowPinning){\n <div [style.max-height]=\"topPinnedMaxHeight\" [style.overflow]=\"topPinnedMaxHeight ? 'auto' : 'visible'\" \n [style.position]=\"'sticky'\" [style.top]=\"'0'\" [style.z-index]=\"'111'\">\n <table style=\"width: 100%;\" \n mat-table #MyTableTop [id]=\"'matTableExtTop'+tableID\" [dataSource]=\"pinnedTopDataSource\" matSort cdkDropList\n cdkDropListOrientation=\"horizontal\" multiTemplateDataRows (cdkDropListDropped)=\"onDrop($event)\"\n (click)=\"saveCellEditing()\" [style.width]=\"scrollbarH?'max-content':'100%'\" \n [class]=\"'mat-mdc-table' + (tableClassName ? ' ' + tableClassName : '')\">\n \n <!-- Row selection column -->\n <ng-container matColumnDef=\"select\">\n <th mat-header-cell *matHeaderCellDef cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"!dndColumns\">\n <mat-checkbox (change)=\"$event ? toggleAllRows() : null\"\n [checked]=\"selection.hasValue() && isAllSelected()\"\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\" [aria-label]=\"checkboxLabel()\">\n </mat-checkbox>\n </th>\n <td mat-cell *matCellDef=\"let row;let i = dataIndex\">\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? setSelectedRows(row,i) : null\"\n [checked]=\"selection.isSelected(row)\" [aria-label]=\"checkboxLabel(row)\">\n </mat-checkbox>\n </td>\n <ng-container *ngIf=\"showFooterRow\">\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n </ng-container>\n <!--dynamic columns are being generated here-->\n @for (column of columnsArray; track column.field + '_' + column.pinned; let i = $index) {\n <div matColumnDef=\"{{column['field']}}\" [sticky]=\"column.pinned === 'left'\" [stickyEnd]=\"column.pinned === 'right'\">\n <th mat-header-cell *matHeaderCellDef [style.minWidth]=\"column.width\" [style.maxWidth]=\"column.maxWidth?column.maxWidth:column.width\"\n [style.minWidth]=\"column.minWidth\" cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"!dndColumns\"\n [columnsResizable]=\"columnResizable\" [index]=\"i\" class=\"mat-mdc-header-cell\"\n [mat-sort-header]=\"column.field\" [disabled]=\"!sorting || column.disabled === true\">\n \n @if (column.headerTemplate || headerTemplateRef) {\n <ng-template [ngTemplateOutlet]=\"column.headerTemplate || headerTemplateRef\"\n [ngTemplateOutletContext]=\"{data:column}\"></ng-template>\n }\n @if (!headerTemplateRef && !column.headerTemplate) {\n <span matTooltip=\"{{column.headerTooltip?.value}}\"\n [matTooltipPosition]=\"column?.headerTooltip?.tooltipPosition!\"\n [class.disabled]=\"!sorting || column.disabled === true\">{{column.header}}</span>\n }\n </th>\n <td mat-cell *matCellDef=\"let row ;let i=dataIndex\" class=\"mat-mdc-cell\">\n @if (!row.editable && !cellEditing[i +'_'+column.field]) {\n <div [style.cursor]=\"'default'\"\n matTooltip=\"{{column.cellTooltip?.value}}\"\n [matTooltipPosition]=\"column?.cellTooltip?.tooltipPosition!\">\n @if (!cellTemplateRef && !column?.cellTemplate && !cellTemplateRefMap[column.field]) {\n <span>{{row[column.field]}}</span>\n }\n @if (cellTemplateRefMap[column.field]) {\n <ng-container [ngTemplateOutlet]=\"cellTemplateRefMap[column.field]\"\n [ngTemplateOutletContext]=\"{row:row,column:column,index:i}\">\n </ng-container>\n }\n @if (cellTemplateRef && column.cellTemplate && !cellTemplateRefMap[column.field]) {\n <ng-container [ngTemplateOutlet]=\"column.cellTemplate\"\n [ngTemplateOutletContext]=\"{row:row,column:column,index:i}\">\n </ng-container>\n }\n @if (!cellTemplateRef && column.cellTemplate && !cellTemplateRefMap[column.field]) {\n <ng-container [ngTemplateOutlet]=\"column.cellTemplate\"\n [ngTemplateOutletContext]=\"{row:row,column:column,index:i}\">\n </ng-container>\n }\n @if (cellTemplateRef && !column.cellTemplate && !cellTemplateRefMap[column.field]) {\n <ng-container [ngTemplateOutlet]=\"cellTemplateRef\"\n [ngTemplateOutletContext]=\"{row:row,column:column,index:i}\">\n </ng-container>\n }\n </div>\n }\n @if (row.editable || cellEditing[i +'_'+column.field]) {\n <div (click)=\"$event.stopPropagation()\">\n @if (inlineEditingTemplateRef && !cellEditing[i +'_'+column.field]) {\n <ng-container [ngTemplateOutlet]=\"inlineEditingTemplateRef\"\n [ngTemplateOutletContext]=\"{data:getInlineEditingData(row,i,column)}\"></ng-container>\n }\n @if (cellEditingTemplateRef && !(row.editable)) {\n <ng-container [ngTemplateOutlet]=\"cellEditingTemplateRef\"\n [ngTemplateOutletContext]=\"{data:getInlineEditingData(row,i,column)}\"></ng-container>\n }\n @if (!inlineEditingTemplateRef && (row.editable) && rowDataTemp['e'+i]) {\n @if (column.type == 'number') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"number\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'string') {\n <mat-form-field style=\"width: 100%;\" appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"text\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'textarea') {\n <mat-form-field style=\"width: 100%;\" appearance=\"outline\" class=\"inline-editing-field\">\n <textarea matInput rows=\"3\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\"></textarea>\n </mat-form-field>\n }\n @if (column.type == 'date') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"date\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'datepicker') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput [matDatepicker]=\"inlinePicker\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n <mat-datepicker-toggle matIconSuffix [for]=\"inlinePicker\"></mat-datepicker-toggle>\n <mat-datepicker #inlinePicker></mat-datepicker>\n </mat-form-field>\n }\n @if (column.type == 'selection') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-select [value]=\"rowDataTemp['e'+i][column.field]\"\n [(ngModel)]=\"rowDataTemp['e'+i][column.field]\">\n @for (option of column.options; track option) {\n <mat-option [value]=\"option\">{{option}}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n @if (column.type == 'boolean') {\n <mat-checkbox (click)=\"$event.stopPropagation()\" color=\"primary\" [(ngModel)]=\"row[column.field]\"></mat-checkbox>\n }\n }\n @if (!cellEditingTemplateRef && cellEditing[i +'_'+column.field]) {\n @if (column.type == 'number') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"number\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'string') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"text\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'textarea') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <textarea matInput rows=\"3\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\"></textarea>\n </mat-form-field>\n }\n @if (column.type == 'date') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"date\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'datepicker') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput [matDatepicker]=\"cellPicker\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n <mat-datepicker-toggle matIconSuffix [for]=\"cellPicker\"></mat-datepicker-toggle>\n <mat-datepicker #cellPicker></mat-datepicker>\n </mat-form-field>\n }\n @if (column.type == 'selection') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-select [value]=\"rowDataTemp['e'+i][column.field]\"\n [(ngModel)]=\"rowDataTemp['e'+i][column.field]\">\n @for (option of column.options; track option) {\n <mat-option [value]=\"option\">{{option}}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n @if (column.type == 'boolean') {\n <mat-checkbox (click)=\"$event.stopPropagation()\" color=\"primary\" [(ngModel)]=\"row[column.field]\"></mat-checkbox>\n }\n }\n </div>\n }\n </td>\n @if (showFooterRow) {\n <td mat-footer-cell *matFooterCellDef> {{column.footerText}} </td>\n }\n </div>\n }\n <ng-container matColumnDef=\"edit\" stickyEnd=\"false\">\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\n class=\"action-column-cells\"> Edit </th>\n <td mat-cell *matCellDef=\"let row; let i = dataIndex\" class=\"inline-edit-column-cell\">\n <!-- Edit disabled in pinned top table -->\n </td>\n <td mat-footer-cell *matFooterCellDef> edit </td>\n </ng-container>\n <ng-container matColumnDef=\"popup\" stickyEnd=\"false\">\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\n class=\"action-column-cells\"> Popup\n </th>\n <td mat-cell *matCellDef=\"let row; let i = index\">\n <!-- Popup edit disabled in pinned top table -->\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n \n <ng-container matColumnDef=\"delete\">\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\n class=\"action-column-cells\"> Delete\n </th>\n <td mat-cell *matCellDef=\"let row;let i=dataIndex\">\n <mat-icon (click)=\"deleteRow(row,i)\" aria-hidden=\"false\" aria-label=\"Example home icon\"\n fontIcon=\"delete\">\n </mat-icon>\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n \n <ng-container matColumnDef=\"hide\" stickyEnd=\"false\">\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\n class=\"action-column-cells\"> Hide\n </th>\n <td mat-cell *matCellDef=\"let row;let i=dataIndex\">\n <button mat-icon-button (click)=\"toggleRowHide(i)\" \n [matTooltip]=\"isRowHidden(i) ? 'Unhide Row' : 'Hide Row'\"\n matTooltipPosition=\"above\">\n <mat-icon [color]=\"isRowHidden(i) ? 'primary' : ''\" aria-hidden=\"false\">\n {{ isRowHidden(i) ? 'visibility_off' : 'visibility' }}\n </mat-icon>\n </button>\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n \n <ng-container matColumnDef=\"pin\" stickyEnd=\"false\">\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\n class=\"action-column-cells\"> Pinning\n </th>\n <td mat-cell *matCellDef=\"let row;let i=dataIndex\">\n <button mat-icon-button \n [matMenuTriggerFor]=\"pinMenu\"\n (click)=\"openRowPinMenu($event, row)\"\n [matTooltip]=\"getRowPinPosition(row) ? 'Pinned ' + getRowPinPosition(row) : 'Pin Row'\"\n matTooltipPosition=\"above\">\n <mat-icon [color]=\"isRowPinned(row) ? 'primary' : ''\" aria-hidden=\"false\">\n {{ isRowPinned(row) ? 'push_pin' : 'push_pin' }}\n </mat-icon>\n </button>\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n \n <!-- Expanded Content Column - The detail row is made up of this one column that spans across all columns -->\n @if (expandRows) {\n <ng-container matColumnDef=\"expandedDetail\">\n <td mat-cell *matCellDef=\"let element;let i=dataIndex \"\n [attr.colspan]=\"columnsToDisplayWithExpand.length\">\n <div class=\"example-element-detail\"\n [@detailExpand]=\"element == expandedElement ? 'expanded' : 'collapsed'\">\n @if (expansionTemplateRef) {\n <ng-container [ngTemplateOutlet]=\"expansionTemplateRef\"\n [ngTemplateOutletContext]=\"{$explicit:element,row:element,index:i}\">\n </ng-container>\n }\n </div>\n </td>\n </ng-container>\n }\n <!-- Column group headers -->\n @if (columnGroups.length > 0) {\n @for (group of columnGroups; track group.name) {\n <ng-container [matColumnDef]=\"'group-' + group.name\">\n <th mat-header-cell *matHeaderCellDef [attr.colspan]=\"group.colspan || group.columns.length\" \n class=\"group-header-cell\">\n <div class=\"group-header-content\">\n <span class=\"group-label\">{{group.label}}</span>\n </div>\n </th>\n </ng-container>\n }\n <!-- Empty header cells for ungrouped columns -->\n @for (column of columnsArray; track column.field) {\n <ng-container [matColumnDef]=\"'ungrouped-' + column.field\">\n <th mat-header-cell *matHeaderCellDef class=\"group-header-cell ungrouped-header-cell\">\n </th>\n </ng-container>\n }\n <!-- Empty header cells for action columns to fill space in group header -->\n <ng-container [matColumnDef]=\"'ungrouped-select'\">\n <th mat-header-cell *matHeaderCellDef class=\"group-header-cell ungrouped-header-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'ungrouped-edit'\">\n <th mat-header-cell *matHeaderCellDef class=\"group-header-cell ungrouped-header-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'ungrouped-popup'\">\n <th mat-header-cell *matHeaderCellDef class=\"group-header-cell ungrouped-header-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'ungrouped-delete'\">\n <th mat-header-cell *matHeaderCellDef class=\"group-header-cell ungrouped-header-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'ungrouped-freeze'\">\n <th mat-header-cell *matHeaderCellDef class=\"group-header-cell ungrouped-header-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'ungrouped-hide'\">\n <th mat-header-cell *matHeaderCellDef class=\"group-header-cell ungrouped-header-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'ungrouped-pin'\">\n <th mat-header-cell *matHeaderCellDef class=\"group-header-cell ungrouped-header-cell\"></th>\n </ng-container>\n }\n <!-- Filter row columns for data columns -->\n @for (ids of headersFiltersIds; track ids; let i = $index) {\n <ng-container [matColumnDef]=\"ids\" [sticky]=\"columnsArray[$index].pinned === 'left'\" [stickyEnd]=\"columnsArray[$index].pinned === 'right'\">\n <th mat-header-cell *matHeaderCellDef [style.minWidth]=\"columnsArray[$index].width\" [style.maxWidth]=\"columnsArray[$index].maxWidth?columnsArray[$index].maxWidth:columnsArray[$index].width\"\n [style.minWidth]=\"columnsArray[$index].minWidth\" >\n <div style=\"display: block; width: 100%;\" class=\"filters-container\" [class.animate]=\"toggleFilters\">\n <app-filter-columns-component style=\"display: block; width: 100%;\" [obj]=\"columnsArray[returnIndex(ids)]\"\n (filterOutput)=\"applyColumnFilter($event,columnsArray[returnIndex(ids)])\"></app-filter-columns-component>\n </div>\n </th>\n </ng-container>\n }\n <!-- Empty filter cells for action columns -->\n <ng-container [matColumnDef]=\"'filter-select'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'filter-edit'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'filter-popup'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'filter-delete'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'filter-freeze'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'filter-hide'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'filter-pin'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n @if (columnGroups.length > 0) {\n <tr mat-header-row *matHeaderRowDef=\"getGroupedColumns(); sticky: stickyHeader\" class=\"mat-mdc-header-row group-header-row\"></tr>\n }\n <tr mat-header-row *matHeaderRowDef=\" getDisplayedColumns(); sticky: stickyHeader\" class=\"mat-mdc-header-row\"></tr>\n <tr style=\"height: 0px;\" mat-header-row class=\"no-default-height\" *matHeaderRowDef=\"getFilterColumns()\">\n </tr>\n \n <tr mat-row *matRowDef=\"let row; columns:getDisplayedColumns(); let i=dataIndex; \" \n class=\"mat-mdc-row data-row\"\n [ngClass]=\"{\n 'data-row':expandRows,\n 'stripedRows':(stripedRows && i % 2 == 1),\n 'hoverClass':rowHover, \n 'hidden':(hiddenCtrl.isSelected(row) && hideRows) || isRowHidden(i),\n 'example-expanded-row':expandedElement === row,\n 'pinned-row': isRowPinned(row),\n 'mat-row-sticky-top': isRowPinnedTop(row),\n 'mat-row-sticky-bottom': isRowPinnedBottom(row)\n }\"\n (click)=\"expandRow(row, row !== expandedElement,i)\">\n </tr>\n \n @if (expandRows) {\n <tr mat-row *matRowDef=\"let row; columns: ['expandedDetail']; let i=dataIndex\"\n class=\"example-detail-row\"\n [ngClass]=\"{'hidden': isRowHidden(i)}\">\n </tr>\n }\n @if (showFooterRow) {\n <tr mat-footer-row *matFooterRowDef=\"getDisplayedColumns(); sticky: stickyFooter\"></tr>\n }\n </table>\n </div>\n \n <table mat-table #matTable #MyTable [id]=\"'matTableExt'+tableID\" [dataSource]=\"dataSource\" matSort cdkDropList\n cdkDropListOrientation=\"horizontal\" multiTemplateDataRows (cdkDropListDropped)=\"onDrop($event)\"\n (click)=\"saveCellEditing()\" [style.width]=\"scrollbarH?'max-content':'100%'\" \n [class]=\"'mat-mdc-table' + (tableClassName ? ' ' + tableClassName : '')\">\n \n <!-- Row selection column -->\n <ng-container matColumnDef=\"select\">\n <th mat-header-cell *matHeaderCellDef cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"!dndColumns\">\n <mat-checkbox (change)=\"$event ? toggleAllRows() : null\"\n [checked]=\"selection.hasValue() && isAllSelected()\"\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\" [aria-label]=\"checkboxLabel()\">\n </mat-checkbox>\n </th>\n <td mat-cell *matCellDef=\"let row;let i = dataIndex\">\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? setSelectedRows(row,i) : null\"\n [checked]=\"selection.isSelected(row)\" [aria-label]=\"checkboxLabel(row)\">\n </mat-checkbox>\n </td>\n <ng-container *ngIf=\"showFooterRow\">\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n </ng-container>\n <!--dynamic columns are being generated here-->\n @for (column of columnsArray; track column.field + '_' + column.pinned; let i = $index) {\n <div matColumnDef=\"{{column['field']}}\" [sticky]=\"column.pinned === 'left'\" [stickyEnd]=\"column.pinned === 'right'\">\n <th mat-header-cell *matHeaderCellDef [style.minWidth]=\"column.width\" [style.maxWidth]=\"column.maxWidth?column.maxWidth:column.width\"\n [style.minWidth]=\"column.minWidth\" cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"!dndColumns\"\n [columnsResizable]=\"columnResizable\" [index]=\"i\" class=\"mat-mdc-header-cell\"\n [mat-sort-header]=\"column.field\" [disabled]=\"!sorting || column.disabled === true\">\n \n @if (column.headerTemplate || headerTemplateRef) {\n <ng-template [ngTemplateOutlet]=\"column.headerTemplate || headerTemplateRef\"\n [ngTemplateOutletContext]=\"{data:column}\"></ng-template>\n }\n @if (!headerTemplateRef && !column.headerTemplate) {\n <span matTooltip=\"{{column.headerTooltip?.value}}\"\n [matTooltipPosition]=\"column?.headerTooltip?.tooltipPosition!\"\n [class.disabled]=\"!sorting || column.disabled === true\">{{column.header}}</span>\n }\n </th>\n <td mat-cell *matCellDef=\"let row ;let i=dataIndex\" class=\"mat-mdc-cell\">\n @if (!row.editable && !cellEditing[i +'_'+column.field]) {\n <div (dblclick)=\"cellEditing[i +'_'+column.field] = inCellEditing;setCellData(row,i)\"\n (click)=\"cellPopupEditing ? openCellPopupDialog(row, column, i) : null\"\n [style.cursor]=\"cellPopupEditing ? 'pointer' : 'default'\"\n matTooltip=\"{{column.cellTooltip?.value}}\"\n [matTooltipPosition]=\"column?.cellTooltip?.tooltipPosition!\">\n @if (!cellTemplateRef && !column?.cellTemplate && !cellTemplateRefMap[column.field]) {\n <span>{{row[column.field]}}</span>\n }\n @if (cellTemplateRefMap[column.field]) {\n <ng-container [ngTemplateOutlet]=\"cellTemplateRefMap[column.field]\"\n [ngTemplateOutletContext]=\"{row:row,column:column,index:i}\">\n </ng-container>\n }\n @if (cellTemplateRef && column.cellTemplate && !cellTemplateRefMap[column.field]) {\n <ng-container [ngTemplateOutlet]=\"column.cellTemplate\"\n [ngTemplateOutletContext]=\"{row:row,column:column,index:i}\">\n </ng-container>\n }\n @if (!cellTemplateRef && column.cellTemplate && !cellTemplateRefMap[column.field]) {\n <ng-container [ngTemplateOutlet]=\"column.cellTemplate\"\n [ngTemplateOutletContext]=\"{row:row,column:column,index:i}\">\n </ng-container>\n }\n @if (cellTemplateRef && !column.cellTemplate && !cellTemplateRefMap[column.field]) {\n <ng-container [ngTemplateOutlet]=\"cellTemplateRef\"\n [ngTemplateOutletContext]=\"{row:row,column:column,index:i}\">\n </ng-container>\n }\n </div>\n }\n @if (row.editable || cellEditing[i +'_'+column.field]) {\n <div (click)=\"$event.stopPropagation()\">\n @if (inlineEditingTemplateRef && !cellEditing[i +'_'+column.field]) {\n <ng-container [ngTemplateOutlet]=\"inlineEditingTemplateRef\"\n [ngTemplateOutletContext]=\"{data:getInlineEditingData(row,i,column)}\"></ng-container>\n }\n @if (cellEditingTemplateRef && !(row.editable)) {\n <ng-container [ngTemplateOutlet]=\"cellEditingTemplateRef\"\n [ngTemplateOutletContext]=\"{data:getInlineEditingData(row,i,column)}\"></ng-container>\n }\n @if (!inlineEditingTemplateRef && (row.editable) && rowDataTemp['e'+i]) {\n @if (column.type == 'number') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"number\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'string') {\n <mat-form-field style=\"width: 100%;\" appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"text\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'textarea') {\n <mat-form-field style=\"width: 100%;\" appearance=\"outline\" class=\"inline-editing-field\">\n <textarea matInput rows=\"3\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\"></textarea>\n </mat-form-field>\n }\n @if (column.type == 'date') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"date\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'datepicker') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput [matDatepicker]=\"inlinePicker\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n <mat-datepicker-toggle matIconSuffix [for]=\"inlinePicker\"></mat-datepicker-toggle>\n <mat-datepicker #inlinePicker></mat-datepicker>\n </mat-form-field>\n }\n @if (column.type == 'selection') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-select [value]=\"rowDataTemp['e'+i][column.field]\"\n [(ngModel)]=\"rowDataTemp['e'+i][column.field]\">\n @for (option of column.options; track option) {\n <mat-option [value]=\"option\">{{option}}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n @if (column.type == 'boolean') {\n <mat-checkbox (click)=\"$event.stopPropagation()\" color=\"primary\" [(ngModel)]=\"row[column.field]\"></mat-checkbox>\n }\n }\n @if (!cellEditingTemplateRef && cellEditing[i +'_'+column.field]) {\n @if (column.type == 'number') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"number\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'string') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"text\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'textarea') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <textarea matInput rows=\"3\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\"></textarea>\n </mat-form-field>\n }\n @if (column.type == 'date') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"date\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'datepicker') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput [matDatepicker]=\"cellPicker\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n <mat-datepicker-toggle matIconSuffix [for]=\"cellPicker\"></mat-datepicker-toggle>\n <mat-datepicker #cellPicker></mat-datepicker>\n </mat-form-field>\n }\n @if (column.type == 'selection') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-select [value]=\"rowDataTemp['e'+i][column.field]\"\n [(ngModel)]=\"rowDataTemp['e'+i][column.field]\">\n @for (option of column.options; track option) {\n <mat-option [value]=\"option\">{{option}}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n @if (column.type == 'boolean') {\n <mat-checkbox (click)=\"$event.stopPropagation()\" color=\"primary\" [(ngModel)]=\"row[column.field]\"></mat-checkbox>\n }\n }\n </div>\n }\n </td>\n @if (showFooterRow) {\n <td mat-footer-cell *matFooterCellDef> {{column.footerText}} </td>\n }\n </div>\n }\n <ng-container matColumnDef=\"edit\" stickyEnd=\"false\">\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\n class=\"action-column-cells\"> Edit </th>\n <td mat-cell *matCellDef=\"let row; let i = dataIndex\" class=\"inline-edit-column-cell\">\n @if (!row.editable && !row.editmodal) {\n <mat-icon class=\"edit-column-icons\" aria-hidden=\"false\"\n (click)=\"enableInlineEditing(row,i)\" fontIcon=\"edit_note\">\n </mat-icon>\n }\n @if (row.editable && !row.editmodal) {\n <div class=\"inline-editing-controls\">\n <mat-icon class=\"edit-column-icons\" aria-hidden=\"false\" (click)=\"saveInlineEditing(row,i)\"\n fontIcon=\"done\"></mat-icon>\n <mat-icon class=\"edit-column-icons\" aria-hidden=\"false\" (click)=\"cancelInlineEditing(row,i)\"\n fontIcon=\"close\"></mat-icon>\n </div>\n }\n </td>\n <td mat-footer-cell *matFooterCellDef> edit </td>\n </ng-container>\n <ng-container matColumnDef=\"popup\" stickyEnd=\"false\">\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\n class=\"action-column-cells\"> Popup\n </th>\n <td mat-cell *matCellDef=\"let row; let i = index\">\n <mat-icon aria-hidden=\"false\" (click)=\"openEditingDialog(row)\" fontIcon=\"edit\">\n </mat-icon>\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n \n <ng-container matColumnDef=\"delete\">\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\n class=\"action-column-cells\"> Delete\n </th>\n <td mat-cell *matCellDef=\"let row;let i=dataIndex\">\n <mat-icon (click)=\"deleteRow(row,i)\" aria-hidden=\"false\" aria-label=\"Example home icon\"\n fontIcon=\"delete\">\n </mat-icon>\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n \n <ng-container matColumnDef=\"hide\" stickyEnd=\"false\">\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\n class=\"action-column-cells\"> Hide\n </th>\n <td mat-cell *matCellDef=\"let row;let i=dataIndex\">\n <button mat-icon-button (click)=\"toggleRowHide(i)\" \n [matTooltip]=\"isRowHidden(i) ? 'Unhide Row' : 'Hide Row'\"\n matTooltipPosition=\"above\">\n <mat-icon [color]=\"isRowHidden(i) ? 'primary' : ''\" aria-hidden=\"false\">\n {{ isRowHidden(i) ? 'visibility_off' : 'visibility' }}\n </mat-icon>\n </button>\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n \n <ng-container matColumnDef=\"pin\" stickyEnd=\"false\">\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\n class=\"action-column-cells\"> Pin\n </th>\n <td mat-cell *matCellDef=\"let row;let i=dataIndex\">\n <button mat-icon-button \n [matMenuTriggerFor]=\"pinMenu\"\n (click)=\"openRowPinMenu($event, row)\"\n [matTooltip]=\"getRowPinPosition(row) ? 'Pinned ' + getRowPinPosition(row) : 'Pin Row'\"\n matTooltipPosition=\"above\">\n <mat-icon [color]=\"isRowPinned(row) ? 'primary' : ''\" aria-hidden=\"false\">\n {{ isRowPinned(row) ? 'push_pin' : 'push_pin' }}\n </mat-icon>\n </button>\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n \n <!-- Expanded Content Column - The detail row is made up of this one column that spans across all columns -->\n @if (expandRows) {\n <ng-container matColumnDef=\"expandedDetail\">\n <td mat-cell *matCellDef=\"let element;let i=dataIndex \"\n [attr.colspan]=\"columnsToDisplayWithExpand.length\">\n <div class=\"example-element-detail\"\n [@detailExpand]=\"element == expandedElement ? 'expanded' : 'collapsed'\">\n @if (expansionTemplateRef) {\n <ng-container [ngTemplateOutlet]=\"expansionTemplateRef\"\n [ngTemplateOutletContext]=\"{$explicit:element,row:element,index:i}\">\n </ng-container>\n }\n </div>\n </td>\n </ng-container>\n }\n <!-- Column group headers -->\n <!-- @if (columnGroups.length > 0) {\n @for (group of columnGroups; track group.name) {\n <ng-container [matColumnDef]=\"'group-' + group.name\">\n <th mat-header-cell *matHeaderCellDef [attr.colspan]=\"group.colspan || group.columns.length\" \n class=\"group-header-cell\">\n <div class=\"group-header-content\">\n <span class=\"group-label\">{{group.label}}</span>\n </div>\n </th>\n </ng-container>\n }\n @for (column of columnsArray; track column.field) {\n <ng-container [matColumnDef]=\"'ungrouped-' + column.field\">\n <th mat-header-cell *matHeaderCellDef class=\"group-header-cell ungrouped-header-cell\">\n </th>\n </ng-container>\n }\n } -->\n <!-- @if (columnGroups.length > 0) {\n <tr mat-header-row *matHeaderRowDef=\"getGroupedColumns(); sticky: stickyHeader\" class=\"mat-mdc-header-row group-header-row\"></tr>\n } -->\n <tr style=\"display:none\" mat-header-row *matHeaderRowDef=\" getDisplayedColumns(); sticky: stickyHeader\" class=\"mat-mdc-header-row\"></tr>\n \n <!-- All Data Rows (with dynamic pinning classes) -->\n <!-- <tr mat-row *matRowDef=\"let row; columns:getDisplayedColumns(); let i=dataIndex;\" \n class=\"mat-mdc-row data-row\"\n [ngClass]=\"{\n 'data-row':expandRows,\n 'stripedRows':(stripedRows && i % 2 == 1),\n 'hoverClass':rowHover, \n 'hidden':(hiddenCtrl.isSelected(row) && hideRows) || isRowHidden(i),\n 'example-expanded-row':expandedElement === row,\n 'pinned-row': isRowPinned(row),\n 'pinned-top-row': isRowPinnedTop(row),\n 'pinned-bottom-row': isRowPinnedBottom(row)\n }\"\n (click)=\"expandRow(row, row !== expandedElement,i)\">\n </tr> -->\n <tr mat-row *matRowDef=\"let row; columns:getDisplayedColumns(); let i=dataIndex; \" \n class=\"mat-mdc-row data-row\"\n [ngClass]=\"{\n 'data-row':expandRows,\n 'stripedRows':(stripedRows && i % 2 == 1),\n 'hoverClass':rowHover, \n 'hidden':(hiddenCtrl.isSelected(row) && hideRows) || isRowHidden(i),\n 'example-expanded-row':expandedElement === row,\n 'pinned-row': isRowPinned(row),\n 'mat-row-sticky-top': isRowPinnedTop(row),\n 'mat-row-sticky-bottom': isRowPinnedBottom(row)\n }\"\n (click)=\"expandRow(row, row !== expandedElement,i)\">\n </tr>\n <!-- <tr mat-header-row *matHeaderRowDef=\"let row; columns:getDisplayedColumns(); let i=dataIndex; when: isRowPinnedTop(row)\" \n class=\"mat-mdc-row data-row\"\n class=\"mat-mdc-header-row\"\n [ngClass]=\"{\n 'data-row':expandRows,\n 'stripedRows':(stripedRows && i % 2 == 1),\n 'hoverClass':rowHover, \n 'hidden':(hiddenCtrl.isSelected(row) && hideRows) || isRowHidden(i),\n 'example-expanded-row':expandedElement === row,\n 'pinned-row': isRowPinned(row),\n 'pinned-top-row': isRowPinnedTop(row),\n 'pinned-bottom-row': isRowPinnedBottom(row)\n }\"\n (click)=\"expandRow(row, row !== expandedElement,i)\">\n </tr> -->\n \n @if (expandRows) {\n <tr mat-row *matRowDef=\"let row; columns: ['expandedDetail']; let i=dataIndex\"\n class=\"example-detail-row\"\n [ngClass]=\"{'hidden': isRowHidden(i)}\">\n </tr>\n }\n @if (showFooterRow) {\n <tr mat-footer-row *matFooterRowDef=\"getDisplayedColumns(); sticky: stickyFooter\"></tr>\n }\n </table>\n @if (pinnedBtmDataSource && pinnedBtmDataSource.data.length > 0) {\n <div [style.max-height]=\"bottomPinnedMaxHeight\" [style.overflow]=\"bottomPinnedMaxHeight ? 'auto' : 'visible'\" \n [style.position]=\"'sticky'\" [style.bottom]=\"'0'\" [style.z-index]=\"'111'\">\n <table style=\"width: 100%;\" mat-table #matTable #MyTable [id]=\"'matTableExtBtm'+tableID\" [dataSource]=\"pinnedBtmDataSource\" matSort cdkDropList\n cdkDropListOrientation=\"horizontal\" multiTemplateDataRows (cdkDropListDropped)=\"onDrop($event)\"\n (click)=\"saveCellEditing()\" [style.width]=\"scrollbarH?'max-content':'100%'\" \n [class]=\"'mat-mdc-table' + (tableClassName ? ' ' + tableClassName : '')\">\n \n <!-- Row selection column -->\n <ng-container matColumnDef=\"select\">\n <th mat-header-cell *matHeaderCellDef cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"!dndColumns\">\n <mat-checkbox (change)=\"$event ? toggleAllRows() : null\"\n [checked]=\"selection.hasValue() && isAllSelected()\"\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\" [aria-label]=\"checkboxLabel()\">\n </mat-checkbox>\n </th>\n <td mat-cell *matCellDef=\"let row;let i = dataIndex\">\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? setSelectedRows(row,i) : null\"\n [checked]=\"selection.isSelected(row)\" [aria-label]=\"checkboxLabel(row)\">\n </mat-checkbox>\n </td>\n <ng-container *ngIf=\"showFooterRow\">\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n </ng-container>\n <!--dynamic columns are being generated here-->\n @for (column of columnsArray; track column.field + '_' + column.pinned; let i = $index) {\n <div matColumnDef=\"{{column['field']}}\" [sticky]=\"column.pinned === 'left'\" [stickyEnd]=\"column.pinned === 'right'\">\n <th mat-header-cell *matHeaderCellDef [style.minWidth]=\"column.width\" [style.maxWidth]=\"column.maxWidth?column.maxWidth:column.width\"\n [style.minWidth]=\"column.minWidth\" cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"!dndColumns\"\n [columnsResizable]=\"columnResizable\" [index]=\"i\" class=\"mat-mdc-header-cell\"\n [mat-sort-header]=\"column.field\" [disabled]=\"!sorting || column.disabled === true\">\n \n @if (column.headerTemplate || headerTemplateRef) {\n <ng-template [ngTemplateOutlet]=\"column.headerTemplate || headerTemplateRef\"\n [ngTemplateOutletContext]=\"{data:column}\"></ng-template>\n }\n @if (!headerTemplateRef && !column.headerTemplate) {\n <span matTooltip=\"{{column.headerTooltip?.value}}\"\n [matTooltipPosition]=\"column?.headerTooltip?.tooltipPosition!\"\n [class.disabled]=\"!sorting || column.disabled === true\">{{column.header}}</span>\n }\n </th>\n <td mat-cell *matCellDef=\"let row ;let i=dataIndex\" class=\"mat-mdc-cell\">\n @if (!row.editable && !cellEditing[i +'_'+column.field]) {\n <div [style.cursor]=\"'default'\"\n matTooltip=\"{{column.cellTooltip?.value}}\"\n [matTooltipPosition]=\"column?.cellTooltip?.tooltipPosition!\">\n @if (!cellTemplateRef && !column?.cellTemplate && !cellTemplateRefMap[column.field]) {\n <span>{{row[column.field]}}</span>\n }\n @if (cellTemplateRefMap[column.field]) {\n <ng-container [ngTemplateOutlet]=\"cellTemplateRefMap[column.field]\"\n [ngTemplateOutletContext]=\"{row:row,column:column,index:i}\">\n </ng-container>\n }\n @if (cellTemplateRef && column.cellTemplate && !cellTemplateRefMap[column.field]) {\n <ng-container [ngTemplateOutlet]=\"column.cellTemplate\"\n [ngTemplateOutletContext]=\"{row:row,column:column,index:i}\">\n </ng-container>\n }\n @if (!cellTemplateRef && column.cellTemplate && !cellTemplateRefMap[column.field]) {\n <ng-container [ngTemplateOutlet]=\"column.cellTemplate\"\n [ngTemplateOutletContext]=\"{row:row,column:column,index:i}\">\n </ng-container>\n }\n @if (cellTemplateRef && !column.cellTemplate && !cellTemplateRefMap[column.field]) {\n <ng-container [ngTemplateOutlet]=\"cellTemplateRef\"\n [ngTemplateOutletContext]=\"{row:row,column:column,index:i}\">\n </ng-container>\n }\n </div>\n }\n @if (row.editable || cellEditing[i +'_'+column.field]) {\n <div (click)=\"$event.stopPropagation()\">\n @if (inlineEditingTemplateRef && !cellEditing[i +'_'+column.field]) {\n <ng-container [ngTemplateOutlet]=\"inlineEditingTemplateRef\"\n [ngTemplateOutletContext]=\"{data:getInlineEditingData(row,i,column)}\"></ng-container>\n }\n @if (cellEditingTemplateRef && !(row.editable)) {\n <ng-container [ngTemplateOutlet]=\"cellEditingTemplateRef\"\n [ngTemplateOutletContext]=\"{data:getInlineEditingData(row,i,column)}\"></ng-container>\n }\n @if (!inlineEditingTemplateRef && (row.editable) && rowDataTemp['e'+i]) {\n @if (column.type == 'number') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"number\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'string') {\n <mat-form-field style=\"width: 100%;\" appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"text\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'textarea') {\n <mat-form-field style=\"width: 100%;\" appearance=\"outline\" class=\"inline-editing-field\">\n <textarea matInput rows=\"3\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\"></textarea>\n </mat-form-field>\n }\n @if (column.type == 'date') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"date\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'datepicker') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput [matDatepicker]=\"inlinePicker\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n <mat-datepicker-toggle matIconSuffix [for]=\"inlinePicker\"></mat-datepicker-toggle>\n <mat-datepicker #inlinePicker></mat-datepicker>\n </mat-form-field>\n }\n @if (column.type == 'selection') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-select [value]=\"rowDataTemp['e'+i][column.field]\"\n [(ngModel)]=\"rowDataTemp['e'+i][column.field]\">\n @for (option of column.options; track option) {\n <mat-option [value]=\"option\">{{option}}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n @if (column.type == 'boolean') {\n <mat-checkbox (click)=\"$event.stopPropagation()\" color=\"primary\" [(ngModel)]=\"row[column.field]\"></mat-checkbox>\n }\n }\n @if (!cellEditingTemplateRef && cellEditing[i +'_'+column.field]) {\n @if (column.type == 'number') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"number\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'string') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"text\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'textarea') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <textarea matInput rows=\"3\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\"></textarea>\n </mat-form-field>\n }\n @if (column.type == 'date') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"date\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'datepicker') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput [matDatepicker]=\"cellPicker\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n <mat-datepicker-toggle matIconSuffix [for]=\"cellPicker\"></mat-datepicker-toggle>\n <mat-datepicker #cellPicker></mat-datepicker>\n </mat-form-field>\n }\n @if (column.type == 'selection') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-select [value]=\"rowDataTemp['e'+i][column.field]\"\n [(ngModel)]=\"rowDataTemp['e'+i][column.field]\">\n @for (option of column.options; track option) {\n <mat-option [value]=\"option\">{{option}}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n @if (column.type == 'boolean') {\n <mat-checkbox (click)=\"$event.stopPropagation()\" color=\"primary\" [(ngModel)]=\"row[column.field]\"></mat-checkbox>\n }\n }\n </div>\n }\n </td>\n @if (showFooterRow) {\n <td mat-footer-cell *matFooterCellDef> {{column.footerText}} </td>\n }\n </div>\n }\n <ng-container matColumnDef=\"edit\" stickyEnd=\"false\">\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\n class=\"action-column-cells\"> Edit </th>\n <td mat-cell *matCellDef=\"let row; let i = dataIndex\" class=\"inline-edit-column-cell\">\n <!-- Edit disabled in pinned bottom table -->\n </td>\n <td mat-footer-cell *matFooterCellDef> edit </td>\n </ng-container>\n <ng-container matColumnDef=\"popup\" stickyEnd=\"false\">\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\n class=\"action-column-cells\"> Popup\n </th>\n <td mat-cell *matCellDef=\"let row; let i = index\">\n <!-- Popup edit disabled in pinned bottom table -->\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n \n <ng-container matColumnDef=\"delete\">\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\n class=\"action-column-cells\"> Delete\n </th>\n <td mat-cell *matCellDef=\"let row;let i=dataIndex\">\n <mat-icon (click)=\"deleteRow(row,i)\" aria-hidden=\"false\" aria-label=\"Example home icon\"\n fontIcon=\"delete\">\n </mat-icon>\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n \n <ng-container matColumnDef=\"hide\" stickyEnd=\"false\">\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\n class=\"action-column-cells\"> Hide\n </th>\n <td mat-cell *matCellDef=\"let row;let i=dataIndex\">\n <button mat-icon-button (click)=\"toggleRowHide(i)\" \n [matTooltip]=\"isRowHidden(i) ? 'Unhide Row' : 'Hide Row'\"\n matTooltipPosition=\"above\">\n <mat-icon [color]=\"isRowHidden(i) ? 'primary' : ''\" aria-hidden=\"false\">\n {{ isRowHidden(i) ? 'visibility_off' : 'visibility' }}\n </mat-icon>\n </button>\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n \n <ng-container matColumnDef=\"pin\" stickyEnd=\"false\">\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\n class=\"action-column-cells\"> Pin\n </th>\n <td mat-cell *matCellDef=\"let row;let i=dataIndex\">\n <button mat-icon-button \n [matMenuTriggerFor]=\"pinMenu\"\n (click)=\"openRowPinMenu($event, row)\"\n [matTooltip]=\"getRowPinPosition(row) ? 'Pinned ' + getRowPinPosition(row) : 'Pin Row'\"\n matTooltipPosition=\"above\">\n <mat-icon [color]=\"isRowPinned(row) ? 'primary' : ''\" aria-hidden=\"false\">\n {{ isRowPinned(row) ? 'push_pin' : 'push_pin' }}\n </mat-icon>\n </button>\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n \n <!-- Expanded Content Column - The detail row is made up of this one column that spans across all columns -->\n @if (expandRows) {\n <ng-container matColumnDef=\"expandedDetail\">\n <td mat-cell *matCellDef=\"let element;let i=dataIndex \"\n [attr.colspan]=\"columnsToDisplayWithExpand.length\">\n <div class=\"example-element-detail\"\n [@detailExpand]=\"element == expandedElement ? 'expanded' : 'collapsed'\">\n @if (expansionTemplateRef) {\n <ng-container [ngTemplateOutlet]=\"expansionTemplateRef\"\n [ngTemplateOutletContext]=\"{$explicit:element,row:element,index:i}\">\n </ng-container>\n }\n </div>\n </td>\n </ng-container>\n }\n <!-- Column group headers -->\n @if (columnGroups.length > 0) {\n @for (group of columnGroups; track group.name) {\n <ng-container [matColumnDef]=\"'group-' + group.name\">\n <th mat-header-cell *matHeaderCellDef [attr.colspan]=\"group.colspan || group.columns.length\" \n class=\"group-header-cell\">\n <div class=\"group-header-content\">\n <span class=\"group-label\">{{group.label}}</span>\n </div>\n </th>\n </ng-container>\n }\n <!-- Empty header cells for ungrouped columns -->\n @for (column of columnsArray; track column.field) {\n <ng-container [matColumnDef]=\"'ungrouped-' + column.field\">\n <th mat-header-cell *matHeaderCellDef class=\"group-header-cell ungrouped-header-cell\">\n </th>\n </ng-container>\n }\n }\n <!-- Empty filter cells for action columns -->\n <ng-container [matColumnDef]=\"'filter-select'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'filter-edit'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'filter-popup'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'filter-delete'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'filter-freeze'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'filter-hide'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'filter-pin'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n @if (columnGroups.length > 0) {\n <tr mat-header-row *matHeaderRowDef=\"getGroupedColumns(); sticky: stickyHeader\" class=\"mat-mdc-header-row group-header-row\"></tr>\n }\n <!-- <tr mat-header-row *matHeaderRowDef=\" getDisplayedColumns(); sticky: stickyHeader\" class=\"mat-mdc-header-row\"></tr> -->\n <tr style=\"display:none\" mat-header-row *matHeaderRowDef=\" getDisplayedColumns(); sticky: stickyHeader\" class=\"mat-mdc-header-row\"></tr>\n \n <!-- All Data Rows (with dynamic pinning classes) -->\n <!-- <tr mat-row *matRowDef=\"let row; columns:getDisplayedColumns(); let i=dataIndex;\" \n class=\"mat-mdc-row data-row\"\n [ngClass]=\"{\n 'data-row':expandRows,\n 'stripedRows':(stripedRows && i % 2 == 1),\n 'hoverClass':rowHover, \n 'hidden':(hiddenCtrl.isSelected(row) && hideRows) || isRowHidden(i),\n 'example-expanded-row':expandedElement === row,\n 'pinned-row': isRowPinned(row),\n 'pinned-top-row': isRowPinnedTop(row),\n 'pinned-bottom-row': isRowPinnedBottom(row)\n }\"\n (click)=\"expandRow(row, row !== expandedElement,i)\">\n </tr> -->\n <tr mat-row *matRowDef=\"let row; columns:getDisplayedColumns(); let i=dataIndex; \" \n class=\"mat-mdc-row data-row\"\n [ngClass]=\"{\n 'data-row':expandRows,\n 'stripedRows':(stripedRows && i % 2 == 1),\n 'hoverClass':rowHover, \n 'hidden':(hiddenCtrl.isSelected(row) && hideRows) || isRowHidden(i),\n 'example-expanded-row':expandedElement === row,\n 'pinned-row': isRowPinned(row),\n 'mat-row-sticky-top': isRowPinnedTop(row),\n 'mat-row-sticky-bottom': isRowPinnedBottom(row)\n }\"\n (click)=\"expandRow(row, row !== expandedElement,i)\">\n </tr>\n <!-- <tr mat-header-row *matHeaderRowDef=\"let row; columns:getDisplayedColumns(); let i=dataIndex; when: isRowPinnedTop(row)\" \n class=\"mat-mdc-row data-row\"\n class=\"mat-mdc-header-row\"\n [ngClass]=\"{\n 'data-row':expandRows,\n 'stripedRows':(stripedRows && i % 2 == 1),\n 'hoverClass':rowHover, \n 'hidden':(hiddenCtrl.isSelected(row) && hideRows) || isRowHidden(i),\n 'example-expanded-row':expandedElement === row,\n 'pinned-row': isRowPinned(row),\n 'pinned-top-row': isRowPinnedTop(row),\n 'pinned-bottom-row': isRowPinnedBottom(row)\n }\"\n (click)=\"expandRow(row, row !== expandedElement,i)\">\n </tr> -->\n \n @if (expandRows) {\n <tr mat-row *matRowDef=\"let row; columns: ['expandedDetail']; let i=dataIndex\"\n class=\"example-detail-row\"\n [ngClass]=\"{'hidden': isRowHidden(i)}\">\n </tr>\n }\n @if (showFooterRow) {\n <tr mat-footer-row *matFooterRowDef=\"getDisplayedColumns(); sticky: stickyFooter\"></tr>\n }\n </table>\n </div>\n }\n }\n @else{\n <table mat-table #matTable #MyTable [id]=\"'matTableExt'+tableID\" [dataSource]=\"dataSource\" matSort cdkDropList\n cdkDropListOrientation=\"horizontal\" multiTemplateDataRows (cdkDropListDropped)=\"onDrop($event)\"\n (click)=\"saveCellEditing()\" [style.width]=\"scrollbarH?'max-content':'100%'\" \n [class]=\"'mat-mdc-table' + (tableClassName ? ' ' + tableClassName : '')\">\n \n <!-- Row selection column -->\n <ng-container matColumnDef=\"select\">\n <th mat-header-cell *matHeaderCellDef cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"!dndColumns\">\n <mat-checkbox (change)=\"$event ? toggleAllRows() : null\"\n [checked]=\"selection.hasValue() && isAllSelected()\"\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\" [aria-label]=\"checkboxLabel()\">\n </mat-checkbox>\n </th>\n <td mat-cell *matCellDef=\"let row;let i = dataIndex\">\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? setSelectedRows(row,i) : null\"\n [checked]=\"selection.isSelected(row)\" [aria-label]=\"checkboxLabel(row)\">\n </mat-checkbox>\n </td>\n <ng-container *ngIf=\"showFooterRow\">\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n </ng-container>\n <!--dynamic columns are being generated here-->\n @for (column of columnsArray; track column.field + '_' + column.pinned; let i = $index) {\n <div matColumnDef=\"{{column['field']}}\" [sticky]=\"column.pinned === 'left'\" [stickyEnd]=\"column.pinned === 'right'\">\n <th mat-header-cell *matHeaderCellDef [style.minWidth]=\"column.width\" [style.maxWidth]=\"column.maxWidth?column.maxWidth:column.width\"\n [style.minWidth]=\"column.minWidth\" cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"!dndColumns\"\n [columnsResizable]=\"columnResizable\" [index]=\"i\" class=\"mat-mdc-header-cell\"\n [mat-sort-header]=\"column.field\" [disabled]=\"!sorting || column.disabled === true\">\n \n @if (column.headerTemplate || headerTemplateRef) {\n <ng-template [ngTemplateOutlet]=\"column.headerTemplate || headerTemplateRef\"\n [ngTemplateOutletContext]=\"{data:column}\"></ng-template>\n }\n @if (!headerTemplateRef && !column.headerTemplate) {\n <span matTooltip=\"{{column.headerTooltip?.value}}\"\n [matTooltipPosition]=\"column?.headerTooltip?.tooltipPosition!\"\n [class.disabled]=\"!sorting || column.disabled === true\">{{column.header}}</span>\n }\n </th>\n <td mat-cell *matCellDef=\"let row ;let i=dataIndex\" class=\"mat-mdc-cell\">\n @if (!row.editable && !cellEditing[i +'_'+column.field]) {\n <div (dblclick)=\"cellEditing[i +'_'+column.field] = inCellEditing;setCellData(row,i)\"\n (click)=\"cellPopupEditing ? openCellPopupDialog(row, column, i) : null\"\n [style.cursor]=\"cellPopupEditing ? 'pointer' : 'default'\"\n matTooltip=\"{{column.cellTooltip?.value}}\"\n [matTooltipPosition]=\"column?.cellTooltip?.tooltipPosition!\">\n @if (!cellTemplateRef && !column?.cellTemplate && !cellTemplateRefMap[column.field]) {\n <span>{{row[column.field]}}</span>\n }\n @if (cellTemplateRefMap[column.field]) {\n <ng-container [ngTemplateOutlet]=\"cellTemplateRefMap[column.field]\"\n [ngTemplateOutletContext]=\"{row:row,column:column,index:i}\">\n </ng-container>\n }\n @if (cellTemplateRef && column.cellTemplate && !cellTemplateRefMap[column.field]) {\n <ng-container [ngTemplateOutlet]=\"column.cellTemplate\"\n [ngTemplateOutletContext]=\"{row:row,column:column,index:i}\">\n </ng-container>\n }\n @if (!cellTemplateRef && column.cellTemplate && !cellTemplateRefMap[column.field]) {\n <ng-container [ngTemplateOutlet]=\"column.cellTemplate\"\n [ngTemplateOutletContext]=\"{row:row,column:column,index:i}\">\n </ng-container>\n }\n @if (cellTemplateRef && !column.cellTemplate && !cellTemplateRefMap[column.field]) {\n <ng-container [ngTemplateOutlet]=\"cellTemplateRef\"\n [ngTemplateOutletContext]=\"{row:row,column:column,index:i}\">\n </ng-container>\n }\n </div>\n }\n @if (row.editable || cellEditing[i +'_'+column.field]) {\n <div (click)=\"$event.stopPropagation()\">\n @if (inlineEditingTemplateRef && !cellEditing[i +'_'+column.field]) {\n <ng-container [ngTemplateOutlet]=\"inlineEditingTemplateRef\"\n [ngTemplateOutletContext]=\"{data:getInlineEditingData(row,i,column)}\"></ng-container>\n }\n @if (cellEditingTemplateRef && !(row.editable)) {\n <ng-container [ngTemplateOutlet]=\"cellEditingTemplateRef\"\n [ngTemplateOutletContext]=\"{data:getInlineEditingData(row,i,column)}\"></ng-container>\n }\n @if (!inlineEditingTemplateRef && (row.editable) && rowDataTemp['e'+i]) {\n @if (column.type == 'number') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"number\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'string') {\n <mat-form-field style=\"width: 100%;\" appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"text\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'textarea') {\n <mat-form-field style=\"width: 100%;\" appearance=\"outline\" class=\"inline-editing-field\">\n <textarea matInput rows=\"3\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\"></textarea>\n </mat-form-field>\n }\n @if (column.type == 'date') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"date\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'datepicker') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput [matDatepicker]=\"inlinePicker\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n <mat-datepicker-toggle matIconSuffix [for]=\"inlinePicker\"></mat-datepicker-toggle>\n <mat-datepicker #inlinePicker></mat-datepicker>\n </mat-form-field>\n }\n @if (column.type == 'selection') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-select [value]=\"rowDataTemp['e'+i][column.field]\"\n [(ngModel)]=\"rowDataTemp['e'+i][column.field]\">\n @for (option of column.options; track option) {\n <mat-option [value]=\"option\">{{option}}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n @if (column.type == 'boolean') {\n <mat-checkbox (click)=\"$event.stopPropagation()\" color=\"primary\" [(ngModel)]=\"row[column.field]\"></mat-checkbox>\n }\n }\n @if (!cellEditingTemplateRef && cellEditing[i +'_'+column.field]) {\n @if (column.type == 'number') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"number\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'string') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"text\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'textarea') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <textarea matInput rows=\"3\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\"></textarea>\n </mat-form-field>\n }\n @if (column.type == 'date') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"date\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'datepicker') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput [matDatepicker]=\"cellPicker\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n <mat-datepicker-toggle matIconSuffix [for]=\"cellPicker\"></mat-datepicker-toggle>\n <mat-datepicker #cellPicker></mat-datepicker>\n </mat-form-field>\n }\n @if (column.type == 'selection') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-select [value]=\"rowDataTemp['e'+i][column.field]\"\n [(ngModel)]=\"rowDataTemp['e'+i][column.field]\">\n @for (option of column.options; track option) {\n <mat-option [value]=\"option\">{{option}}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n @if (column.type == 'boolean') {\n <mat-checkbox (click)=\"$event.stopPropagation()\" color=\"primary\" [(ngModel)]=\"row[column.field]\"></mat-checkbox>\n }\n }\n </div>\n }\n </td>\n @if (showFooterRow) {\n <td mat-footer-cell *matFooterCellDef> {{column.footerText}} </td>\n }\n </div>\n }\n <ng-container matColumnDef=\"edit\" stickyEnd=\"false\">\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\n class=\"action-column-cells\"> Edit </th>\n <td mat-cell *matCellDef=\"let row; let i = dataIndex\" class=\"inline-edit-column-cell\">\n @if (!row.editable && !row.editmodal) {\n <mat-icon class=\"edit-column-icons\" aria-hidden=\"false\"\n (click)=\"enableInlineEditing(row,i)\" fontIcon=\"edit_note\">\n </mat-icon>\n }\n @if (row.editable && !row.editmodal) {\n <div class=\"inline-editing-controls\">\n <mat-icon class=\"edit-column-icons\" aria-hidden=\"false\" (click)=\"saveInlineEditing(row,i)\"\n fontIcon=\"done\"></mat-icon>\n <mat-icon class=\"edit-column-icons\" aria-hidden=\"false\" (click)=\"cancelInlineEditing(row,i)\"\n fontIcon=\"close\"></mat-icon>\n </div>\n }\n </td>\n <td mat-footer-cell *matFooterCellDef> edit </td>\n </ng-container>\n <ng-container matColumnDef=\"popup\" stickyEnd=\"false\">\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\n class=\"action-column-cells\"> Popup\n </th>\n <td mat-cell *matCellDef=\"let row; let i = index\">\n <mat-icon aria-hidden=\"false\" (click)=\"openEditingDialog(row)\" fontIcon=\"edit\">\n </mat-icon>\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n \n <ng-container matColumnDef=\"delete\">\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\n class=\"action-column-cells\"> Delete\n </th>\n <td mat-cell *matCellDef=\"let row;let i=dataIndex\">\n <mat-icon (click)=\"deleteRow(row,i)\" aria-hidden=\"false\" aria-label=\"Example home icon\"\n fontIcon=\"delete\">\n </mat-icon>\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n \n <ng-container matColumnDef=\"hide\" stickyEnd=\"false\">\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\n class=\"action-column-cells\"> Hide\n </th>\n <td mat-cell *matCellDef=\"let row;let i=dataIndex\">\n <button mat-icon-button (click)=\"toggleRowHide(i)\" \n [matTooltip]=\"isRowHidden(i) ? 'Unhide Row' : 'Hide Row'\"\n matTooltipPosition=\"above\">\n <mat-icon [color]=\"isRowHidden(i) ? 'primary' : ''\" aria-hidden=\"false\">\n {{ isRowHidden(i) ? 'visibility_off' : 'visibility' }}\n </mat-icon>\n </button>\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n \n <ng-container matColumnDef=\"pin\" stickyEnd=\"false\">\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\n class=\"action-column-cells\"> Pinning\n </th>\n <td mat-cell *matCellDef=\"let row;let i=dataIndex\">\n <button mat-icon-button \n [matMenuTriggerFor]=\"pinMenu\"\n (click)=\"openRowPinMenu($event, row)\"\n [matTooltip]=\"getRowPinPosition(row) ? 'Pinned ' + getRowPinPosition(row) : 'Pin Row'\"\n matTooltipPosition=\"above\">\n <mat-icon [color]=\"isRowPinned(row) ? 'primary' : ''\" aria-hidden=\"false\">\n {{ isRowPinned(row) ? 'push_pin' : 'push_pin' }}\n </mat-icon>\n </button>\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n \n <!-- Expanded Content Column - The detail row is made up of this one column that spans across all columns -->\n @if (expandRows) {\n <ng-container matColumnDef=\"expandedDetail\">\n <td mat-cell *matCellDef=\"let element;let i=dataIndex \"\n [attr.colspan]=\"columnsToDisplayWithExpand.length\">\n <div class=\"example-element-detail\"\n [@detailExpand]=\"element == expandedElement ? 'expanded' : 'collapsed'\">\n @if (expansionTemplateRef) {\n <ng-container [ngTemplateOutlet]=\"expansionTemplateRef\"\n [ngTemplateOutletContext]=\"{$explicit:element,row:element,index:i}\">\n </ng-container>\n }\n </div>\n </td>\n </ng-container>\n }\n <!-- Column group headers -->\n @if (columnGroups.length > 0) {\n @for (group of columnGroups; track group.name) {\n <ng-container [matColumnDef]=\"'group-' + group.name\">\n <th mat-header-cell *matHeaderCellDef [attr.colspan]=\"group.colspan || group.columns.length\" \n class=\"group-header-cell\">\n <div class=\"group-header-content\">\n <span class=\"group-label\">{{group.label}}</span>\n </div>\n </th>\n </ng-container>\n }\n <!-- Empty header cells for ungrouped columns -->\n <ng-container *ngFor=\"let column of columnsArray\">\n <ng-container [matColumnDef]=\"'ungrouped-' + column.field\">\n <th mat-header-cell *matHeaderCellDef class=\"group-header-cell ungrouped-header-cell\">\n </th>\n </ng-container>\n </ng-container>\n }\n <!-- Filter row columns for data columns -->\n <ng-container *ngFor=\"let ids of headersFiltersIds; let i = index\">\n <ng-container [matColumnDef]=\"ids\" [sticky]=\"columnsArray[returnIndex(ids)].pinned === 'left'\" [stickyEnd]=\"columnsArray[returnIndex(ids)].pinned === 'right'\">\n <th mat-header-cell *matHeaderCellDef [style.minWidth]=\"columnsArray[returnIndex(ids)].width\" [style.maxWidth]=\"columnsArray[returnIndex(ids)].maxWidth?columnsArray[returnIndex(ids)].maxWidth:columnsArray[returnIndex(ids)].width\"\n [style.minWidth]=\"columnsArray[returnIndex(ids)].minWidth\" >\n <div style=\"display: block; width: 100%;\" class=\"filters-container\" [class.animate]=\"toggleFilters\">\n <app-filter-columns-component style=\"display: block; width: 100%;\" [obj]=\"columnsArray[returnIndex(ids)]\"\n (filterOutput)=\"applyColumnFilter($event,columnsArray[returnIndex(ids)])\"></app-filter-columns-component>\n </div>\n </th>\n </ng-container>\n </ng-container>\n\n <!-- Empty filter cells for action columns -->\n <ng-container [matColumnDef]=\"'filter-select'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'filter-edit'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'filter-popup'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'filter-delete'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'filter-freeze'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'filter-hide'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'filter-pin'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n\n <ng-container *ngIf=\"columnGroups.length > 0\">\n <tr mat-header-row *matHeaderRowDef=\"getGroupedColumns(); sticky: stickyHeader\" class=\"mat-mdc-header-row group-header-row\"></tr>\n </ng-container>\n <tr mat-header-row *matHeaderRowDef=\" getDisplayedColumns(); sticky: stickyHeader\" class=\"mat-mdc-header-row\"></tr>\n <tr style=\"height: 0px;\" mat-header-row class=\"no-default-height\" *matHeaderRowDef=\"getFilterColumns()\">\n </tr>\n \n <!-- All Data Rows (with dynamic pinning classes) -->\n <!-- <tr mat-row *matRowDef=\"let row; columns:getDisplayedColumns(); let i=dataIndex;\" \n class=\"mat-mdc-row data-row\"\n [ngClass]=\"{\n 'data-row':expandRows,\n 'stripedRows':(stripedRows && i % 2 == 1),\n 'hoverClass':rowHover, \n 'hidden':(hiddenCtrl.isSelected(row) && hideRows) || isRowHidden(i),\n 'example-expanded-row':expandedElement === row,\n 'pinned-row': isRowPinned(row),\n 'pinned-top-row': isRowPinnedTop(row),\n 'pinned-bottom-row': isRowPinnedBottom(row)\n }\"\n (click)=\"expandRow(row, row !== expandedElement,i)\">\n </tr> -->\n <tr mat-row *matRowDef=\"let row; columns:getDisplayedColumns(); let i=dataIndex; \" \n class=\"mat-mdc-row data-row\"\n [ngClass]=\"{\n 'data-row':expandRows,\n 'stripedRows':(stripedRows && i % 2 == 1),\n 'hoverClass':rowHover, \n 'hidden':(hiddenCtrl.isSelected(row) && hideRows) || isRowHidden(i),\n 'example-expanded-row':expandedElement === row,\n 'pinned-row': isRowPinned(row),\n 'mat-row-sticky-top': isRowPinnedTop(row),\n 'mat-row-sticky-bottom': isRowPinnedBottom(row)\n }\"\n (click)=\"expandRow(row, row !== expandedElement,i)\">\n </tr>\n <!-- <tr mat-header-row *matHeaderRowDef=\"let row; columns:getDisplayedColumns(); let i=dataIndex; when: isRowPinnedTop(row)\" \n class=\"mat-mdc-row data-row\"\n class=\"mat-mdc-header-row\"\n [ngClass]=\"{\n 'data-row':expandRows,\n 'stripedRows':(stripedRows && i % 2 == 1),\n 'hoverClass':rowHover, \n 'hidden':(hiddenCtrl.isSelected(row) && hideRows) || isRowHidden(i),\n 'example-expanded-row':expandedElement === row,\n 'pinned-row': isRowPinned(row),\n 'pinned-top-row': isRowPinnedTop(row),\n 'pinned-bottom-row': isRowPinnedBottom(row)\n }\"\n (click)=\"expandRow(row, row !== expandedElement,i)\">\n </tr> -->\n \n @if (expandRows) {\n <tr mat-row *matRowDef=\"let row; columns: ['expandedDetail']; let i=dataIndex\"\n class=\"example-detail-row\"\n [ngClass]=\"{'hidden': isRowHidden(i)}\">\n </tr>\n }\n @if (showFooterRow) {\n <tr mat-footer-row *matFooterRowDef=\"getDisplayedColumns(); sticky: stickyFooter\"></tr>\n }\n </table>\n\n }\n \n </section>\n @if (showPaginator) {\n <mat-paginator [pageSizeOptions]=\"pageSizeOptions\"\n [showFirstLastButtons]=\"showFirstLastButtons\" class=\"mat-mdc-paginator\">\n </mat-paginator>\n }\n</div>", styles: [".custom-primary-color{color:#3f51b5!important;border-color:#3f51b5!important}table{min-width:100%}.mat-mdc-table-sticky-border-elem-right{border-left:1px solid #e0e0e0}.mat-mdc-table-sticky-border-elem-left{border-right:1px solid #e0e0e0}tr.example-detail-row{height:0!important;overflow:hidden}.example-element-detail{overflow:hidden;display:flex;transition:height .3s cubic-bezier(.4,0,.2,1);padding:0}.example-element-detail[style*=\"height: auto\"],.example-element-detail[style*=\"height: 1\"]{padding:10px 0}.hidden{display:none}.stripedRows{background:var(--mat-table-row-hover-state-layer-color, #eaeaea)!important}.hoverClass:hover{background:var(--mat-table-row-hover-state-layer-color, #dbdbdb)!important}.filters-container{overflow:hidden;transition:height .5s ease-in-out}.animate{max-height:max-content!important}.cell-popup-indicator{font-size:18px;color:var(--mat-sys-color-primary, #1976d2);cursor:pointer;-webkit-user-select:none;user-select:none;display:inline-block;transition:transform .2s}.cell-popup-indicator:hover{transform:scale(1.3);color:var(--mat-sys-color-primary-container, #1565c0)}.resize-handle{display:inline-block;border-right:2px solid var(--mat-table-outline-color, rgb(140, 140, 140));position:absolute;top:0;right:0;height:100%;cursor:col-resize;opacity:0}.resize-handle:hover{width:20px}table th:hover .resize-handle{opacity:1;transition:.3s ease-in-out}.mat-mdc-table.resizing{-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;user-select:none;cursor:col-resize}.mat-mdc-table .mat-mdc-header-cell{position:relative}.mat-mdc-table .mat-mdc-header-cell:not(:last-child) .resize-holder{cursor:col-resize;width:20px;height:100%;position:absolute;right:-10px;top:0;z-index:1}.toolbar-container{display:flex;padding:0 15px;gap:1rem;grid-auto-rows:10px;justify-content:flex-end;align-items:center}.mat-table-ext-container{width:100%;max-width:100%;overflow:auto}.column-headers{font-family:Roboto,Helvetica Neue,sans-serif}.example-spacer{flex:1 1 auto}.export-button .export-button-content{display:flex!important;align-items:center;justify-content:space-between;gap:4px;width:100%;padding:0 4px}.export-button .mat-button-wrapper{display:flex!important;width:8em;justify-content:space-around;align-items:center}.toolbar-menu-container{display:flex;flex-direction:column;margin:auto .8em;width:15em;height:20em}.inline-editing-field{padding:8px 0}.inline-editing-field div.mat-mdc-form-field-subscript-wrapper{display:none}.toolbar-menu-item{display:flex;height:3em}.toolbar-menu-checkbox{margin-left:8%}.toolbar-menu-checkbox.mat-checkbox{width:max-content;display:flex;align-items:center}.hide-button .mat-button-wrapper,.pin-button .mat-button-wrapper{display:flex!important;align-items:center;gap:5px}.pin-button .mat-icon{margin-right:2px}.pin-button,.hide-button{padding-right:10px!important}.hide-button,.pin-button,.export-button,.print-button{height:3em;border:2px solid currentColor!important}.print-button .mat-button-wrapper{display:flex!important;align-items:center;gap:5px}.showHide-menu-columns-list{height:10em;max-height:10em;overflow-y:auto}.mat-column-select{width:50px!important}.data-row td,.example-expanded-row td{border-bottom-width:0!important}.action-column-cells{width:40px;height:inherit}.inline-editing-controls{display:flex}.global-search-field{width:-webkit-fill-available}.mat-mdc-table{--mat-table-container-elevation: 0;--mat-table-row-hover-state-layer-color: var(--mat-sys-color-surface-variant);--mat-table-row-hover-state-layer-opacity: .08}.group-header-row{background-color:var(--mat-sys-color-surface-container-low, #f5f5f5)}.group-header-row .group-header-cell{text-align:center!important;font-weight:600;font-size:13px;letter-spacing:.5px;text-transform:uppercase;padding:12px 16px;position:relative}.group-header-row .group-header-cell.ungrouped-header-cell{min-height:48px}.group-header-row .group-header-cell .group-header-content{display:flex;align-items:center;justify-content:center;gap:8px;text-align:center}.group-header-row .group-header-cell .group-header-content .group-label{font-weight:600;text-align:center}.group-header-row .group-header-cell:after{content:\"\";position:absolute;bottom:-2px;left:0;right:0;height:2px;background:linear-gradient(90deg,transparent 0%,var(--mat-sys-color-primary, #1976d2) 50%,transparent 100%);opacity:.3}.frozen-row{position:sticky!important;z-index:10;background-color:var(--mat-sys-color-surface, #ffffff)!important;box-shadow:0 2px 4px #0000001a}.frozen-row:after{content:\"\";position:absolute;bottom:0;left:0;right:0;height:2px;background:linear-gradient(to right,var(--mat-sys-color-primary, #1976d2) 0%,transparent 100%)}.frozen-row-bottom{position:sticky!important;z-index:10;background-color:var(--mat-sys-color-surface, #ffffff)!important;box-shadow:0 -2px 4px #0000001a}.frozen-row-bottom:before{content:\"\";position:absolute;top:0;left:0;right:0;height:2px;background:linear-gradient(to right,var(--mat-sys-color-primary, #1976d2) 0%,transparent 100%)}.mat-mdc-header-cell{--mat-table-header-container-background-color: var(--mat-sys-color-surface);--mat-table-header-container-text-color: var(--mat-sys-color-on-surface)}.mat-mdc-cell{--mat-table-cell-container-background-color: var(--mat-sys-color-surface);--mat-table-cell-container-text-color: var(--mat-sys-color-on-surface)}.mat-mdc-row{--mat-table-row-container-background-color: var(--mat-sys-color-surface)}.mat-mdc-paginator{--mat-paginator-container-background-color: var(--mat-sys-color-surface);--mat-paginator-container-text-color: var(--mat-sys-color-on-surface)}.pinned-row{background:var(--mat-sys-color-surface, #ffffff);box-shadow:0 2px 4px #0000001a;position:sticky!important;z-index:10}.pinned-row.pinned-top-row{top:var(--pinned-row-top-offset, var(--pinned-top-base-offset, 0px))}.pinned-row.pinned-bottom-row{bottom:var(--pinned-row-bottom-offset, var(--pinned-bottom-base-offset, 0px))}.pinned-top-row:after{content:\"\";position:absolute;bottom:-2px;left:0;right:0;height:2px;background:linear-gradient(to bottom,rgba(0,0,0,.1),transparent)}.pinned-bottom-row:before{content:\"\";position:absolute;top:-2px;left:0;right:0;height:2px;background:linear-gradient(to top,rgba(0,0,0,.1),transparent)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i6.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i6.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i3.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: i3.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i3.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i7$1.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i7$1.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i7$1.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i7$1.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i7$1.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i7$1.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i7$1.MatFooterCellDef, selector: "[matFooterCellDef]" }, { kind: "directive", type: i7$1.MatFooterRowDef, selector: "[matFooterRowDef]", inputs: ["matFooterRowDef", "matFooterRowDefSticky"] }, { kind: "directive", type: i7$1.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i7$1.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "directive", type: i7$1.MatFooterCell, selector: "mat-footer-cell, td[mat-footer-cell]" }, { kind: "component", type: i7$1.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i7$1.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: i7$1.MatFooterRow, selector: "mat-footer-row, tr[mat-footer-row]", exportAs: ["matFooterRow"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i5.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i5.MatLabel, selector: "mat-label" }, { kind: "directive", type: i5.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i6$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i7.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i7.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i8.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatPaginatorModule }, { kind: "component", type: i12.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "ngmodule", type: MatSortModule }, { kind: "directive", type: i13.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i13.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i14.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i14.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i14.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i9.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i9.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i2.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatToolbarModule }, { kind: "component", type: i17.MatToolbar, selector: "mat-toolbar", inputs: ["color"], exportAs: ["matToolbar"] }, { kind: "ngmodule", type: MatProgressBarModule }, { kind: "component", type: i18.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i10.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i10.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i10.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "ngmodule", type: MatNativeDateModule }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i20.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i20.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "component", type: ColumnPinningComponent, selector: "app-column-pinning", inputs: ["columns"], outputs: ["columnsChanged"] }, { kind: "component", type: FilterColumnsComponentComponent, selector: "app-filter-columns-component", inputs: ["obj"], outputs: ["filterOutput"] }, { kind: "directive", type: ResizeColumnDirective, selector: "[columnsResizable]", inputs: ["columnsResizable", "index"] }], animations: [
|
|
2660
|
+
trigger('detailExpand', [
|
|
2661
|
+
state('collapsed', style({ height: '0px', minHeight: '0' })),
|
|
2662
|
+
state('expanded', style({ height: '*' })),
|
|
2663
|
+
transition('expanded <=> collapsed', animate('300ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
|
|
2664
|
+
]),
|
|
2665
|
+
], encapsulation: i0.ViewEncapsulation.None }); }
|
|
2666
|
+
}
|
|
2667
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.5", ngImport: i0, type: MatTableExtComponent, decorators: [{
|
|
2668
|
+
type: Component,
|
|
2669
|
+
args: [{ selector: 'mat-table-ext', encapsulation: ViewEncapsulation.None, standalone: true, imports: [
|
|
2670
|
+
CommonModule,
|
|
2671
|
+
FormsModule,
|
|
2672
|
+
ReactiveFormsModule,
|
|
2673
|
+
MatTableModule,
|
|
2674
|
+
MatFormFieldModule,
|
|
2675
|
+
MatInputModule,
|
|
2676
|
+
MatSelectModule,
|
|
2677
|
+
MatCheckboxModule,
|
|
2678
|
+
MatIconModule,
|
|
2679
|
+
MatPaginatorModule,
|
|
2680
|
+
MatSortModule,
|
|
2681
|
+
MatMenuModule,
|
|
2682
|
+
MatButtonModule,
|
|
2683
|
+
MatTooltipModule,
|
|
2684
|
+
MatToolbarModule,
|
|
2685
|
+
MatProgressBarModule,
|
|
2686
|
+
MatDatepickerModule,
|
|
2687
|
+
MatNativeDateModule,
|
|
2688
|
+
DragDropModule,
|
|
2689
|
+
ColumnPinningComponent,
|
|
2690
|
+
FilterColumnsComponentComponent,
|
|
2691
|
+
ResizeColumnDirective
|
|
2692
|
+
], animations: [
|
|
2693
|
+
trigger('detailExpand', [
|
|
2694
|
+
state('collapsed', style({ height: '0px', minHeight: '0' })),
|
|
2695
|
+
state('expanded', style({ height: '*' })),
|
|
2696
|
+
transition('expanded <=> collapsed', animate('300ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
|
|
2697
|
+
]),
|
|
2698
|
+
], template: "<div [style.width]=\"tableWidth\">\n @if (globalSearch) {\n <mat-form-field class=\"global-search-field\" appearance=\"fill\">\n <mat-label>Search</mat-label>\n <input matInput [ngModel]=\"globalFilter\" (ngModelChange)=\"applyGlobalFilter($event)\" placeholder=\"Ex. Mia\"\n #input>\n </mat-form-field>\n }\n @if (showToolbar) {\n <mat-toolbar class=\"toolbar-container\" [style.height]=\"toolbarHeight?toolbarHeight:'50px'\">\n @if (toolbarTitle) {\n <span class=\"toolbar-title\">{{toolbarTitle}}</span>\n }\n @if (toolbarTemplateRef) {\n <ng-container [ngTemplateOutlet]=\"toolbarTemplateRef\"></ng-container>\n }\n <span class=\"example-spacer\"></span>\n @if (rowSelection || multiRowSelection) {\n <button class=\"hide-button\" mat-stroked-button color=\"primary\" (click)=\"hideSelectedRows()\">\n Hide Rows\n </button>\n <button class=\"hide-button\" mat-stroked-button color=\"primary\" (click)=\"showHiddenRows()\">\n Show All Rows\n </button>\n }\n @if (enableRowHiding && hiddenRowIndices.length > 0) {\n <button class=\"hide-button custom-primary-color\" mat-stroked-button color=\"accent\" (click)=\"unhideAllRows()\"\n matTooltip=\"Unhide all hidden rows\" matTooltipPosition=\"above\">\n <mat-icon>visibility</mat-icon>\n <span>Unhide All ({{hiddenRowIndices.length}})</span>\n </button>\n }\n @if (columnHidable) {\n <button class=\"hide-button\" mat-stroked-button color=\"primary\"\n (click)=\"openMenu('hideShow',$event)\" matTooltip=\"Column Visibility\" matTooltipPosition=\"above\">\n <mat-icon>visibility</mat-icon>\n </button>\n }\n @if (columnPinnable) {\n <button class=\"pin-button\" mat-stroked-button color=\"primary\"\n (click)=\"openMenu('columnPin',$event)\" matTooltip=\"Column Pinning\">\n <mat-icon svgIcon=\"pinIcon\"></mat-icon>\n </button>\n }\n @if (exportButtonEnable) {\n <button class=\"export-button\" mat-stroked-button color=\"primary\"\n (click)=\"openMenu('export',$event)\" matTooltip=\"Table Data Export\">\n <mat-icon>import_export</mat-icon>\n <span>Export</span>\n <mat-icon iconPositionEnd>expand_more</mat-icon>\n </button>\n }\n @if (printButtonEnable) {\n <button class=\"print-button\" mat-stroked-button color=\"primary\"\n (click)=\"printTable()\" matTooltip=\"Print Table\">\n <mat-icon style=\"margin:unset;\">print</mat-icon>\n </button>\n }\n <div style=\"visibility: hidden; position:fixed\" [matMenuTriggerFor]=\"menu\" [style.left.px]=\"menuX\"\n [style.top.px]=\"menuY\"></div>\n </mat-toolbar>\n }\n <mat-menu #menu=\"matMenu\" (closed)=\"menuClosed()\" id=\"exportMenu\">\n @if (exportMenuCtrl) {\n <mat-option (click)=\"exportTable('xlsx')\">Export to Excel</mat-option>\n <mat-option (click)=\"exportTable('csv')\">Export to CSV</mat-option>\n <mat-option (click)=\"exportToPDF()\">Export to PDF</mat-option>\n }\n </mat-menu>\n <div style=\"visibility: hidden; position:fixed\" #columnMenuTrigger=\"matMenuTrigger\" [matMenuTriggerFor]=\"columnMenu\"\n [style.left.px]=\"menuX\" [style.top.px]=\"menuY\">\n </div>\n <mat-menu #columnMenu=\"matMenu\" (closed)=\"resetMenuChecks()\">\n @if (hideShowMenuCtrl) {\n <div class=\"toolbar-menu-container\" [formGroup]=\"hideShowMenuGroup\"\n (click)=\"$event.stopPropagation()\">\n <h4 class=\"column-headers\">Visible Columns</h4>\n <mat-form-field appearance=\"fill\" style=\"width: -webkit-fill-available;\">\n <mat-label>Filter Columns</mat-label>\n <input matInput [(ngModel)]=\"showHideFilter\" (ngModelChange)=\"filterColumns($event)\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n <div class=\"showHide-menu-columns-list\">\n @for (column of showHideColumnsArray; track column.field) {\n <div class=\"toolbar-menu-item\">\n <mat-checkbox color=\"primary\" class=\"toolbar-menu-checkbox\" style=\"width: max-content;\"\n [formControlName]=\"column.field\" (change)=\"setColumnHideShow()\">{{column.header}}</mat-checkbox>\n </div>\n }\n </div>\n </div>\n }\n @if (columnPinMenuCtrl) {\n <div class=\"toolbar-menu-container\" (click)=\"$event.stopPropagation()\">\n <h4 class=\"column-headers\">Pin Columns</h4>\n <form class=\"example-form\">\n <mat-form-field appearance=\"fill\" style=\"width: -webkit-fill-available;\">\n <mat-label>Filter Columns</mat-label>\n <input matInput [(ngModel)]=\"showHideFilter\" (ngModelChange)=\"filterColumns($event)\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n </form>\n <div class=\"showHide-menu-columns-list\">\n <app-column-pinning [columns]=\"showHideColumnsArray\" (columnsChanged)=\"updateColumns($event)\"></app-column-pinning>\n </div>\n </div>\n }\n </mat-menu>\n\n <!-- Row Pin Menu -->\n <mat-menu #pinMenu=\"matMenu\" (closed)=\"closeRowPinMenu()\">\n @if (rowPinMenuRow) {\n @if (!isRowPinned(rowPinMenuRow)) {\n <button mat-menu-item (click)=\"pinRow(rowPinMenuRow, 'top')\">\n <mat-icon>vertical_align_top</mat-icon>\n <span>Pin to Top</span>\n </button>\n <button mat-menu-item (click)=\"pinRow(rowPinMenuRow, 'bottom')\">\n <mat-icon>vertical_align_bottom</mat-icon>\n <span>Pin to Bottom</span>\n </button>\n }\n @if (isRowPinned(rowPinMenuRow)) {\n <button mat-menu-item (click)=\"unpinRow(rowPinMenuRow)\">\n <mat-icon>close</mat-icon>\n <span>Unpin Row</span>\n </button>\n }\n }\n </mat-menu>\n\n @if (loadingIndicator) {\n <mat-progress-bar mode=\"indeterminate\"></mat-progress-bar>\n }\n <section id=\"tableContainer\" class=\"mat-table-ext-container\" (scroll)=\"onScroll($event)\"\n [style.height]=\"tableHeight ? tableHeight :'max-content'\">\n \n @if(enableRowPinning){\n <div [style.max-height]=\"topPinnedMaxHeight\" [style.overflow]=\"topPinnedMaxHeight ? 'auto' : 'visible'\" \n [style.position]=\"'sticky'\" [style.top]=\"'0'\" [style.z-index]=\"'111'\">\n <table style=\"width: 100%;\" \n mat-table #MyTableTop [id]=\"'matTableExtTop'+tableID\" [dataSource]=\"pinnedTopDataSource\" matSort cdkDropList\n cdkDropListOrientation=\"horizontal\" multiTemplateDataRows (cdkDropListDropped)=\"onDrop($event)\"\n (click)=\"saveCellEditing()\" [style.width]=\"scrollbarH?'max-content':'100%'\" \n [class]=\"'mat-mdc-table' + (tableClassName ? ' ' + tableClassName : '')\">\n \n <!-- Row selection column -->\n <ng-container matColumnDef=\"select\">\n <th mat-header-cell *matHeaderCellDef cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"!dndColumns\">\n <mat-checkbox (change)=\"$event ? toggleAllRows() : null\"\n [checked]=\"selection.hasValue() && isAllSelected()\"\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\" [aria-label]=\"checkboxLabel()\">\n </mat-checkbox>\n </th>\n <td mat-cell *matCellDef=\"let row;let i = dataIndex\">\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? setSelectedRows(row,i) : null\"\n [checked]=\"selection.isSelected(row)\" [aria-label]=\"checkboxLabel(row)\">\n </mat-checkbox>\n </td>\n <ng-container *ngIf=\"showFooterRow\">\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n </ng-container>\n <!--dynamic columns are being generated here-->\n @for (column of columnsArray; track column.field + '_' + column.pinned; let i = $index) {\n <div matColumnDef=\"{{column['field']}}\" [sticky]=\"column.pinned === 'left'\" [stickyEnd]=\"column.pinned === 'right'\">\n <th mat-header-cell *matHeaderCellDef [style.minWidth]=\"column.width\" [style.maxWidth]=\"column.maxWidth?column.maxWidth:column.width\"\n [style.minWidth]=\"column.minWidth\" cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"!dndColumns\"\n [columnsResizable]=\"columnResizable\" [index]=\"i\" class=\"mat-mdc-header-cell\"\n [mat-sort-header]=\"column.field\" [disabled]=\"!sorting || column.disabled === true\">\n \n @if (column.headerTemplate || headerTemplateRef) {\n <ng-template [ngTemplateOutlet]=\"column.headerTemplate || headerTemplateRef\"\n [ngTemplateOutletContext]=\"{data:column}\"></ng-template>\n }\n @if (!headerTemplateRef && !column.headerTemplate) {\n <span matTooltip=\"{{column.headerTooltip?.value}}\"\n [matTooltipPosition]=\"column?.headerTooltip?.tooltipPosition!\"\n [class.disabled]=\"!sorting || column.disabled === true\">{{column.header}}</span>\n }\n </th>\n <td mat-cell *matCellDef=\"let row ;let i=dataIndex\" class=\"mat-mdc-cell\">\n @if (!row.editable && !cellEditing[i +'_'+column.field]) {\n <div [style.cursor]=\"'default'\"\n matTooltip=\"{{column.cellTooltip?.value}}\"\n [matTooltipPosition]=\"column?.cellTooltip?.tooltipPosition!\">\n @if (!cellTemplateRef && !column?.cellTemplate && !cellTemplateRefMap[column.field]) {\n <span>{{row[column.field]}}</span>\n }\n @if (cellTemplateRefMap[column.field]) {\n <ng-container [ngTemplateOutlet]=\"cellTemplateRefMap[column.field]\"\n [ngTemplateOutletContext]=\"{row:row,column:column,index:i}\">\n </ng-container>\n }\n @if (cellTemplateRef && column.cellTemplate && !cellTemplateRefMap[column.field]) {\n <ng-container [ngTemplateOutlet]=\"column.cellTemplate\"\n [ngTemplateOutletContext]=\"{row:row,column:column,index:i}\">\n </ng-container>\n }\n @if (!cellTemplateRef && column.cellTemplate && !cellTemplateRefMap[column.field]) {\n <ng-container [ngTemplateOutlet]=\"column.cellTemplate\"\n [ngTemplateOutletContext]=\"{row:row,column:column,index:i}\">\n </ng-container>\n }\n @if (cellTemplateRef && !column.cellTemplate && !cellTemplateRefMap[column.field]) {\n <ng-container [ngTemplateOutlet]=\"cellTemplateRef\"\n [ngTemplateOutletContext]=\"{row:row,column:column,index:i}\">\n </ng-container>\n }\n </div>\n }\n @if (row.editable || cellEditing[i +'_'+column.field]) {\n <div (click)=\"$event.stopPropagation()\">\n @if (inlineEditingTemplateRef && !cellEditing[i +'_'+column.field]) {\n <ng-container [ngTemplateOutlet]=\"inlineEditingTemplateRef\"\n [ngTemplateOutletContext]=\"{data:getInlineEditingData(row,i,column)}\"></ng-container>\n }\n @if (cellEditingTemplateRef && !(row.editable)) {\n <ng-container [ngTemplateOutlet]=\"cellEditingTemplateRef\"\n [ngTemplateOutletContext]=\"{data:getInlineEditingData(row,i,column)}\"></ng-container>\n }\n @if (!inlineEditingTemplateRef && (row.editable) && rowDataTemp['e'+i]) {\n @if (column.type == 'number') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"number\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'string') {\n <mat-form-field style=\"width: 100%;\" appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"text\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'textarea') {\n <mat-form-field style=\"width: 100%;\" appearance=\"outline\" class=\"inline-editing-field\">\n <textarea matInput rows=\"3\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\"></textarea>\n </mat-form-field>\n }\n @if (column.type == 'date') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"date\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'datepicker') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput [matDatepicker]=\"inlinePicker\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n <mat-datepicker-toggle matIconSuffix [for]=\"inlinePicker\"></mat-datepicker-toggle>\n <mat-datepicker #inlinePicker></mat-datepicker>\n </mat-form-field>\n }\n @if (column.type == 'selection') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-select [value]=\"rowDataTemp['e'+i][column.field]\"\n [(ngModel)]=\"rowDataTemp['e'+i][column.field]\">\n @for (option of column.options; track option) {\n <mat-option [value]=\"option\">{{option}}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n @if (column.type == 'boolean') {\n <mat-checkbox (click)=\"$event.stopPropagation()\" color=\"primary\" [(ngModel)]=\"row[column.field]\"></mat-checkbox>\n }\n }\n @if (!cellEditingTemplateRef && cellEditing[i +'_'+column.field]) {\n @if (column.type == 'number') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"number\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'string') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"text\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'textarea') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <textarea matInput rows=\"3\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\"></textarea>\n </mat-form-field>\n }\n @if (column.type == 'date') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"date\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'datepicker') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput [matDatepicker]=\"cellPicker\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n <mat-datepicker-toggle matIconSuffix [for]=\"cellPicker\"></mat-datepicker-toggle>\n <mat-datepicker #cellPicker></mat-datepicker>\n </mat-form-field>\n }\n @if (column.type == 'selection') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-select [value]=\"rowDataTemp['e'+i][column.field]\"\n [(ngModel)]=\"rowDataTemp['e'+i][column.field]\">\n @for (option of column.options; track option) {\n <mat-option [value]=\"option\">{{option}}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n @if (column.type == 'boolean') {\n <mat-checkbox (click)=\"$event.stopPropagation()\" color=\"primary\" [(ngModel)]=\"row[column.field]\"></mat-checkbox>\n }\n }\n </div>\n }\n </td>\n @if (showFooterRow) {\n <td mat-footer-cell *matFooterCellDef> {{column.footerText}} </td>\n }\n </div>\n }\n <ng-container matColumnDef=\"edit\" stickyEnd=\"false\">\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\n class=\"action-column-cells\"> Edit </th>\n <td mat-cell *matCellDef=\"let row; let i = dataIndex\" class=\"inline-edit-column-cell\">\n <!-- Edit disabled in pinned top table -->\n </td>\n <td mat-footer-cell *matFooterCellDef> edit </td>\n </ng-container>\n <ng-container matColumnDef=\"popup\" stickyEnd=\"false\">\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\n class=\"action-column-cells\"> Popup\n </th>\n <td mat-cell *matCellDef=\"let row; let i = index\">\n <!-- Popup edit disabled in pinned top table -->\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n \n <ng-container matColumnDef=\"delete\">\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\n class=\"action-column-cells\"> Delete\n </th>\n <td mat-cell *matCellDef=\"let row;let i=dataIndex\">\n <mat-icon (click)=\"deleteRow(row,i)\" aria-hidden=\"false\" aria-label=\"Example home icon\"\n fontIcon=\"delete\">\n </mat-icon>\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n \n <ng-container matColumnDef=\"hide\" stickyEnd=\"false\">\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\n class=\"action-column-cells\"> Hide\n </th>\n <td mat-cell *matCellDef=\"let row;let i=dataIndex\">\n <button mat-icon-button (click)=\"toggleRowHide(i)\" \n [matTooltip]=\"isRowHidden(i) ? 'Unhide Row' : 'Hide Row'\"\n matTooltipPosition=\"above\">\n <mat-icon [color]=\"isRowHidden(i) ? 'primary' : ''\" aria-hidden=\"false\">\n {{ isRowHidden(i) ? 'visibility_off' : 'visibility' }}\n </mat-icon>\n </button>\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n \n <ng-container matColumnDef=\"pin\" stickyEnd=\"false\">\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\n class=\"action-column-cells\"> Pinning\n </th>\n <td mat-cell *matCellDef=\"let row;let i=dataIndex\">\n <button mat-icon-button \n [matMenuTriggerFor]=\"pinMenu\"\n (click)=\"openRowPinMenu($event, row)\"\n [matTooltip]=\"getRowPinPosition(row) ? 'Pinned ' + getRowPinPosition(row) : 'Pin Row'\"\n matTooltipPosition=\"above\">\n <mat-icon [color]=\"isRowPinned(row) ? 'primary' : ''\" aria-hidden=\"false\">\n {{ isRowPinned(row) ? 'push_pin' : 'push_pin' }}\n </mat-icon>\n </button>\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n \n <!-- Expanded Content Column - The detail row is made up of this one column that spans across all columns -->\n @if (expandRows) {\n <ng-container matColumnDef=\"expandedDetail\">\n <td mat-cell *matCellDef=\"let element;let i=dataIndex \"\n [attr.colspan]=\"columnsToDisplayWithExpand.length\">\n <div class=\"example-element-detail\"\n [@detailExpand]=\"element == expandedElement ? 'expanded' : 'collapsed'\">\n @if (expansionTemplateRef) {\n <ng-container [ngTemplateOutlet]=\"expansionTemplateRef\"\n [ngTemplateOutletContext]=\"{$explicit:element,row:element,index:i}\">\n </ng-container>\n }\n </div>\n </td>\n </ng-container>\n }\n <!-- Column group headers -->\n @if (columnGroups.length > 0) {\n @for (group of columnGroups; track group.name) {\n <ng-container [matColumnDef]=\"'group-' + group.name\">\n <th mat-header-cell *matHeaderCellDef [attr.colspan]=\"group.colspan || group.columns.length\" \n class=\"group-header-cell\">\n <div class=\"group-header-content\">\n <span class=\"group-label\">{{group.label}}</span>\n </div>\n </th>\n </ng-container>\n }\n <!-- Empty header cells for ungrouped columns -->\n @for (column of columnsArray; track column.field) {\n <ng-container [matColumnDef]=\"'ungrouped-' + column.field\">\n <th mat-header-cell *matHeaderCellDef class=\"group-header-cell ungrouped-header-cell\">\n </th>\n </ng-container>\n }\n <!-- Empty header cells for action columns to fill space in group header -->\n <ng-container [matColumnDef]=\"'ungrouped-select'\">\n <th mat-header-cell *matHeaderCellDef class=\"group-header-cell ungrouped-header-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'ungrouped-edit'\">\n <th mat-header-cell *matHeaderCellDef class=\"group-header-cell ungrouped-header-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'ungrouped-popup'\">\n <th mat-header-cell *matHeaderCellDef class=\"group-header-cell ungrouped-header-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'ungrouped-delete'\">\n <th mat-header-cell *matHeaderCellDef class=\"group-header-cell ungrouped-header-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'ungrouped-freeze'\">\n <th mat-header-cell *matHeaderCellDef class=\"group-header-cell ungrouped-header-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'ungrouped-hide'\">\n <th mat-header-cell *matHeaderCellDef class=\"group-header-cell ungrouped-header-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'ungrouped-pin'\">\n <th mat-header-cell *matHeaderCellDef class=\"group-header-cell ungrouped-header-cell\"></th>\n </ng-container>\n }\n <!-- Filter row columns for data columns -->\n @for (ids of headersFiltersIds; track ids; let i = $index) {\n <ng-container [matColumnDef]=\"ids\" [sticky]=\"columnsArray[$index].pinned === 'left'\" [stickyEnd]=\"columnsArray[$index].pinned === 'right'\">\n <th mat-header-cell *matHeaderCellDef [style.minWidth]=\"columnsArray[$index].width\" [style.maxWidth]=\"columnsArray[$index].maxWidth?columnsArray[$index].maxWidth:columnsArray[$index].width\"\n [style.minWidth]=\"columnsArray[$index].minWidth\" >\n <div style=\"display: block; width: 100%;\" class=\"filters-container\" [class.animate]=\"toggleFilters\">\n <app-filter-columns-component style=\"display: block; width: 100%;\" [obj]=\"columnsArray[returnIndex(ids)]\"\n (filterOutput)=\"applyColumnFilter($event,columnsArray[returnIndex(ids)])\"></app-filter-columns-component>\n </div>\n </th>\n </ng-container>\n }\n <!-- Empty filter cells for action columns -->\n <ng-container [matColumnDef]=\"'filter-select'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'filter-edit'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'filter-popup'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'filter-delete'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'filter-freeze'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'filter-hide'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'filter-pin'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n @if (columnGroups.length > 0) {\n <tr mat-header-row *matHeaderRowDef=\"getGroupedColumns(); sticky: stickyHeader\" class=\"mat-mdc-header-row group-header-row\"></tr>\n }\n <tr mat-header-row *matHeaderRowDef=\" getDisplayedColumns(); sticky: stickyHeader\" class=\"mat-mdc-header-row\"></tr>\n <tr style=\"height: 0px;\" mat-header-row class=\"no-default-height\" *matHeaderRowDef=\"getFilterColumns()\">\n </tr>\n \n <tr mat-row *matRowDef=\"let row; columns:getDisplayedColumns(); let i=dataIndex; \" \n class=\"mat-mdc-row data-row\"\n [ngClass]=\"{\n 'data-row':expandRows,\n 'stripedRows':(stripedRows && i % 2 == 1),\n 'hoverClass':rowHover, \n 'hidden':(hiddenCtrl.isSelected(row) && hideRows) || isRowHidden(i),\n 'example-expanded-row':expandedElement === row,\n 'pinned-row': isRowPinned(row),\n 'mat-row-sticky-top': isRowPinnedTop(row),\n 'mat-row-sticky-bottom': isRowPinnedBottom(row)\n }\"\n (click)=\"expandRow(row, row !== expandedElement,i)\">\n </tr>\n \n @if (expandRows) {\n <tr mat-row *matRowDef=\"let row; columns: ['expandedDetail']; let i=dataIndex\"\n class=\"example-detail-row\"\n [ngClass]=\"{'hidden': isRowHidden(i)}\">\n </tr>\n }\n @if (showFooterRow) {\n <tr mat-footer-row *matFooterRowDef=\"getDisplayedColumns(); sticky: stickyFooter\"></tr>\n }\n </table>\n </div>\n \n <table mat-table #matTable #MyTable [id]=\"'matTableExt'+tableID\" [dataSource]=\"dataSource\" matSort cdkDropList\n cdkDropListOrientation=\"horizontal\" multiTemplateDataRows (cdkDropListDropped)=\"onDrop($event)\"\n (click)=\"saveCellEditing()\" [style.width]=\"scrollbarH?'max-content':'100%'\" \n [class]=\"'mat-mdc-table' + (tableClassName ? ' ' + tableClassName : '')\">\n \n <!-- Row selection column -->\n <ng-container matColumnDef=\"select\">\n <th mat-header-cell *matHeaderCellDef cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"!dndColumns\">\n <mat-checkbox (change)=\"$event ? toggleAllRows() : null\"\n [checked]=\"selection.hasValue() && isAllSelected()\"\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\" [aria-label]=\"checkboxLabel()\">\n </mat-checkbox>\n </th>\n <td mat-cell *matCellDef=\"let row;let i = dataIndex\">\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? setSelectedRows(row,i) : null\"\n [checked]=\"selection.isSelected(row)\" [aria-label]=\"checkboxLabel(row)\">\n </mat-checkbox>\n </td>\n <ng-container *ngIf=\"showFooterRow\">\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n </ng-container>\n <!--dynamic columns are being generated here-->\n @for (column of columnsArray; track column.field + '_' + column.pinned; let i = $index) {\n <div matColumnDef=\"{{column['field']}}\" [sticky]=\"column.pinned === 'left'\" [stickyEnd]=\"column.pinned === 'right'\">\n <th mat-header-cell *matHeaderCellDef [style.minWidth]=\"column.width\" [style.maxWidth]=\"column.maxWidth?column.maxWidth:column.width\"\n [style.minWidth]=\"column.minWidth\" cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"!dndColumns\"\n [columnsResizable]=\"columnResizable\" [index]=\"i\" class=\"mat-mdc-header-cell\"\n [mat-sort-header]=\"column.field\" [disabled]=\"!sorting || column.disabled === true\">\n \n @if (column.headerTemplate || headerTemplateRef) {\n <ng-template [ngTemplateOutlet]=\"column.headerTemplate || headerTemplateRef\"\n [ngTemplateOutletContext]=\"{data:column}\"></ng-template>\n }\n @if (!headerTemplateRef && !column.headerTemplate) {\n <span matTooltip=\"{{column.headerTooltip?.value}}\"\n [matTooltipPosition]=\"column?.headerTooltip?.tooltipPosition!\"\n [class.disabled]=\"!sorting || column.disabled === true\">{{column.header}}</span>\n }\n </th>\n <td mat-cell *matCellDef=\"let row ;let i=dataIndex\" class=\"mat-mdc-cell\">\n @if (!row.editable && !cellEditing[i +'_'+column.field]) {\n <div (dblclick)=\"cellEditing[i +'_'+column.field] = inCellEditing;setCellData(row,i)\"\n (click)=\"cellPopupEditing ? openCellPopupDialog(row, column, i) : null\"\n [style.cursor]=\"cellPopupEditing ? 'pointer' : 'default'\"\n matTooltip=\"{{column.cellTooltip?.value}}\"\n [matTooltipPosition]=\"column?.cellTooltip?.tooltipPosition!\">\n @if (!cellTemplateRef && !column?.cellTemplate && !cellTemplateRefMap[column.field]) {\n <span>{{row[column.field]}}</span>\n }\n @if (cellTemplateRefMap[column.field]) {\n <ng-container [ngTemplateOutlet]=\"cellTemplateRefMap[column.field]\"\n [ngTemplateOutletContext]=\"{row:row,column:column,index:i}\">\n </ng-container>\n }\n @if (cellTemplateRef && column.cellTemplate && !cellTemplateRefMap[column.field]) {\n <ng-container [ngTemplateOutlet]=\"column.cellTemplate\"\n [ngTemplateOutletContext]=\"{row:row,column:column,index:i}\">\n </ng-container>\n }\n @if (!cellTemplateRef && column.cellTemplate && !cellTemplateRefMap[column.field]) {\n <ng-container [ngTemplateOutlet]=\"column.cellTemplate\"\n [ngTemplateOutletContext]=\"{row:row,column:column,index:i}\">\n </ng-container>\n }\n @if (cellTemplateRef && !column.cellTemplate && !cellTemplateRefMap[column.field]) {\n <ng-container [ngTemplateOutlet]=\"cellTemplateRef\"\n [ngTemplateOutletContext]=\"{row:row,column:column,index:i}\">\n </ng-container>\n }\n </div>\n }\n @if (row.editable || cellEditing[i +'_'+column.field]) {\n <div (click)=\"$event.stopPropagation()\">\n @if (inlineEditingTemplateRef && !cellEditing[i +'_'+column.field]) {\n <ng-container [ngTemplateOutlet]=\"inlineEditingTemplateRef\"\n [ngTemplateOutletContext]=\"{data:getInlineEditingData(row,i,column)}\"></ng-container>\n }\n @if (cellEditingTemplateRef && !(row.editable)) {\n <ng-container [ngTemplateOutlet]=\"cellEditingTemplateRef\"\n [ngTemplateOutletContext]=\"{data:getInlineEditingData(row,i,column)}\"></ng-container>\n }\n @if (!inlineEditingTemplateRef && (row.editable) && rowDataTemp['e'+i]) {\n @if (column.type == 'number') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"number\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'string') {\n <mat-form-field style=\"width: 100%;\" appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"text\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'textarea') {\n <mat-form-field style=\"width: 100%;\" appearance=\"outline\" class=\"inline-editing-field\">\n <textarea matInput rows=\"3\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\"></textarea>\n </mat-form-field>\n }\n @if (column.type == 'date') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"date\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'datepicker') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput [matDatepicker]=\"inlinePicker\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n <mat-datepicker-toggle matIconSuffix [for]=\"inlinePicker\"></mat-datepicker-toggle>\n <mat-datepicker #inlinePicker></mat-datepicker>\n </mat-form-field>\n }\n @if (column.type == 'selection') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-select [value]=\"rowDataTemp['e'+i][column.field]\"\n [(ngModel)]=\"rowDataTemp['e'+i][column.field]\">\n @for (option of column.options; track option) {\n <mat-option [value]=\"option\">{{option}}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n @if (column.type == 'boolean') {\n <mat-checkbox (click)=\"$event.stopPropagation()\" color=\"primary\" [(ngModel)]=\"row[column.field]\"></mat-checkbox>\n }\n }\n @if (!cellEditingTemplateRef && cellEditing[i +'_'+column.field]) {\n @if (column.type == 'number') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"number\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'string') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"text\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'textarea') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <textarea matInput rows=\"3\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\"></textarea>\n </mat-form-field>\n }\n @if (column.type == 'date') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"date\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'datepicker') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput [matDatepicker]=\"cellPicker\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n <mat-datepicker-toggle matIconSuffix [for]=\"cellPicker\"></mat-datepicker-toggle>\n <mat-datepicker #cellPicker></mat-datepicker>\n </mat-form-field>\n }\n @if (column.type == 'selection') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-select [value]=\"rowDataTemp['e'+i][column.field]\"\n [(ngModel)]=\"rowDataTemp['e'+i][column.field]\">\n @for (option of column.options; track option) {\n <mat-option [value]=\"option\">{{option}}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n @if (column.type == 'boolean') {\n <mat-checkbox (click)=\"$event.stopPropagation()\" color=\"primary\" [(ngModel)]=\"row[column.field]\"></mat-checkbox>\n }\n }\n </div>\n }\n </td>\n @if (showFooterRow) {\n <td mat-footer-cell *matFooterCellDef> {{column.footerText}} </td>\n }\n </div>\n }\n <ng-container matColumnDef=\"edit\" stickyEnd=\"false\">\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\n class=\"action-column-cells\"> Edit </th>\n <td mat-cell *matCellDef=\"let row; let i = dataIndex\" class=\"inline-edit-column-cell\">\n @if (!row.editable && !row.editmodal) {\n <mat-icon class=\"edit-column-icons\" aria-hidden=\"false\"\n (click)=\"enableInlineEditing(row,i)\" fontIcon=\"edit_note\">\n </mat-icon>\n }\n @if (row.editable && !row.editmodal) {\n <div class=\"inline-editing-controls\">\n <mat-icon class=\"edit-column-icons\" aria-hidden=\"false\" (click)=\"saveInlineEditing(row,i)\"\n fontIcon=\"done\"></mat-icon>\n <mat-icon class=\"edit-column-icons\" aria-hidden=\"false\" (click)=\"cancelInlineEditing(row,i)\"\n fontIcon=\"close\"></mat-icon>\n </div>\n }\n </td>\n <td mat-footer-cell *matFooterCellDef> edit </td>\n </ng-container>\n <ng-container matColumnDef=\"popup\" stickyEnd=\"false\">\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\n class=\"action-column-cells\"> Popup\n </th>\n <td mat-cell *matCellDef=\"let row; let i = index\">\n <mat-icon aria-hidden=\"false\" (click)=\"openEditingDialog(row)\" fontIcon=\"edit\">\n </mat-icon>\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n \n <ng-container matColumnDef=\"delete\">\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\n class=\"action-column-cells\"> Delete\n </th>\n <td mat-cell *matCellDef=\"let row;let i=dataIndex\">\n <mat-icon (click)=\"deleteRow(row,i)\" aria-hidden=\"false\" aria-label=\"Example home icon\"\n fontIcon=\"delete\">\n </mat-icon>\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n \n <ng-container matColumnDef=\"hide\" stickyEnd=\"false\">\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\n class=\"action-column-cells\"> Hide\n </th>\n <td mat-cell *matCellDef=\"let row;let i=dataIndex\">\n <button mat-icon-button (click)=\"toggleRowHide(i)\" \n [matTooltip]=\"isRowHidden(i) ? 'Unhide Row' : 'Hide Row'\"\n matTooltipPosition=\"above\">\n <mat-icon [color]=\"isRowHidden(i) ? 'primary' : ''\" aria-hidden=\"false\">\n {{ isRowHidden(i) ? 'visibility_off' : 'visibility' }}\n </mat-icon>\n </button>\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n \n <ng-container matColumnDef=\"pin\" stickyEnd=\"false\">\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\n class=\"action-column-cells\"> Pin\n </th>\n <td mat-cell *matCellDef=\"let row;let i=dataIndex\">\n <button mat-icon-button \n [matMenuTriggerFor]=\"pinMenu\"\n (click)=\"openRowPinMenu($event, row)\"\n [matTooltip]=\"getRowPinPosition(row) ? 'Pinned ' + getRowPinPosition(row) : 'Pin Row'\"\n matTooltipPosition=\"above\">\n <mat-icon [color]=\"isRowPinned(row) ? 'primary' : ''\" aria-hidden=\"false\">\n {{ isRowPinned(row) ? 'push_pin' : 'push_pin' }}\n </mat-icon>\n </button>\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n \n <!-- Expanded Content Column - The detail row is made up of this one column that spans across all columns -->\n @if (expandRows) {\n <ng-container matColumnDef=\"expandedDetail\">\n <td mat-cell *matCellDef=\"let element;let i=dataIndex \"\n [attr.colspan]=\"columnsToDisplayWithExpand.length\">\n <div class=\"example-element-detail\"\n [@detailExpand]=\"element == expandedElement ? 'expanded' : 'collapsed'\">\n @if (expansionTemplateRef) {\n <ng-container [ngTemplateOutlet]=\"expansionTemplateRef\"\n [ngTemplateOutletContext]=\"{$explicit:element,row:element,index:i}\">\n </ng-container>\n }\n </div>\n </td>\n </ng-container>\n }\n <!-- Column group headers -->\n <!-- @if (columnGroups.length > 0) {\n @for (group of columnGroups; track group.name) {\n <ng-container [matColumnDef]=\"'group-' + group.name\">\n <th mat-header-cell *matHeaderCellDef [attr.colspan]=\"group.colspan || group.columns.length\" \n class=\"group-header-cell\">\n <div class=\"group-header-content\">\n <span class=\"group-label\">{{group.label}}</span>\n </div>\n </th>\n </ng-container>\n }\n @for (column of columnsArray; track column.field) {\n <ng-container [matColumnDef]=\"'ungrouped-' + column.field\">\n <th mat-header-cell *matHeaderCellDef class=\"group-header-cell ungrouped-header-cell\">\n </th>\n </ng-container>\n }\n } -->\n <!-- @if (columnGroups.length > 0) {\n <tr mat-header-row *matHeaderRowDef=\"getGroupedColumns(); sticky: stickyHeader\" class=\"mat-mdc-header-row group-header-row\"></tr>\n } -->\n <tr style=\"display:none\" mat-header-row *matHeaderRowDef=\" getDisplayedColumns(); sticky: stickyHeader\" class=\"mat-mdc-header-row\"></tr>\n \n <!-- All Data Rows (with dynamic pinning classes) -->\n <!-- <tr mat-row *matRowDef=\"let row; columns:getDisplayedColumns(); let i=dataIndex;\" \n class=\"mat-mdc-row data-row\"\n [ngClass]=\"{\n 'data-row':expandRows,\n 'stripedRows':(stripedRows && i % 2 == 1),\n 'hoverClass':rowHover, \n 'hidden':(hiddenCtrl.isSelected(row) && hideRows) || isRowHidden(i),\n 'example-expanded-row':expandedElement === row,\n 'pinned-row': isRowPinned(row),\n 'pinned-top-row': isRowPinnedTop(row),\n 'pinned-bottom-row': isRowPinnedBottom(row)\n }\"\n (click)=\"expandRow(row, row !== expandedElement,i)\">\n </tr> -->\n <tr mat-row *matRowDef=\"let row; columns:getDisplayedColumns(); let i=dataIndex; \" \n class=\"mat-mdc-row data-row\"\n [ngClass]=\"{\n 'data-row':expandRows,\n 'stripedRows':(stripedRows && i % 2 == 1),\n 'hoverClass':rowHover, \n 'hidden':(hiddenCtrl.isSelected(row) && hideRows) || isRowHidden(i),\n 'example-expanded-row':expandedElement === row,\n 'pinned-row': isRowPinned(row),\n 'mat-row-sticky-top': isRowPinnedTop(row),\n 'mat-row-sticky-bottom': isRowPinnedBottom(row)\n }\"\n (click)=\"expandRow(row, row !== expandedElement,i)\">\n </tr>\n <!-- <tr mat-header-row *matHeaderRowDef=\"let row; columns:getDisplayedColumns(); let i=dataIndex; when: isRowPinnedTop(row)\" \n class=\"mat-mdc-row data-row\"\n class=\"mat-mdc-header-row\"\n [ngClass]=\"{\n 'data-row':expandRows,\n 'stripedRows':(stripedRows && i % 2 == 1),\n 'hoverClass':rowHover, \n 'hidden':(hiddenCtrl.isSelected(row) && hideRows) || isRowHidden(i),\n 'example-expanded-row':expandedElement === row,\n 'pinned-row': isRowPinned(row),\n 'pinned-top-row': isRowPinnedTop(row),\n 'pinned-bottom-row': isRowPinnedBottom(row)\n }\"\n (click)=\"expandRow(row, row !== expandedElement,i)\">\n </tr> -->\n \n @if (expandRows) {\n <tr mat-row *matRowDef=\"let row; columns: ['expandedDetail']; let i=dataIndex\"\n class=\"example-detail-row\"\n [ngClass]=\"{'hidden': isRowHidden(i)}\">\n </tr>\n }\n @if (showFooterRow) {\n <tr mat-footer-row *matFooterRowDef=\"getDisplayedColumns(); sticky: stickyFooter\"></tr>\n }\n </table>\n @if (pinnedBtmDataSource && pinnedBtmDataSource.data.length > 0) {\n <div [style.max-height]=\"bottomPinnedMaxHeight\" [style.overflow]=\"bottomPinnedMaxHeight ? 'auto' : 'visible'\" \n [style.position]=\"'sticky'\" [style.bottom]=\"'0'\" [style.z-index]=\"'111'\">\n <table style=\"width: 100%;\" mat-table #matTable #MyTable [id]=\"'matTableExtBtm'+tableID\" [dataSource]=\"pinnedBtmDataSource\" matSort cdkDropList\n cdkDropListOrientation=\"horizontal\" multiTemplateDataRows (cdkDropListDropped)=\"onDrop($event)\"\n (click)=\"saveCellEditing()\" [style.width]=\"scrollbarH?'max-content':'100%'\" \n [class]=\"'mat-mdc-table' + (tableClassName ? ' ' + tableClassName : '')\">\n \n <!-- Row selection column -->\n <ng-container matColumnDef=\"select\">\n <th mat-header-cell *matHeaderCellDef cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"!dndColumns\">\n <mat-checkbox (change)=\"$event ? toggleAllRows() : null\"\n [checked]=\"selection.hasValue() && isAllSelected()\"\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\" [aria-label]=\"checkboxLabel()\">\n </mat-checkbox>\n </th>\n <td mat-cell *matCellDef=\"let row;let i = dataIndex\">\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? setSelectedRows(row,i) : null\"\n [checked]=\"selection.isSelected(row)\" [aria-label]=\"checkboxLabel(row)\">\n </mat-checkbox>\n </td>\n <ng-container *ngIf=\"showFooterRow\">\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n </ng-container>\n <!--dynamic columns are being generated here-->\n @for (column of columnsArray; track column.field + '_' + column.pinned; let i = $index) {\n <div matColumnDef=\"{{column['field']}}\" [sticky]=\"column.pinned === 'left'\" [stickyEnd]=\"column.pinned === 'right'\">\n <th mat-header-cell *matHeaderCellDef [style.minWidth]=\"column.width\" [style.maxWidth]=\"column.maxWidth?column.maxWidth:column.width\"\n [style.minWidth]=\"column.minWidth\" cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"!dndColumns\"\n [columnsResizable]=\"columnResizable\" [index]=\"i\" class=\"mat-mdc-header-cell\"\n [mat-sort-header]=\"column.field\" [disabled]=\"!sorting || column.disabled === true\">\n \n @if (column.headerTemplate || headerTemplateRef) {\n <ng-template [ngTemplateOutlet]=\"column.headerTemplate || headerTemplateRef\"\n [ngTemplateOutletContext]=\"{data:column}\"></ng-template>\n }\n @if (!headerTemplateRef && !column.headerTemplate) {\n <span matTooltip=\"{{column.headerTooltip?.value}}\"\n [matTooltipPosition]=\"column?.headerTooltip?.tooltipPosition!\"\n [class.disabled]=\"!sorting || column.disabled === true\">{{column.header}}</span>\n }\n </th>\n <td mat-cell *matCellDef=\"let row ;let i=dataIndex\" class=\"mat-mdc-cell\">\n @if (!row.editable && !cellEditing[i +'_'+column.field]) {\n <div [style.cursor]=\"'default'\"\n matTooltip=\"{{column.cellTooltip?.value}}\"\n [matTooltipPosition]=\"column?.cellTooltip?.tooltipPosition!\">\n @if (!cellTemplateRef && !column?.cellTemplate && !cellTemplateRefMap[column.field]) {\n <span>{{row[column.field]}}</span>\n }\n @if (cellTemplateRefMap[column.field]) {\n <ng-container [ngTemplateOutlet]=\"cellTemplateRefMap[column.field]\"\n [ngTemplateOutletContext]=\"{row:row,column:column,index:i}\">\n </ng-container>\n }\n @if (cellTemplateRef && column.cellTemplate && !cellTemplateRefMap[column.field]) {\n <ng-container [ngTemplateOutlet]=\"column.cellTemplate\"\n [ngTemplateOutletContext]=\"{row:row,column:column,index:i}\">\n </ng-container>\n }\n @if (!cellTemplateRef && column.cellTemplate && !cellTemplateRefMap[column.field]) {\n <ng-container [ngTemplateOutlet]=\"column.cellTemplate\"\n [ngTemplateOutletContext]=\"{row:row,column:column,index:i}\">\n </ng-container>\n }\n @if (cellTemplateRef && !column.cellTemplate && !cellTemplateRefMap[column.field]) {\n <ng-container [ngTemplateOutlet]=\"cellTemplateRef\"\n [ngTemplateOutletContext]=\"{row:row,column:column,index:i}\">\n </ng-container>\n }\n </div>\n }\n @if (row.editable || cellEditing[i +'_'+column.field]) {\n <div (click)=\"$event.stopPropagation()\">\n @if (inlineEditingTemplateRef && !cellEditing[i +'_'+column.field]) {\n <ng-container [ngTemplateOutlet]=\"inlineEditingTemplateRef\"\n [ngTemplateOutletContext]=\"{data:getInlineEditingData(row,i,column)}\"></ng-container>\n }\n @if (cellEditingTemplateRef && !(row.editable)) {\n <ng-container [ngTemplateOutlet]=\"cellEditingTemplateRef\"\n [ngTemplateOutletContext]=\"{data:getInlineEditingData(row,i,column)}\"></ng-container>\n }\n @if (!inlineEditingTemplateRef && (row.editable) && rowDataTemp['e'+i]) {\n @if (column.type == 'number') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"number\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'string') {\n <mat-form-field style=\"width: 100%;\" appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"text\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'textarea') {\n <mat-form-field style=\"width: 100%;\" appearance=\"outline\" class=\"inline-editing-field\">\n <textarea matInput rows=\"3\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\"></textarea>\n </mat-form-field>\n }\n @if (column.type == 'date') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"date\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'datepicker') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput [matDatepicker]=\"inlinePicker\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n <mat-datepicker-toggle matIconSuffix [for]=\"inlinePicker\"></mat-datepicker-toggle>\n <mat-datepicker #inlinePicker></mat-datepicker>\n </mat-form-field>\n }\n @if (column.type == 'selection') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-select [value]=\"rowDataTemp['e'+i][column.field]\"\n [(ngModel)]=\"rowDataTemp['e'+i][column.field]\">\n @for (option of column.options; track option) {\n <mat-option [value]=\"option\">{{option}}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n @if (column.type == 'boolean') {\n <mat-checkbox (click)=\"$event.stopPropagation()\" color=\"primary\" [(ngModel)]=\"row[column.field]\"></mat-checkbox>\n }\n }\n @if (!cellEditingTemplateRef && cellEditing[i +'_'+column.field]) {\n @if (column.type == 'number') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"number\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'string') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"text\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'textarea') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <textarea matInput rows=\"3\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\"></textarea>\n </mat-form-field>\n }\n @if (column.type == 'date') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"date\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'datepicker') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput [matDatepicker]=\"cellPicker\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n <mat-datepicker-toggle matIconSuffix [for]=\"cellPicker\"></mat-datepicker-toggle>\n <mat-datepicker #cellPicker></mat-datepicker>\n </mat-form-field>\n }\n @if (column.type == 'selection') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-select [value]=\"rowDataTemp['e'+i][column.field]\"\n [(ngModel)]=\"rowDataTemp['e'+i][column.field]\">\n @for (option of column.options; track option) {\n <mat-option [value]=\"option\">{{option}}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n @if (column.type == 'boolean') {\n <mat-checkbox (click)=\"$event.stopPropagation()\" color=\"primary\" [(ngModel)]=\"row[column.field]\"></mat-checkbox>\n }\n }\n </div>\n }\n </td>\n @if (showFooterRow) {\n <td mat-footer-cell *matFooterCellDef> {{column.footerText}} </td>\n }\n </div>\n }\n <ng-container matColumnDef=\"edit\" stickyEnd=\"false\">\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\n class=\"action-column-cells\"> Edit </th>\n <td mat-cell *matCellDef=\"let row; let i = dataIndex\" class=\"inline-edit-column-cell\">\n <!-- Edit disabled in pinned bottom table -->\n </td>\n <td mat-footer-cell *matFooterCellDef> edit </td>\n </ng-container>\n <ng-container matColumnDef=\"popup\" stickyEnd=\"false\">\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\n class=\"action-column-cells\"> Popup\n </th>\n <td mat-cell *matCellDef=\"let row; let i = index\">\n <!-- Popup edit disabled in pinned bottom table -->\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n \n <ng-container matColumnDef=\"delete\">\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\n class=\"action-column-cells\"> Delete\n </th>\n <td mat-cell *matCellDef=\"let row;let i=dataIndex\">\n <mat-icon (click)=\"deleteRow(row,i)\" aria-hidden=\"false\" aria-label=\"Example home icon\"\n fontIcon=\"delete\">\n </mat-icon>\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n \n <ng-container matColumnDef=\"hide\" stickyEnd=\"false\">\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\n class=\"action-column-cells\"> Hide\n </th>\n <td mat-cell *matCellDef=\"let row;let i=dataIndex\">\n <button mat-icon-button (click)=\"toggleRowHide(i)\" \n [matTooltip]=\"isRowHidden(i) ? 'Unhide Row' : 'Hide Row'\"\n matTooltipPosition=\"above\">\n <mat-icon [color]=\"isRowHidden(i) ? 'primary' : ''\" aria-hidden=\"false\">\n {{ isRowHidden(i) ? 'visibility_off' : 'visibility' }}\n </mat-icon>\n </button>\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n \n <ng-container matColumnDef=\"pin\" stickyEnd=\"false\">\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\n class=\"action-column-cells\"> Pin\n </th>\n <td mat-cell *matCellDef=\"let row;let i=dataIndex\">\n <button mat-icon-button \n [matMenuTriggerFor]=\"pinMenu\"\n (click)=\"openRowPinMenu($event, row)\"\n [matTooltip]=\"getRowPinPosition(row) ? 'Pinned ' + getRowPinPosition(row) : 'Pin Row'\"\n matTooltipPosition=\"above\">\n <mat-icon [color]=\"isRowPinned(row) ? 'primary' : ''\" aria-hidden=\"false\">\n {{ isRowPinned(row) ? 'push_pin' : 'push_pin' }}\n </mat-icon>\n </button>\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n \n <!-- Expanded Content Column - The detail row is made up of this one column that spans across all columns -->\n @if (expandRows) {\n <ng-container matColumnDef=\"expandedDetail\">\n <td mat-cell *matCellDef=\"let element;let i=dataIndex \"\n [attr.colspan]=\"columnsToDisplayWithExpand.length\">\n <div class=\"example-element-detail\"\n [@detailExpand]=\"element == expandedElement ? 'expanded' : 'collapsed'\">\n @if (expansionTemplateRef) {\n <ng-container [ngTemplateOutlet]=\"expansionTemplateRef\"\n [ngTemplateOutletContext]=\"{$explicit:element,row:element,index:i}\">\n </ng-container>\n }\n </div>\n </td>\n </ng-container>\n }\n <!-- Column group headers -->\n @if (columnGroups.length > 0) {\n @for (group of columnGroups; track group.name) {\n <ng-container [matColumnDef]=\"'group-' + group.name\">\n <th mat-header-cell *matHeaderCellDef [attr.colspan]=\"group.colspan || group.columns.length\" \n class=\"group-header-cell\">\n <div class=\"group-header-content\">\n <span class=\"group-label\">{{group.label}}</span>\n </div>\n </th>\n </ng-container>\n }\n <!-- Empty header cells for ungrouped columns -->\n @for (column of columnsArray; track column.field) {\n <ng-container [matColumnDef]=\"'ungrouped-' + column.field\">\n <th mat-header-cell *matHeaderCellDef class=\"group-header-cell ungrouped-header-cell\">\n </th>\n </ng-container>\n }\n }\n <!-- Empty filter cells for action columns -->\n <ng-container [matColumnDef]=\"'filter-select'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'filter-edit'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'filter-popup'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'filter-delete'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'filter-freeze'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'filter-hide'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'filter-pin'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n @if (columnGroups.length > 0) {\n <tr mat-header-row *matHeaderRowDef=\"getGroupedColumns(); sticky: stickyHeader\" class=\"mat-mdc-header-row group-header-row\"></tr>\n }\n <!-- <tr mat-header-row *matHeaderRowDef=\" getDisplayedColumns(); sticky: stickyHeader\" class=\"mat-mdc-header-row\"></tr> -->\n <tr style=\"display:none\" mat-header-row *matHeaderRowDef=\" getDisplayedColumns(); sticky: stickyHeader\" class=\"mat-mdc-header-row\"></tr>\n \n <!-- All Data Rows (with dynamic pinning classes) -->\n <!-- <tr mat-row *matRowDef=\"let row; columns:getDisplayedColumns(); let i=dataIndex;\" \n class=\"mat-mdc-row data-row\"\n [ngClass]=\"{\n 'data-row':expandRows,\n 'stripedRows':(stripedRows && i % 2 == 1),\n 'hoverClass':rowHover, \n 'hidden':(hiddenCtrl.isSelected(row) && hideRows) || isRowHidden(i),\n 'example-expanded-row':expandedElement === row,\n 'pinned-row': isRowPinned(row),\n 'pinned-top-row': isRowPinnedTop(row),\n 'pinned-bottom-row': isRowPinnedBottom(row)\n }\"\n (click)=\"expandRow(row, row !== expandedElement,i)\">\n </tr> -->\n <tr mat-row *matRowDef=\"let row; columns:getDisplayedColumns(); let i=dataIndex; \" \n class=\"mat-mdc-row data-row\"\n [ngClass]=\"{\n 'data-row':expandRows,\n 'stripedRows':(stripedRows && i % 2 == 1),\n 'hoverClass':rowHover, \n 'hidden':(hiddenCtrl.isSelected(row) && hideRows) || isRowHidden(i),\n 'example-expanded-row':expandedElement === row,\n 'pinned-row': isRowPinned(row),\n 'mat-row-sticky-top': isRowPinnedTop(row),\n 'mat-row-sticky-bottom': isRowPinnedBottom(row)\n }\"\n (click)=\"expandRow(row, row !== expandedElement,i)\">\n </tr>\n <!-- <tr mat-header-row *matHeaderRowDef=\"let row; columns:getDisplayedColumns(); let i=dataIndex; when: isRowPinnedTop(row)\" \n class=\"mat-mdc-row data-row\"\n class=\"mat-mdc-header-row\"\n [ngClass]=\"{\n 'data-row':expandRows,\n 'stripedRows':(stripedRows && i % 2 == 1),\n 'hoverClass':rowHover, \n 'hidden':(hiddenCtrl.isSelected(row) && hideRows) || isRowHidden(i),\n 'example-expanded-row':expandedElement === row,\n 'pinned-row': isRowPinned(row),\n 'pinned-top-row': isRowPinnedTop(row),\n 'pinned-bottom-row': isRowPinnedBottom(row)\n }\"\n (click)=\"expandRow(row, row !== expandedElement,i)\">\n </tr> -->\n \n @if (expandRows) {\n <tr mat-row *matRowDef=\"let row; columns: ['expandedDetail']; let i=dataIndex\"\n class=\"example-detail-row\"\n [ngClass]=\"{'hidden': isRowHidden(i)}\">\n </tr>\n }\n @if (showFooterRow) {\n <tr mat-footer-row *matFooterRowDef=\"getDisplayedColumns(); sticky: stickyFooter\"></tr>\n }\n </table>\n </div>\n }\n }\n @else{\n <table mat-table #matTable #MyTable [id]=\"'matTableExt'+tableID\" [dataSource]=\"dataSource\" matSort cdkDropList\n cdkDropListOrientation=\"horizontal\" multiTemplateDataRows (cdkDropListDropped)=\"onDrop($event)\"\n (click)=\"saveCellEditing()\" [style.width]=\"scrollbarH?'max-content':'100%'\" \n [class]=\"'mat-mdc-table' + (tableClassName ? ' ' + tableClassName : '')\">\n \n <!-- Row selection column -->\n <ng-container matColumnDef=\"select\">\n <th mat-header-cell *matHeaderCellDef cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"!dndColumns\">\n <mat-checkbox (change)=\"$event ? toggleAllRows() : null\"\n [checked]=\"selection.hasValue() && isAllSelected()\"\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\" [aria-label]=\"checkboxLabel()\">\n </mat-checkbox>\n </th>\n <td mat-cell *matCellDef=\"let row;let i = dataIndex\">\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? setSelectedRows(row,i) : null\"\n [checked]=\"selection.isSelected(row)\" [aria-label]=\"checkboxLabel(row)\">\n </mat-checkbox>\n </td>\n <ng-container *ngIf=\"showFooterRow\">\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n </ng-container>\n <!--dynamic columns are being generated here-->\n @for (column of columnsArray; track column.field + '_' + column.pinned; let i = $index) {\n <div matColumnDef=\"{{column['field']}}\" [sticky]=\"column.pinned === 'left'\" [stickyEnd]=\"column.pinned === 'right'\">\n <th mat-header-cell *matHeaderCellDef [style.minWidth]=\"column.width\" [style.maxWidth]=\"column.maxWidth?column.maxWidth:column.width\"\n [style.minWidth]=\"column.minWidth\" cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"!dndColumns\"\n [columnsResizable]=\"columnResizable\" [index]=\"i\" class=\"mat-mdc-header-cell\"\n [mat-sort-header]=\"column.field\" [disabled]=\"!sorting || column.disabled === true\">\n \n @if (column.headerTemplate || headerTemplateRef) {\n <ng-template [ngTemplateOutlet]=\"column.headerTemplate || headerTemplateRef\"\n [ngTemplateOutletContext]=\"{data:column}\"></ng-template>\n }\n @if (!headerTemplateRef && !column.headerTemplate) {\n <span matTooltip=\"{{column.headerTooltip?.value}}\"\n [matTooltipPosition]=\"column?.headerTooltip?.tooltipPosition!\"\n [class.disabled]=\"!sorting || column.disabled === true\">{{column.header}}</span>\n }\n </th>\n <td mat-cell *matCellDef=\"let row ;let i=dataIndex\" class=\"mat-mdc-cell\">\n @if (!row.editable && !cellEditing[i +'_'+column.field]) {\n <div (dblclick)=\"cellEditing[i +'_'+column.field] = inCellEditing;setCellData(row,i)\"\n (click)=\"cellPopupEditing ? openCellPopupDialog(row, column, i) : null\"\n [style.cursor]=\"cellPopupEditing ? 'pointer' : 'default'\"\n matTooltip=\"{{column.cellTooltip?.value}}\"\n [matTooltipPosition]=\"column?.cellTooltip?.tooltipPosition!\">\n @if (!cellTemplateRef && !column?.cellTemplate && !cellTemplateRefMap[column.field]) {\n <span>{{row[column.field]}}</span>\n }\n @if (cellTemplateRefMap[column.field]) {\n <ng-container [ngTemplateOutlet]=\"cellTemplateRefMap[column.field]\"\n [ngTemplateOutletContext]=\"{row:row,column:column,index:i}\">\n </ng-container>\n }\n @if (cellTemplateRef && column.cellTemplate && !cellTemplateRefMap[column.field]) {\n <ng-container [ngTemplateOutlet]=\"column.cellTemplate\"\n [ngTemplateOutletContext]=\"{row:row,column:column,index:i}\">\n </ng-container>\n }\n @if (!cellTemplateRef && column.cellTemplate && !cellTemplateRefMap[column.field]) {\n <ng-container [ngTemplateOutlet]=\"column.cellTemplate\"\n [ngTemplateOutletContext]=\"{row:row,column:column,index:i}\">\n </ng-container>\n }\n @if (cellTemplateRef && !column.cellTemplate && !cellTemplateRefMap[column.field]) {\n <ng-container [ngTemplateOutlet]=\"cellTemplateRef\"\n [ngTemplateOutletContext]=\"{row:row,column:column,index:i}\">\n </ng-container>\n }\n </div>\n }\n @if (row.editable || cellEditing[i +'_'+column.field]) {\n <div (click)=\"$event.stopPropagation()\">\n @if (inlineEditingTemplateRef && !cellEditing[i +'_'+column.field]) {\n <ng-container [ngTemplateOutlet]=\"inlineEditingTemplateRef\"\n [ngTemplateOutletContext]=\"{data:getInlineEditingData(row,i,column)}\"></ng-container>\n }\n @if (cellEditingTemplateRef && !(row.editable)) {\n <ng-container [ngTemplateOutlet]=\"cellEditingTemplateRef\"\n [ngTemplateOutletContext]=\"{data:getInlineEditingData(row,i,column)}\"></ng-container>\n }\n @if (!inlineEditingTemplateRef && (row.editable) && rowDataTemp['e'+i]) {\n @if (column.type == 'number') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"number\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'string') {\n <mat-form-field style=\"width: 100%;\" appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"text\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'textarea') {\n <mat-form-field style=\"width: 100%;\" appearance=\"outline\" class=\"inline-editing-field\">\n <textarea matInput rows=\"3\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\"></textarea>\n </mat-form-field>\n }\n @if (column.type == 'date') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"date\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'datepicker') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput [matDatepicker]=\"inlinePicker\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n <mat-datepicker-toggle matIconSuffix [for]=\"inlinePicker\"></mat-datepicker-toggle>\n <mat-datepicker #inlinePicker></mat-datepicker>\n </mat-form-field>\n }\n @if (column.type == 'selection') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-select [value]=\"rowDataTemp['e'+i][column.field]\"\n [(ngModel)]=\"rowDataTemp['e'+i][column.field]\">\n @for (option of column.options; track option) {\n <mat-option [value]=\"option\">{{option}}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n @if (column.type == 'boolean') {\n <mat-checkbox (click)=\"$event.stopPropagation()\" color=\"primary\" [(ngModel)]=\"row[column.field]\"></mat-checkbox>\n }\n }\n @if (!cellEditingTemplateRef && cellEditing[i +'_'+column.field]) {\n @if (column.type == 'number') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"number\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'string') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"text\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'textarea') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <textarea matInput rows=\"3\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\"></textarea>\n </mat-form-field>\n }\n @if (column.type == 'date') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput type=\"date\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n </mat-form-field>\n }\n @if (column.type == 'datepicker') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <input matInput [matDatepicker]=\"cellPicker\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\n [ngModelOptions]=\"{standalone: true}\">\n <mat-datepicker-toggle matIconSuffix [for]=\"cellPicker\"></mat-datepicker-toggle>\n <mat-datepicker #cellPicker></mat-datepicker>\n </mat-form-field>\n }\n @if (column.type == 'selection') {\n <mat-form-field appearance=\"outline\" class=\"inline-editing-field\">\n <mat-select [value]=\"rowDataTemp['e'+i][column.field]\"\n [(ngModel)]=\"rowDataTemp['e'+i][column.field]\">\n @for (option of column.options; track option) {\n <mat-option [value]=\"option\">{{option}}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n @if (column.type == 'boolean') {\n <mat-checkbox (click)=\"$event.stopPropagation()\" color=\"primary\" [(ngModel)]=\"row[column.field]\"></mat-checkbox>\n }\n }\n </div>\n }\n </td>\n @if (showFooterRow) {\n <td mat-footer-cell *matFooterCellDef> {{column.footerText}} </td>\n }\n </div>\n }\n <ng-container matColumnDef=\"edit\" stickyEnd=\"false\">\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\n class=\"action-column-cells\"> Edit </th>\n <td mat-cell *matCellDef=\"let row; let i = dataIndex\" class=\"inline-edit-column-cell\">\n @if (!row.editable && !row.editmodal) {\n <mat-icon class=\"edit-column-icons\" aria-hidden=\"false\"\n (click)=\"enableInlineEditing(row,i)\" fontIcon=\"edit_note\">\n </mat-icon>\n }\n @if (row.editable && !row.editmodal) {\n <div class=\"inline-editing-controls\">\n <mat-icon class=\"edit-column-icons\" aria-hidden=\"false\" (click)=\"saveInlineEditing(row,i)\"\n fontIcon=\"done\"></mat-icon>\n <mat-icon class=\"edit-column-icons\" aria-hidden=\"false\" (click)=\"cancelInlineEditing(row,i)\"\n fontIcon=\"close\"></mat-icon>\n </div>\n }\n </td>\n <td mat-footer-cell *matFooterCellDef> edit </td>\n </ng-container>\n <ng-container matColumnDef=\"popup\" stickyEnd=\"false\">\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\n class=\"action-column-cells\"> Popup\n </th>\n <td mat-cell *matCellDef=\"let row; let i = index\">\n <mat-icon aria-hidden=\"false\" (click)=\"openEditingDialog(row)\" fontIcon=\"edit\">\n </mat-icon>\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n \n <ng-container matColumnDef=\"delete\">\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\n class=\"action-column-cells\"> Delete\n </th>\n <td mat-cell *matCellDef=\"let row;let i=dataIndex\">\n <mat-icon (click)=\"deleteRow(row,i)\" aria-hidden=\"false\" aria-label=\"Example home icon\"\n fontIcon=\"delete\">\n </mat-icon>\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n \n <ng-container matColumnDef=\"hide\" stickyEnd=\"false\">\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\n class=\"action-column-cells\"> Hide\n </th>\n <td mat-cell *matCellDef=\"let row;let i=dataIndex\">\n <button mat-icon-button (click)=\"toggleRowHide(i)\" \n [matTooltip]=\"isRowHidden(i) ? 'Unhide Row' : 'Hide Row'\"\n matTooltipPosition=\"above\">\n <mat-icon [color]=\"isRowHidden(i) ? 'primary' : ''\" aria-hidden=\"false\">\n {{ isRowHidden(i) ? 'visibility_off' : 'visibility' }}\n </mat-icon>\n </button>\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n \n <ng-container matColumnDef=\"pin\" stickyEnd=\"false\">\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\n class=\"action-column-cells\"> Pinning\n </th>\n <td mat-cell *matCellDef=\"let row;let i=dataIndex\">\n <button mat-icon-button \n [matMenuTriggerFor]=\"pinMenu\"\n (click)=\"openRowPinMenu($event, row)\"\n [matTooltip]=\"getRowPinPosition(row) ? 'Pinned ' + getRowPinPosition(row) : 'Pin Row'\"\n matTooltipPosition=\"above\">\n <mat-icon [color]=\"isRowPinned(row) ? 'primary' : ''\" aria-hidden=\"false\">\n {{ isRowPinned(row) ? 'push_pin' : 'push_pin' }}\n </mat-icon>\n </button>\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n \n <!-- Expanded Content Column - The detail row is made up of this one column that spans across all columns -->\n @if (expandRows) {\n <ng-container matColumnDef=\"expandedDetail\">\n <td mat-cell *matCellDef=\"let element;let i=dataIndex \"\n [attr.colspan]=\"columnsToDisplayWithExpand.length\">\n <div class=\"example-element-detail\"\n [@detailExpand]=\"element == expandedElement ? 'expanded' : 'collapsed'\">\n @if (expansionTemplateRef) {\n <ng-container [ngTemplateOutlet]=\"expansionTemplateRef\"\n [ngTemplateOutletContext]=\"{$explicit:element,row:element,index:i}\">\n </ng-container>\n }\n </div>\n </td>\n </ng-container>\n }\n <!-- Column group headers -->\n @if (columnGroups.length > 0) {\n @for (group of columnGroups; track group.name) {\n <ng-container [matColumnDef]=\"'group-' + group.name\">\n <th mat-header-cell *matHeaderCellDef [attr.colspan]=\"group.colspan || group.columns.length\" \n class=\"group-header-cell\">\n <div class=\"group-header-content\">\n <span class=\"group-label\">{{group.label}}</span>\n </div>\n </th>\n </ng-container>\n }\n <!-- Empty header cells for ungrouped columns -->\n <ng-container *ngFor=\"let column of columnsArray\">\n <ng-container [matColumnDef]=\"'ungrouped-' + column.field\">\n <th mat-header-cell *matHeaderCellDef class=\"group-header-cell ungrouped-header-cell\">\n </th>\n </ng-container>\n </ng-container>\n }\n <!-- Filter row columns for data columns -->\n <ng-container *ngFor=\"let ids of headersFiltersIds; let i = index\">\n <ng-container [matColumnDef]=\"ids\" [sticky]=\"columnsArray[returnIndex(ids)].pinned === 'left'\" [stickyEnd]=\"columnsArray[returnIndex(ids)].pinned === 'right'\">\n <th mat-header-cell *matHeaderCellDef [style.minWidth]=\"columnsArray[returnIndex(ids)].width\" [style.maxWidth]=\"columnsArray[returnIndex(ids)].maxWidth?columnsArray[returnIndex(ids)].maxWidth:columnsArray[returnIndex(ids)].width\"\n [style.minWidth]=\"columnsArray[returnIndex(ids)].minWidth\" >\n <div style=\"display: block; width: 100%;\" class=\"filters-container\" [class.animate]=\"toggleFilters\">\n <app-filter-columns-component style=\"display: block; width: 100%;\" [obj]=\"columnsArray[returnIndex(ids)]\"\n (filterOutput)=\"applyColumnFilter($event,columnsArray[returnIndex(ids)])\"></app-filter-columns-component>\n </div>\n </th>\n </ng-container>\n </ng-container>\n\n <!-- Empty filter cells for action columns -->\n <ng-container [matColumnDef]=\"'filter-select'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'filter-edit'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'filter-popup'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'filter-delete'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'filter-freeze'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'filter-hide'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n <ng-container [matColumnDef]=\"'filter-pin'\">\n <th mat-header-cell *matHeaderCellDef class=\"filter-placeholder-cell\"></th>\n </ng-container>\n\n <ng-container *ngIf=\"columnGroups.length > 0\">\n <tr mat-header-row *matHeaderRowDef=\"getGroupedColumns(); sticky: stickyHeader\" class=\"mat-mdc-header-row group-header-row\"></tr>\n </ng-container>\n <tr mat-header-row *matHeaderRowDef=\" getDisplayedColumns(); sticky: stickyHeader\" class=\"mat-mdc-header-row\"></tr>\n <tr style=\"height: 0px;\" mat-header-row class=\"no-default-height\" *matHeaderRowDef=\"getFilterColumns()\">\n </tr>\n \n <!-- All Data Rows (with dynamic pinning classes) -->\n <!-- <tr mat-row *matRowDef=\"let row; columns:getDisplayedColumns(); let i=dataIndex;\" \n class=\"mat-mdc-row data-row\"\n [ngClass]=\"{\n 'data-row':expandRows,\n 'stripedRows':(stripedRows && i % 2 == 1),\n 'hoverClass':rowHover, \n 'hidden':(hiddenCtrl.isSelected(row) && hideRows) || isRowHidden(i),\n 'example-expanded-row':expandedElement === row,\n 'pinned-row': isRowPinned(row),\n 'pinned-top-row': isRowPinnedTop(row),\n 'pinned-bottom-row': isRowPinnedBottom(row)\n }\"\n (click)=\"expandRow(row, row !== expandedElement,i)\">\n </tr> -->\n <tr mat-row *matRowDef=\"let row; columns:getDisplayedColumns(); let i=dataIndex; \" \n class=\"mat-mdc-row data-row\"\n [ngClass]=\"{\n 'data-row':expandRows,\n 'stripedRows':(stripedRows && i % 2 == 1),\n 'hoverClass':rowHover, \n 'hidden':(hiddenCtrl.isSelected(row) && hideRows) || isRowHidden(i),\n 'example-expanded-row':expandedElement === row,\n 'pinned-row': isRowPinned(row),\n 'mat-row-sticky-top': isRowPinnedTop(row),\n 'mat-row-sticky-bottom': isRowPinnedBottom(row)\n }\"\n (click)=\"expandRow(row, row !== expandedElement,i)\">\n </tr>\n <!-- <tr mat-header-row *matHeaderRowDef=\"let row; columns:getDisplayedColumns(); let i=dataIndex; when: isRowPinnedTop(row)\" \n class=\"mat-mdc-row data-row\"\n class=\"mat-mdc-header-row\"\n [ngClass]=\"{\n 'data-row':expandRows,\n 'stripedRows':(stripedRows && i % 2 == 1),\n 'hoverClass':rowHover, \n 'hidden':(hiddenCtrl.isSelected(row) && hideRows) || isRowHidden(i),\n 'example-expanded-row':expandedElement === row,\n 'pinned-row': isRowPinned(row),\n 'pinned-top-row': isRowPinnedTop(row),\n 'pinned-bottom-row': isRowPinnedBottom(row)\n }\"\n (click)=\"expandRow(row, row !== expandedElement,i)\">\n </tr> -->\n \n @if (expandRows) {\n <tr mat-row *matRowDef=\"let row; columns: ['expandedDetail']; let i=dataIndex\"\n class=\"example-detail-row\"\n [ngClass]=\"{'hidden': isRowHidden(i)}\">\n </tr>\n }\n @if (showFooterRow) {\n <tr mat-footer-row *matFooterRowDef=\"getDisplayedColumns(); sticky: stickyFooter\"></tr>\n }\n </table>\n\n }\n \n </section>\n @if (showPaginator) {\n <mat-paginator [pageSizeOptions]=\"pageSizeOptions\"\n [showFirstLastButtons]=\"showFirstLastButtons\" class=\"mat-mdc-paginator\">\n </mat-paginator>\n }\n</div>", styles: [".custom-primary-color{color:#3f51b5!important;border-color:#3f51b5!important}table{min-width:100%}.mat-mdc-table-sticky-border-elem-right{border-left:1px solid #e0e0e0}.mat-mdc-table-sticky-border-elem-left{border-right:1px solid #e0e0e0}tr.example-detail-row{height:0!important;overflow:hidden}.example-element-detail{overflow:hidden;display:flex;transition:height .3s cubic-bezier(.4,0,.2,1);padding:0}.example-element-detail[style*=\"height: auto\"],.example-element-detail[style*=\"height: 1\"]{padding:10px 0}.hidden{display:none}.stripedRows{background:var(--mat-table-row-hover-state-layer-color, #eaeaea)!important}.hoverClass:hover{background:var(--mat-table-row-hover-state-layer-color, #dbdbdb)!important}.filters-container{overflow:hidden;transition:height .5s ease-in-out}.animate{max-height:max-content!important}.cell-popup-indicator{font-size:18px;color:var(--mat-sys-color-primary, #1976d2);cursor:pointer;-webkit-user-select:none;user-select:none;display:inline-block;transition:transform .2s}.cell-popup-indicator:hover{transform:scale(1.3);color:var(--mat-sys-color-primary-container, #1565c0)}.resize-handle{display:inline-block;border-right:2px solid var(--mat-table-outline-color, rgb(140, 140, 140));position:absolute;top:0;right:0;height:100%;cursor:col-resize;opacity:0}.resize-handle:hover{width:20px}table th:hover .resize-handle{opacity:1;transition:.3s ease-in-out}.mat-mdc-table.resizing{-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;user-select:none;cursor:col-resize}.mat-mdc-table .mat-mdc-header-cell{position:relative}.mat-mdc-table .mat-mdc-header-cell:not(:last-child) .resize-holder{cursor:col-resize;width:20px;height:100%;position:absolute;right:-10px;top:0;z-index:1}.toolbar-container{display:flex;padding:0 15px;gap:1rem;grid-auto-rows:10px;justify-content:flex-end;align-items:center}.mat-table-ext-container{width:100%;max-width:100%;overflow:auto}.column-headers{font-family:Roboto,Helvetica Neue,sans-serif}.example-spacer{flex:1 1 auto}.export-button .export-button-content{display:flex!important;align-items:center;justify-content:space-between;gap:4px;width:100%;padding:0 4px}.export-button .mat-button-wrapper{display:flex!important;width:8em;justify-content:space-around;align-items:center}.toolbar-menu-container{display:flex;flex-direction:column;margin:auto .8em;width:15em;height:20em}.inline-editing-field{padding:8px 0}.inline-editing-field div.mat-mdc-form-field-subscript-wrapper{display:none}.toolbar-menu-item{display:flex;height:3em}.toolbar-menu-checkbox{margin-left:8%}.toolbar-menu-checkbox.mat-checkbox{width:max-content;display:flex;align-items:center}.hide-button .mat-button-wrapper,.pin-button .mat-button-wrapper{display:flex!important;align-items:center;gap:5px}.pin-button .mat-icon{margin-right:2px}.pin-button,.hide-button{padding-right:10px!important}.hide-button,.pin-button,.export-button,.print-button{height:3em;border:2px solid currentColor!important}.print-button .mat-button-wrapper{display:flex!important;align-items:center;gap:5px}.showHide-menu-columns-list{height:10em;max-height:10em;overflow-y:auto}.mat-column-select{width:50px!important}.data-row td,.example-expanded-row td{border-bottom-width:0!important}.action-column-cells{width:40px;height:inherit}.inline-editing-controls{display:flex}.global-search-field{width:-webkit-fill-available}.mat-mdc-table{--mat-table-container-elevation: 0;--mat-table-row-hover-state-layer-color: var(--mat-sys-color-surface-variant);--mat-table-row-hover-state-layer-opacity: .08}.group-header-row{background-color:var(--mat-sys-color-surface-container-low, #f5f5f5)}.group-header-row .group-header-cell{text-align:center!important;font-weight:600;font-size:13px;letter-spacing:.5px;text-transform:uppercase;padding:12px 16px;position:relative}.group-header-row .group-header-cell.ungrouped-header-cell{min-height:48px}.group-header-row .group-header-cell .group-header-content{display:flex;align-items:center;justify-content:center;gap:8px;text-align:center}.group-header-row .group-header-cell .group-header-content .group-label{font-weight:600;text-align:center}.group-header-row .group-header-cell:after{content:\"\";position:absolute;bottom:-2px;left:0;right:0;height:2px;background:linear-gradient(90deg,transparent 0%,var(--mat-sys-color-primary, #1976d2) 50%,transparent 100%);opacity:.3}.frozen-row{position:sticky!important;z-index:10;background-color:var(--mat-sys-color-surface, #ffffff)!important;box-shadow:0 2px 4px #0000001a}.frozen-row:after{content:\"\";position:absolute;bottom:0;left:0;right:0;height:2px;background:linear-gradient(to right,var(--mat-sys-color-primary, #1976d2) 0%,transparent 100%)}.frozen-row-bottom{position:sticky!important;z-index:10;background-color:var(--mat-sys-color-surface, #ffffff)!important;box-shadow:0 -2px 4px #0000001a}.frozen-row-bottom:before{content:\"\";position:absolute;top:0;left:0;right:0;height:2px;background:linear-gradient(to right,var(--mat-sys-color-primary, #1976d2) 0%,transparent 100%)}.mat-mdc-header-cell{--mat-table-header-container-background-color: var(--mat-sys-color-surface);--mat-table-header-container-text-color: var(--mat-sys-color-on-surface)}.mat-mdc-cell{--mat-table-cell-container-background-color: var(--mat-sys-color-surface);--mat-table-cell-container-text-color: var(--mat-sys-color-on-surface)}.mat-mdc-row{--mat-table-row-container-background-color: var(--mat-sys-color-surface)}.mat-mdc-paginator{--mat-paginator-container-background-color: var(--mat-sys-color-surface);--mat-paginator-container-text-color: var(--mat-sys-color-on-surface)}.pinned-row{background:var(--mat-sys-color-surface, #ffffff);box-shadow:0 2px 4px #0000001a;position:sticky!important;z-index:10}.pinned-row.pinned-top-row{top:var(--pinned-row-top-offset, var(--pinned-top-base-offset, 0px))}.pinned-row.pinned-bottom-row{bottom:var(--pinned-row-bottom-offset, var(--pinned-bottom-base-offset, 0px))}.pinned-top-row:after{content:\"\";position:absolute;bottom:-2px;left:0;right:0;height:2px;background:linear-gradient(to bottom,rgba(0,0,0,.1),transparent)}.pinned-bottom-row:before{content:\"\";position:absolute;top:-2px;left:0;right:0;height:2px;background:linear-gradient(to top,rgba(0,0,0,.1),transparent)}\n"] }]
|
|
2699
|
+
}], ctorParameters: () => [{ type: i1$1.MatDialog }, { type: MatTableExtService }, { type: i3.FormBuilder }, { type: i4.DomSanitizer }, { type: i5$1.MatIconRegistry }, { type: i0.ChangeDetectorRef }], propDecorators: { menuTrigger: [{
|
|
2700
|
+
type: ViewChild,
|
|
2701
|
+
args: [MatMenuTrigger]
|
|
2702
|
+
}], columnMenuTrigger: [{
|
|
2703
|
+
type: ViewChild,
|
|
2704
|
+
args: ['columnMenuTrigger']
|
|
2705
|
+
}], paginator: [{
|
|
2706
|
+
type: ViewChild,
|
|
2707
|
+
args: [MatPaginator]
|
|
2708
|
+
}], sort: [{
|
|
2709
|
+
type: ViewChild,
|
|
2710
|
+
args: [MatSort]
|
|
2711
|
+
}], matTableRef: [{
|
|
2712
|
+
type: ViewChild,
|
|
2713
|
+
args: ['matTable', { read: ElementRef }]
|
|
2714
|
+
}], table: [{
|
|
2715
|
+
type: ViewChild,
|
|
2716
|
+
args: ['MyTable']
|
|
2717
|
+
}], tableElement: [{
|
|
2718
|
+
type: ViewChild,
|
|
2719
|
+
args: ['MyTable', { read: ElementRef }]
|
|
2720
|
+
}], dataSource: [{
|
|
2721
|
+
type: Input
|
|
2722
|
+
}], columns: [{
|
|
2723
|
+
type: Input
|
|
2724
|
+
}], columnResizable: [{
|
|
2725
|
+
type: Input
|
|
2726
|
+
}], stripedRows: [{
|
|
2727
|
+
type: Input
|
|
2728
|
+
}], rowHover: [{
|
|
2729
|
+
type: Input
|
|
2730
|
+
}], inlineRowEditing: [{
|
|
2731
|
+
type: Input
|
|
2732
|
+
}], inCellEditing: [{
|
|
2733
|
+
type: Input
|
|
2734
|
+
}], cellPopupEditing: [{
|
|
2735
|
+
type: Input
|
|
2736
|
+
}], popupRowEditing: [{
|
|
2737
|
+
type: Input
|
|
2738
|
+
}], enableDelete: [{
|
|
2739
|
+
type: Input
|
|
2740
|
+
}], rowSelection: [{
|
|
2741
|
+
type: Input
|
|
2742
|
+
}], multiRowSelection: [{
|
|
2743
|
+
type: Input
|
|
2744
|
+
}], stickyFooter: [{
|
|
2745
|
+
type: Input
|
|
2746
|
+
}], stickyHeader: [{
|
|
2747
|
+
type: Input
|
|
2748
|
+
}], showFooterRow: [{
|
|
2749
|
+
type: Input
|
|
2750
|
+
}], columnFilter: [{
|
|
2751
|
+
type: Input
|
|
2752
|
+
}], loadingIndicator: [{
|
|
2753
|
+
type: Input
|
|
2754
|
+
}], sorting: [{
|
|
2755
|
+
type: Input
|
|
2756
|
+
}], showToolbar: [{
|
|
2757
|
+
type: Input
|
|
2758
|
+
}], toolbarTitle: [{
|
|
2759
|
+
type: Input
|
|
2760
|
+
}], tableHeight: [{
|
|
2761
|
+
type: Input
|
|
2762
|
+
}], toolbarHeight: [{
|
|
2763
|
+
type: Input
|
|
2764
|
+
}], tableWidth: [{
|
|
2765
|
+
type: Input
|
|
2766
|
+
}], scrollbarH: [{
|
|
2767
|
+
type: Input
|
|
2768
|
+
}], toolbarTemplate: [{
|
|
2769
|
+
type: Input
|
|
2770
|
+
}], columnHidable: [{
|
|
2771
|
+
type: Input
|
|
2772
|
+
}], columnPinnable: [{
|
|
2773
|
+
type: Input
|
|
2774
|
+
}], globalSearch: [{
|
|
2775
|
+
type: Input
|
|
2776
|
+
}], expandRows: [{
|
|
2777
|
+
type: Input
|
|
2778
|
+
}], dndColumns: [{
|
|
2779
|
+
type: Input
|
|
2780
|
+
}], showPaginator: [{
|
|
2781
|
+
type: Input
|
|
2782
|
+
}], showFirstLastButtons: [{
|
|
2783
|
+
type: Input
|
|
2784
|
+
}], exportButtonEnable: [{
|
|
2785
|
+
type: Input
|
|
2786
|
+
}], printButtonEnable: [{
|
|
2787
|
+
type: Input
|
|
2788
|
+
}], pageSizeOptions: [{
|
|
2789
|
+
type: Input
|
|
2790
|
+
}], toolbarTemplateRef: [{
|
|
2791
|
+
type: Input
|
|
2792
|
+
}], headerTemplateRef: [{
|
|
2793
|
+
type: Input
|
|
2794
|
+
}], cellTemplateRef: [{
|
|
2795
|
+
type: Input
|
|
2796
|
+
}], expansionTemplateRef: [{
|
|
2797
|
+
type: Input
|
|
2798
|
+
}], popupEditingTemplateRef: [{
|
|
2799
|
+
type: Input
|
|
2800
|
+
}], inlineEditingTemplateRef: [{
|
|
2801
|
+
type: Input
|
|
2802
|
+
}], cellEditingTemplateRef: [{
|
|
2803
|
+
type: Input
|
|
2804
|
+
}], cellPopupEditingTemplateRef: [{
|
|
2805
|
+
type: Input
|
|
2806
|
+
}], cellTemplateRefMap: [{
|
|
2807
|
+
type: Input
|
|
2808
|
+
}], tableClassName: [{
|
|
2809
|
+
type: Input
|
|
2810
|
+
}], columnGroups: [{
|
|
2811
|
+
type: Input
|
|
2812
|
+
}], hiddenRowIndices: [{
|
|
2813
|
+
type: Input
|
|
2814
|
+
}], enableRowHiding: [{
|
|
2815
|
+
type: Input
|
|
2816
|
+
}], enableRowPinning: [{
|
|
2817
|
+
type: Input
|
|
2818
|
+
}], topPinnedMaxHeight: [{
|
|
2819
|
+
type: Input
|
|
2820
|
+
}], bottomPinnedMaxHeight: [{
|
|
2821
|
+
type: Input
|
|
2822
|
+
}], rowPinningFn: [{
|
|
2823
|
+
type: Input
|
|
2824
|
+
}], rowHidingFilterFn: [{
|
|
2825
|
+
type: Input
|
|
2826
|
+
}], pdfOrientation: [{
|
|
2827
|
+
type: Input
|
|
2828
|
+
}], inlineChange: [{
|
|
2829
|
+
type: Output
|
|
2830
|
+
}], cellChange: [{
|
|
2831
|
+
type: Output
|
|
2832
|
+
}], popupChange: [{
|
|
2833
|
+
type: Output
|
|
2834
|
+
}], rowDeleted: [{
|
|
2835
|
+
type: Output
|
|
2836
|
+
}], scroll: [{
|
|
2837
|
+
type: Output
|
|
2838
|
+
}], selectionChanged: [{
|
|
2839
|
+
type: Output
|
|
2840
|
+
}], expansionChange: [{
|
|
2841
|
+
type: Output
|
|
2842
|
+
}], rowPinningChange: [{
|
|
2843
|
+
type: Output
|
|
2844
|
+
}] } });
|
|
2845
|
+
|
|
2846
|
+
class MatTableExtModule {
|
|
2847
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.5", ngImport: i0, type: MatTableExtModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
2848
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.5", ngImport: i0, type: MatTableExtModule, imports: [CommonModule, i1$2.TranslateModule, MatTableModule,
|
|
2849
|
+
FormsModule,
|
|
2850
|
+
ReactiveFormsModule,
|
|
2851
|
+
MatNativeDateModule,
|
|
2852
|
+
A11yModule,
|
|
2853
|
+
CdkAccordionModule,
|
|
2854
|
+
ClipboardModule,
|
|
2855
|
+
CdkStepperModule,
|
|
2856
|
+
CdkTableModule,
|
|
2857
|
+
CdkTreeModule,
|
|
2858
|
+
DragDropModule,
|
|
2859
|
+
MatAutocompleteModule,
|
|
2860
|
+
MatBadgeModule,
|
|
2861
|
+
MatBottomSheetModule,
|
|
2862
|
+
MatButtonModule,
|
|
2863
|
+
MatButtonToggleModule,
|
|
2864
|
+
MatCardModule,
|
|
2865
|
+
MatCheckboxModule,
|
|
2866
|
+
MatChipsModule,
|
|
2867
|
+
MatStepperModule,
|
|
2868
|
+
MatDatepickerModule,
|
|
2869
|
+
MatDialogModule,
|
|
2870
|
+
MatDividerModule,
|
|
2871
|
+
MatExpansionModule,
|
|
2872
|
+
MatGridListModule,
|
|
2873
|
+
MatIconModule,
|
|
2874
|
+
MatInputModule,
|
|
2875
|
+
MatListModule,
|
|
2876
|
+
MatMenuModule,
|
|
2877
|
+
MatNativeDateModule,
|
|
2878
|
+
MatPaginatorModule,
|
|
2879
|
+
MatProgressBarModule,
|
|
2880
|
+
MatProgressSpinnerModule,
|
|
2881
|
+
MatRadioModule,
|
|
2882
|
+
MatRippleModule,
|
|
2883
|
+
MatSelectModule,
|
|
2884
|
+
MatSidenavModule,
|
|
2885
|
+
MatSliderModule,
|
|
2886
|
+
MatSlideToggleModule,
|
|
2887
|
+
MatSnackBarModule,
|
|
2888
|
+
MatSortModule,
|
|
2889
|
+
MatTabsModule,
|
|
2890
|
+
MatToolbarModule,
|
|
2891
|
+
MatTooltipModule,
|
|
2892
|
+
MatTreeModule,
|
|
2893
|
+
PortalModule,
|
|
2894
|
+
ScrollingModule,
|
|
2895
|
+
MatFormFieldModule,
|
|
2896
|
+
MatTableExtComponent,
|
|
2897
|
+
ResizeColumnDirective,
|
|
2898
|
+
ColumnPinningComponent,
|
|
2899
|
+
EditingComponent,
|
|
2900
|
+
FilterColumnsComponentComponent], exports: [MatTableExtComponent,
|
|
2901
|
+
ResizeColumnDirective,
|
|
2902
|
+
ColumnPinningComponent,
|
|
2903
|
+
EditingComponent,
|
|
2904
|
+
FilterColumnsComponentComponent] }); }
|
|
2905
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.5", ngImport: i0, type: MatTableExtModule, imports: [CommonModule,
|
|
2906
|
+
TranslateModule.forChild(),
|
|
2907
|
+
MatTableModule,
|
|
2908
|
+
FormsModule,
|
|
2909
|
+
ReactiveFormsModule,
|
|
2910
|
+
MatNativeDateModule,
|
|
2911
|
+
A11yModule,
|
|
2912
|
+
CdkAccordionModule,
|
|
2913
|
+
ClipboardModule,
|
|
2914
|
+
CdkStepperModule,
|
|
2915
|
+
CdkTableModule,
|
|
2916
|
+
CdkTreeModule,
|
|
2917
|
+
DragDropModule,
|
|
2918
|
+
MatAutocompleteModule,
|
|
2919
|
+
MatBadgeModule,
|
|
2920
|
+
MatBottomSheetModule,
|
|
2921
|
+
MatButtonModule,
|
|
2922
|
+
MatButtonToggleModule,
|
|
2923
|
+
MatCardModule,
|
|
2924
|
+
MatCheckboxModule,
|
|
2925
|
+
MatChipsModule,
|
|
2926
|
+
MatStepperModule,
|
|
2927
|
+
MatDatepickerModule,
|
|
2928
|
+
MatDialogModule,
|
|
2929
|
+
MatDividerModule,
|
|
2930
|
+
MatExpansionModule,
|
|
2931
|
+
MatGridListModule,
|
|
2932
|
+
MatIconModule,
|
|
2933
|
+
MatInputModule,
|
|
2934
|
+
MatListModule,
|
|
2935
|
+
MatMenuModule,
|
|
2936
|
+
MatNativeDateModule,
|
|
2937
|
+
MatPaginatorModule,
|
|
2938
|
+
MatProgressBarModule,
|
|
2939
|
+
MatProgressSpinnerModule,
|
|
2940
|
+
MatRadioModule,
|
|
2941
|
+
MatRippleModule,
|
|
2942
|
+
MatSelectModule,
|
|
2943
|
+
MatSidenavModule,
|
|
2944
|
+
MatSliderModule,
|
|
2945
|
+
MatSlideToggleModule,
|
|
2946
|
+
MatSnackBarModule,
|
|
2947
|
+
MatSortModule,
|
|
2948
|
+
MatTabsModule,
|
|
2949
|
+
MatToolbarModule,
|
|
2950
|
+
MatTooltipModule,
|
|
2951
|
+
MatTreeModule,
|
|
2952
|
+
PortalModule,
|
|
2953
|
+
ScrollingModule,
|
|
2954
|
+
MatFormFieldModule,
|
|
2955
|
+
MatTableExtComponent,
|
|
2956
|
+
ColumnPinningComponent,
|
|
2957
|
+
EditingComponent,
|
|
2958
|
+
FilterColumnsComponentComponent] }); }
|
|
2959
|
+
}
|
|
2960
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.5", ngImport: i0, type: MatTableExtModule, decorators: [{
|
|
2961
|
+
type: NgModule,
|
|
2962
|
+
args: [{
|
|
2963
|
+
declarations: [],
|
|
2964
|
+
imports: [
|
|
2965
|
+
CommonModule,
|
|
2966
|
+
TranslateModule.forChild(),
|
|
2967
|
+
MatTableModule,
|
|
2968
|
+
FormsModule,
|
|
2969
|
+
ReactiveFormsModule,
|
|
2970
|
+
MatNativeDateModule,
|
|
2971
|
+
A11yModule,
|
|
2972
|
+
CdkAccordionModule,
|
|
2973
|
+
ClipboardModule,
|
|
2974
|
+
CdkStepperModule,
|
|
2975
|
+
CdkTableModule,
|
|
2976
|
+
CdkTreeModule,
|
|
2977
|
+
DragDropModule,
|
|
2978
|
+
MatAutocompleteModule,
|
|
2979
|
+
MatBadgeModule,
|
|
2980
|
+
MatBottomSheetModule,
|
|
2981
|
+
MatButtonModule,
|
|
2982
|
+
MatButtonToggleModule,
|
|
2983
|
+
MatCardModule,
|
|
2984
|
+
MatCheckboxModule,
|
|
2985
|
+
MatChipsModule,
|
|
2986
|
+
MatStepperModule,
|
|
2987
|
+
MatDatepickerModule,
|
|
2988
|
+
MatDialogModule,
|
|
2989
|
+
MatDividerModule,
|
|
2990
|
+
MatExpansionModule,
|
|
2991
|
+
MatGridListModule,
|
|
2992
|
+
MatIconModule,
|
|
2993
|
+
MatInputModule,
|
|
2994
|
+
MatListModule,
|
|
2995
|
+
MatMenuModule,
|
|
2996
|
+
MatNativeDateModule,
|
|
2997
|
+
MatPaginatorModule,
|
|
2998
|
+
MatProgressBarModule,
|
|
2999
|
+
MatProgressSpinnerModule,
|
|
3000
|
+
MatRadioModule,
|
|
3001
|
+
MatRippleModule,
|
|
3002
|
+
MatSelectModule,
|
|
3003
|
+
MatSidenavModule,
|
|
3004
|
+
MatSliderModule,
|
|
3005
|
+
MatSlideToggleModule,
|
|
3006
|
+
MatSnackBarModule,
|
|
3007
|
+
MatSortModule,
|
|
3008
|
+
MatTabsModule,
|
|
3009
|
+
MatToolbarModule,
|
|
3010
|
+
MatTooltipModule,
|
|
3011
|
+
MatTreeModule,
|
|
3012
|
+
PortalModule,
|
|
3013
|
+
ScrollingModule,
|
|
3014
|
+
MatFormFieldModule,
|
|
3015
|
+
MatTableExtComponent,
|
|
3016
|
+
ResizeColumnDirective,
|
|
3017
|
+
ColumnPinningComponent,
|
|
3018
|
+
EditingComponent,
|
|
3019
|
+
FilterColumnsComponentComponent,
|
|
3020
|
+
],
|
|
3021
|
+
exports: [
|
|
3022
|
+
MatTableExtComponent,
|
|
3023
|
+
ResizeColumnDirective,
|
|
3024
|
+
ColumnPinningComponent,
|
|
3025
|
+
EditingComponent,
|
|
3026
|
+
FilterColumnsComponentComponent,
|
|
3027
|
+
],
|
|
3028
|
+
}]
|
|
3029
|
+
}] });
|
|
3030
|
+
|
|
3031
|
+
/*
|
|
3032
|
+
* Public API Surface of mat-table-ext
|
|
3033
|
+
*/
|
|
3034
|
+
|
|
3035
|
+
/**
|
|
3036
|
+
* Generated bundle index. Do not edit.
|
|
3037
|
+
*/
|
|
3038
|
+
|
|
3039
|
+
export { ColumnPinningComponent, EditingComponent, FilterColumnsComponentComponent, MatTableExtComponent, MatTableExtModule, MatTableExtService, ResizeColumnDirective };
|
|
3040
|
+
//# sourceMappingURL=mat-table-ext.mjs.map
|