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.
Files changed (33) hide show
  1. package/README.md +63 -57
  2. package/assets/_theming.scss +7 -7
  3. package/assets/pinLeft.svg +11 -11
  4. package/assets/pinNone.svg +5 -5
  5. package/assets/pinRight.svg +11 -11
  6. package/assets/pinned.svg +6 -2
  7. package/fesm2022/mat-table-ext.mjs +3040 -0
  8. package/fesm2022/mat-table-ext.mjs.map +1 -0
  9. package/index.d.ts +858 -5
  10. package/package.json +16 -22
  11. package/esm2020/lib/components/column-pinning/column-pinning.component.mjs +0 -58
  12. package/esm2020/lib/components/editing/editing.component.mjs +0 -122
  13. package/esm2020/lib/components/filter-columns-component/filter-columns-component.component.mjs +0 -68
  14. package/esm2020/lib/directives/resize-column.directive.mjs +0 -99
  15. package/esm2020/lib/mat-table-ext.component.mjs +0 -1020
  16. package/esm2020/lib/mat-table-ext.module.mjs +0 -237
  17. package/esm2020/lib/mat-table-ext.service.mjs +0 -20
  18. package/esm2020/lib/models/tableExtModels.mjs +0 -2
  19. package/esm2020/mat-table-ext.mjs +0 -5
  20. package/esm2020/public-api.mjs +0 -11
  21. package/fesm2015/mat-table-ext.mjs +0 -1584
  22. package/fesm2015/mat-table-ext.mjs.map +0 -1
  23. package/fesm2020/mat-table-ext.mjs +0 -1581
  24. package/fesm2020/mat-table-ext.mjs.map +0 -1
  25. package/lib/components/column-pinning/column-pinning.component.d.ts +0 -27
  26. package/lib/components/editing/editing.component.d.ts +0 -42
  27. package/lib/components/filter-columns-component/filter-columns-component.component.d.ts +0 -26
  28. package/lib/directives/resize-column.directive.d.ts +0 -27
  29. package/lib/mat-table-ext.component.d.ts +0 -348
  30. package/lib/mat-table-ext.module.d.ts +0 -58
  31. package/lib/mat-table-ext.service.d.ts +0 -11
  32. package/lib/models/tableExtModels.d.ts +0 -76
  33. 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