mat-table-ext 0.0.10 → 1.0.0-beta.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 +57 -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-test1.mjs +3019 -0
  8. package/fesm2022/mat-table-ext-test1.mjs.map +1 -0
  9. package/index.d.ts +774 -5
  10. package/package.json +13 -21
  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,3019 @@
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 };
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
+ /**
676
+ * @description Check if row is pinned to top (for CSS class binding)
677
+ */
678
+ this.isRowPinnedTop = (row) => {
679
+ return this.pinnedTopRows.includes(row);
680
+ };
681
+ /**
682
+ * @description Check if row is pinned to bottom (for CSS class binding)
683
+ */
684
+ this.isRowPinnedBottom = (row) => {
685
+ return this.pinnedBottomRows.includes(row);
686
+ };
687
+ /**
688
+ * @description This method will take data from inline editing template and update in table data source.
689
+ * @param row updated row from inline editing template.
690
+ */
691
+ this.updateInlineTemplateData = (row) => {
692
+ this.service.selectedRow.next(row);
693
+ };
694
+ this.addIconsToRegistry();
695
+ if (this.dataSource) {
696
+ this.tableData = this.dataSource.data;
697
+ }
698
+ }
699
+ /**
700
+ *
701
+ * @param changes changes captured each time user changes property value.
702
+ */
703
+ /**
704
+ * Handle column pinning changes from ColumnPinningComponent
705
+ * @param updatedColumns Updated columns array with new pinning states
706
+ */
707
+ updateColumns(updatedColumns) {
708
+ // Create a completely new columnsArray to trigger change detection
709
+ this.columnsArray = updatedColumns.map(col => ({ ...col }));
710
+ // Update showHideColumnsArray to keep it in sync
711
+ this.showHideColumnsArray = [...this.columnsArray];
712
+ // Re-apply column configurations
713
+ this.setColumnsList(this.columnsArray);
714
+ // Force complete table re-render by recreating the data source
715
+ if (this.dataSource) {
716
+ const currentData = [...this.dataSource.data];
717
+ this.dataSource = new MatTableDataSource(currentData);
718
+ this.pinnedTopDataSource = new MatTableDataSource(this.pinnedTopRows);
719
+ this.pinnedBtmDataSource = new MatTableDataSource(this.pinnedBottomRows);
720
+ this.reCal(); // Re-apply paginator, sort, and filter
721
+ }
722
+ if (this.columnFilter) {
723
+ this.setColumnFilter(true);
724
+ }
725
+ // Force change detection
726
+ this.cdr.markForCheck();
727
+ this.cdr.detectChanges();
728
+ // Re-sync column sizes in case column ordering/visibility changed
729
+ if (this.enableRowPinning) {
730
+ setTimeout(() => this.syncColumnSizesFromTop(), 80);
731
+ }
732
+ }
733
+ ngOnChanges(changes) {
734
+ this.setPropertyValue(changes);
735
+ }
736
+ ngOnInit() {
737
+ if (this.dataSource) {
738
+ this.dataSource.filterPredicate = this.createFilter();
739
+ }
740
+ // Initialize FormGroup if not already initialized
741
+ if (!this.hideShowMenuGroup || Object.keys(this.hideShowMenuGroup.controls).length === 0) {
742
+ this.hideShowMenuGroup = this.formBuilder.group({});
743
+ }
744
+ // Initialize pinned rows if function provided
745
+ if (this.enableRowPinning) {
746
+ this.initializePinnedRows();
747
+ }
748
+ }
749
+ ngAfterViewInit() {
750
+ if (this.dataSource) {
751
+ this.dataSource.paginator = this.paginator;
752
+ this.dataSource.sort = this.sort;
753
+ if (this.enableRowPinning) {
754
+ this.pinnedTopDataSource.sort = this.sort;
755
+ this.pinnedBtmDataSource.sort = this.sort;
756
+ }
757
+ }
758
+ // Calculate and set pinned row offsets
759
+ this.updatePinnedRowOffsets();
760
+ // Sync column sizes from top table to middle/bottom when pinning enabled
761
+ if (this.enableRowPinning) {
762
+ setTimeout(() => this.syncColumnSizesFromTop(), 150);
763
+ window.addEventListener('resize', this.onWindowResizeBound);
764
+ }
765
+ }
766
+ /**
767
+ * @description Calculate offsets for pinned rows based on sticky headers/footers
768
+ */
769
+ updatePinnedRowOffsets() {
770
+ if (!this.tableElement?.nativeElement || !this.enableRowPinning)
771
+ return;
772
+ setTimeout(() => {
773
+ const table = this.tableElement.nativeElement;
774
+ // Calculate top offset (sticky header + group header + filter row)
775
+ let topOffset = 0;
776
+ if (this.stickyHeader) {
777
+ // Get all header rows that are sticky
778
+ const headerRows = table.querySelectorAll('.mat-mdc-header-row');
779
+ headerRows.forEach((header) => {
780
+ topOffset += header.offsetHeight;
781
+ });
782
+ }
783
+ // Calculate bottom offset (sticky footer + paginator)
784
+ let bottomOffset = 0;
785
+ if (this.stickyFooter) {
786
+ const footerRow = table.querySelector('.mat-mdc-footer-row');
787
+ if (footerRow) {
788
+ bottomOffset += footerRow.offsetHeight;
789
+ }
790
+ }
791
+ // Set base offsets
792
+ table.style.setProperty('--pinned-top-base-offset', `${topOffset}px`);
793
+ table.style.setProperty('--pinned-bottom-base-offset', `${bottomOffset}px`);
794
+ // Calculate and set individual row offsets for stacked pinned rows
795
+ this.updateStackedPinnedRowOffsets(table, topOffset, bottomOffset);
796
+ // After offsets are updated, ensure column sizes are re-synced
797
+ if (this.enableRowPinning) {
798
+ setTimeout(() => this.syncColumnSizesFromTop(), 10);
799
+ }
800
+ console.log('Pinned row offsets:', { topOffset, bottomOffset });
801
+ }, 100);
802
+ }
803
+ /**
804
+ * @description Update offsets for each individual pinned row to stack them
805
+ */
806
+ updateStackedPinnedRowOffsets(table, baseTopOffset, baseBottomOffset) {
807
+ // Use setTimeout to ensure DOM is fully rendered with pinned classes
808
+ setTimeout(() => {
809
+ // Handle top pinned rows - stack them from top to bottom
810
+ const topPinnedRows = table.querySelectorAll('.pinned-top-row');
811
+ let currentTopOffset = baseTopOffset;
812
+ topPinnedRows.forEach((row, index) => {
813
+ const htmlRow = row;
814
+ htmlRow.style.setProperty('--pinned-row-top-offset', `${currentTopOffset}px`);
815
+ htmlRow.style.top = `${currentTopOffset}px`;
816
+ // Add current row height to offset for next row
817
+ if (index < topPinnedRows.length - 1) {
818
+ currentTopOffset += htmlRow.offsetHeight;
819
+ }
820
+ });
821
+ // Handle bottom pinned rows - stack them from bottom to top
822
+ const bottomPinnedRows = table.querySelectorAll('.pinned-bottom-row');
823
+ let currentBottomOffset = baseBottomOffset;
824
+ // Process bottom rows in reverse order (from bottom to top)
825
+ for (let i = bottomPinnedRows.length - 1; i >= 0; i--) {
826
+ const htmlRow = bottomPinnedRows[i];
827
+ htmlRow.style.setProperty('--pinned-row-bottom-offset', `${currentBottomOffset}px`);
828
+ htmlRow.style.bottom = `${currentBottomOffset}px`;
829
+ // Add current row height to offset for next row (going upward)
830
+ if (i > 0) {
831
+ currentBottomOffset += htmlRow.offsetHeight;
832
+ }
833
+ }
834
+ // After stacking offsets are applied, re-sync column sizes to handle any layout changes
835
+ if (this.enableRowPinning) {
836
+ setTimeout(() => this.syncColumnSizesFromTop(), 60);
837
+ }
838
+ }, 50);
839
+ }
840
+ /**
841
+ * Copy header cell widths/heights from the top table and apply them to middle and bottom tables.
842
+ * This ensures columns line up when the middle/bottom tables don't render headers.
843
+ */
844
+ syncColumnSizesFromTop() {
845
+ if (!this.enableRowPinning)
846
+ return;
847
+ try {
848
+ const topId = `matTableExtTop${this.tableID}`;
849
+ const bottomId = `matTableExtBtm${this.tableID}`;
850
+ const topTable = document.getElementById(topId);
851
+ const middleTable = document.getElementById(`matTableExt${this.tableID}`);
852
+ const bottomTable = document.getElementById(bottomId);
853
+ if (!topTable)
854
+ return;
855
+ 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)');
856
+ if (!headerRow)
857
+ return;
858
+ const headerCells = Array.from(headerRow.querySelectorAll('th, .mat-header-cell'));
859
+ if (!headerCells.length)
860
+ return;
861
+ const topTableWidth = topTable.getBoundingClientRect().width;
862
+ [middleTable, bottomTable].forEach(tbl => {
863
+ if (!tbl)
864
+ return;
865
+ tbl.style.width = topTable.style.width && topTable.style.width !== '' ? topTable.style.width : `${topTableWidth}px`;
866
+ });
867
+ // Use the header row height as the canonical row height to apply
868
+ const headerRowHeight = Math.round(headerRow.getBoundingClientRect().height);
869
+ headerCells.forEach((hc, index) => {
870
+ const rect = hc.getBoundingClientRect();
871
+ const w = Math.round(rect.width);
872
+ [middleTable, bottomTable].forEach(tbl => {
873
+ if (!tbl)
874
+ return;
875
+ // If a placeholder header exists in the target table, set its cell sizes
876
+ const placeholderHeader = tbl.querySelector('tr.mat-mdc-header-row, tr.mat-header-row');
877
+ if (placeholderHeader) {
878
+ const phCells = placeholderHeader.querySelectorAll('th, .mat-header-cell');
879
+ if (phCells && phCells[index]) {
880
+ const el = phCells[index];
881
+ el.style.minWidth = `${w}px`;
882
+ el.style.maxWidth = `${w}px`;
883
+ el.style.boxSizing = 'border-box';
884
+ el.style.height = `${headerRowHeight}px`;
885
+ el.style.minHeight = `${headerRowHeight}px`;
886
+ el.style.maxHeight = `${headerRowHeight}px`;
887
+ }
888
+ }
889
+ // Apply widths/heights directly to data cells (in case header placeholder is not present)
890
+ const dataRow = tbl.querySelector('tr.mat-mdc-row, tr.mat-row');
891
+ if (dataRow) {
892
+ const dataCells = dataRow.querySelectorAll('td, .mat-cell');
893
+ if (dataCells && dataCells[index]) {
894
+ const cel = dataCells[index];
895
+ cel.style.minWidth = `${w}px`;
896
+ cel.style.maxWidth = `${w}px`;
897
+ cel.style.boxSizing = 'border-box';
898
+ cel.style.height = `${headerRowHeight}px`;
899
+ cel.style.minHeight = `${headerRowHeight}px`;
900
+ cel.style.maxHeight = `${headerRowHeight}px`;
901
+ }
902
+ // Set every data row's height to match the header row height for visual alignment
903
+ const rows = tbl.querySelectorAll('tr.mat-mdc-row, tr.mat-row');
904
+ rows.forEach((r) => {
905
+ const reh = r;
906
+ reh.style.height = `${headerRowHeight}px`;
907
+ reh.style.minHeight = `${headerRowHeight}px`;
908
+ reh.style.maxHeight = `${headerRowHeight}px`;
909
+ });
910
+ }
911
+ });
912
+ });
913
+ }
914
+ catch (err) {
915
+ console.warn('syncColumnSizesFromTop failed', err);
916
+ }
917
+ }
918
+ /**
919
+ * Sync column sizes from the currently edited row in the middle table to top/bottom tables.
920
+ * This ensures proper alignment when a row is in edit mode with different height.
921
+ */
922
+ syncColumnSizesFromEditedRow(editedRowIndex) {
923
+ if (!this.enableRowPinning)
924
+ return;
925
+ try {
926
+ const topTable = document.getElementById(`matTableExtTop${this.tableID}`);
927
+ if (!topTable)
928
+ return;
929
+ // Capture original sizes from the top table header before modifying
930
+ if (!this.originalSizesBeforeEdit) {
931
+ const headerRow = topTable.querySelector('tr.mat-mdc-header-row:not(.group-header-row), tr.mat-header-row:not(.group-header-row)');
932
+ if (headerRow) {
933
+ const headerCells = Array.from(headerRow.querySelectorAll('th, .mat-header-cell'));
934
+ const headerRowHeight = Math.round(headerRow.getBoundingClientRect().height);
935
+ const columnWidths = headerCells.map(cell => Math.round(cell.getBoundingClientRect().width));
936
+ this.originalSizesBeforeEdit = {
937
+ columnWidths,
938
+ rowHeight: headerRowHeight
939
+ };
940
+ }
941
+ }
942
+ const middleTable = document.getElementById(`matTableExt${this.tableID}`);
943
+ const bottomTable = document.getElementById(`matTableExtBtm${this.tableID}`);
944
+ if (!middleTable || !topTable)
945
+ return;
946
+ // Find the edited row in the middle table
947
+ const editedRow = middleTable.querySelector(`tr.mat-mdc-row:nth-child(${editedRowIndex + 1})`);
948
+ if (!editedRow) {
949
+ // Fallback to normal sync if edited row not found
950
+ this.syncColumnSizesFromTop();
951
+ return;
952
+ }
953
+ const editedCells = Array.from(editedRow.querySelectorAll('td, .mat-cell'));
954
+ if (!editedCells.length)
955
+ return;
956
+ // Get the height of the edited row
957
+ const editedRowHeight = Math.round(editedRow.getBoundingClientRect().height);
958
+ // Sync widths and heights from edited row to top and bottom tables
959
+ // First, collect all widths in a single pass (layout read)
960
+ const cellWidths = editedCells.map(cell => Math.round(cell.getBoundingClientRect().width));
961
+ // Then, apply style changes in a separate pass (layout write)
962
+ cellWidths.forEach((w, index) => {
963
+ [topTable, bottomTable].forEach(tbl => {
964
+ if (!tbl)
965
+ return;
966
+ // Update header cells in top table
967
+ if (tbl === topTable) {
968
+ const headerRow = tbl.querySelector('tr.mat-mdc-header-row:not(.group-header-row), tr.mat-header-row:not(.group-header-row)');
969
+ if (headerRow) {
970
+ const headerCells = headerRow.querySelectorAll('th, .mat-header-cell');
971
+ if (headerCells && headerCells[index]) {
972
+ const hc = headerCells[index];
973
+ hc.style.minWidth = `${w}px`;
974
+ hc.style.maxWidth = `${w}px`;
975
+ hc.style.boxSizing = 'border-box';
976
+ }
977
+ }
978
+ }
979
+ // Update data cells in both tables
980
+ const dataRow = tbl.querySelector('tr.mat-mdc-row, tr.mat-row');
981
+ if (dataRow) {
982
+ const dataCells = dataRow.querySelectorAll('td, .mat-cell');
983
+ if (dataCells && dataCells[index]) {
984
+ const dc = dataCells[index];
985
+ dc.style.minWidth = `${w}px`;
986
+ dc.style.maxWidth = `${w}px`;
987
+ dc.style.boxSizing = 'border-box';
988
+ }
989
+ // Set all data rows' height to match the edited row height
990
+ // const rows = tbl.querySelectorAll('tr.mat-mdc-row, tr.mat-row');
991
+ // rows.forEach((r: Element) => {
992
+ // const reh = r as HTMLElement;
993
+ // reh.style.height = `${editedRowHeight}px`;
994
+ // reh.style.minHeight = `${editedRowHeight}px`;
995
+ // reh.style.maxHeight = `${editedRowHeight}px`;
996
+ // });
997
+ }
998
+ });
999
+ });
1000
+ }
1001
+ catch (err) {
1002
+ console.warn('syncColumnSizesFromEditedRow failed', err);
1003
+ }
1004
+ }
1005
+ /**
1006
+ * Restore original column widths and row heights from before edit mode.
1007
+ */
1008
+ restoreOriginalSizes() {
1009
+ if (!this.enableRowPinning || !this.originalSizesBeforeEdit)
1010
+ return;
1011
+ try {
1012
+ const topTable = document.getElementById(`matTableExtTop${this.tableID}`);
1013
+ const middleTable = document.getElementById(`matTableExt${this.tableID}`);
1014
+ const bottomTable = document.getElementById(`matTableExtBtm${this.tableID}`);
1015
+ if (!topTable)
1016
+ return;
1017
+ const { columnWidths, rowHeight } = this.originalSizesBeforeEdit;
1018
+ [topTable, middleTable, bottomTable].forEach(tbl => {
1019
+ if (!tbl)
1020
+ return;
1021
+ // Restore header cells in top table
1022
+ if (tbl === topTable) {
1023
+ const headerRow = tbl.querySelector('tr.mat-mdc-header-row:not(.group-header-row), tr.mat-header-row:not(.group-header-row)');
1024
+ if (headerRow) {
1025
+ const headerCells = Array.from(headerRow.querySelectorAll('th, .mat-header-cell'));
1026
+ headerCells.forEach((cell, index) => {
1027
+ if (columnWidths[index] !== undefined) {
1028
+ const w = columnWidths[index];
1029
+ cell.style.minWidth = `${w}px`;
1030
+ cell.style.maxWidth = `${w}px`;
1031
+ cell.style.boxSizing = 'border-box';
1032
+ cell.style.height = `${rowHeight}px`;
1033
+ cell.style.minHeight = `${rowHeight}px`;
1034
+ cell.style.maxHeight = `${rowHeight}px`;
1035
+ }
1036
+ });
1037
+ }
1038
+ }
1039
+ // Restore data cells
1040
+ const dataRow = tbl.querySelector('tr.mat-mdc-row, tr.mat-row');
1041
+ if (dataRow) {
1042
+ const dataCells = Array.from(dataRow.querySelectorAll('td, .mat-cell'));
1043
+ dataCells.forEach((cell, index) => {
1044
+ if (columnWidths[index] !== undefined) {
1045
+ const w = columnWidths[index];
1046
+ cell.style.minWidth = `${w}px`;
1047
+ cell.style.maxWidth = `${w}px`;
1048
+ cell.style.boxSizing = 'border-box';
1049
+ cell.style.height = `${rowHeight}px`;
1050
+ cell.style.minHeight = `${rowHeight}px`;
1051
+ cell.style.maxHeight = `${rowHeight}px`;
1052
+ }
1053
+ });
1054
+ // Restore all data rows' height
1055
+ const rows = tbl.querySelectorAll('tr.mat-mdc-row, tr.mat-row');
1056
+ rows.forEach((r) => {
1057
+ const reh = r;
1058
+ reh.style.height = `${rowHeight}px`;
1059
+ reh.style.minHeight = `${rowHeight}px`;
1060
+ reh.style.maxHeight = `${rowHeight}px`;
1061
+ });
1062
+ }
1063
+ });
1064
+ // Clear the stored sizes
1065
+ this.originalSizesBeforeEdit = null;
1066
+ }
1067
+ catch (err) {
1068
+ console.warn('restoreOriginalSizes failed', err);
1069
+ }
1070
+ }
1071
+ ngOnDestroy() {
1072
+ window.removeEventListener('resize', this.onWindowResizeBound);
1073
+ }
1074
+ /**
1075
+ * @description checks and updates the the column's hide and show properties.
1076
+ */
1077
+ setColumnHideShow() {
1078
+ if (this.hideShowMenuGroup !== undefined &&
1079
+ this.hideShowMenuGroup !== null) {
1080
+ this.updateColumnsHideShow(this.hideShowMenuGroup.value);
1081
+ }
1082
+ }
1083
+ /**
1084
+ * @description set the properties of the table.
1085
+ * @param changes changes captured each time user changes property value.
1086
+ */
1087
+ setPropertyValue(changes) {
1088
+ let keys = Object.keys(changes);
1089
+ keys.forEach((property) => {
1090
+ if (this.inputPropertyKeys.includes(property)) {
1091
+ this.setPropertiesMap[property](changes[property]);
1092
+ setTimeout(() => this.syncColumnSizesFromTop(), 80);
1093
+ }
1094
+ else if (property == 'showToolbar') {
1095
+ if (changes['columns']) {
1096
+ this.setToolbarMenuControls(changes['columns'].currentValue);
1097
+ }
1098
+ else {
1099
+ this.setToolbarMenuControls(this.columnsArray);
1100
+ }
1101
+ }
1102
+ });
1103
+ }
1104
+ /**
1105
+ * @description used set data source for table.
1106
+ * @param value data source value from user.
1107
+ */
1108
+ setTableDataSource(value) {
1109
+ if (value.currentValue) {
1110
+ this.tableData = value.currentValue.data;
1111
+ this.dataSource = value.currentValue;
1112
+ this.reCal();
1113
+ }
1114
+ else {
1115
+ this.dataSource = new MatTableDataSource([{}]);
1116
+ }
1117
+ }
1118
+ /**
1119
+ * @description used create seletion model and set selection column visibility.
1120
+ * @param value boolean value to show or hide selection Column from table.
1121
+ */
1122
+ setRowSelection(value) {
1123
+ this.selection = new SelectionModel(true, []);
1124
+ this.updateSelectionColumnVisibility(value);
1125
+ }
1126
+ /**
1127
+ * @description create filter header row and assigns filter predicate to table data source.
1128
+ * @param value boolean value to change visibility of column filter row.
1129
+ */
1130
+ setColumnFilter(value) {
1131
+ if (value) {
1132
+ let array = [];
1133
+ this.columnsArray.forEach((column, i) => {
1134
+ if (this.dynamicDisplayedColumns.filter((a) => a.name == column?.field)[0]
1135
+ .show) {
1136
+ array.push(column?.field + '_' + i);
1137
+ }
1138
+ });
1139
+ this.headersFiltersIds = array;
1140
+ this.dataSource.filterPredicate = this.createFilter();
1141
+ }
1142
+ else {
1143
+ this.headersFiltersIds = [];
1144
+ this.dataSource.filter = '';
1145
+ }
1146
+ this.toggleFilters = value;
1147
+ setTimeout(() => this.syncColumnSizesFromTop(), 150);
1148
+ }
1149
+ /**
1150
+ * @description This method returns the list of visible column names.
1151
+ * @returns list of visible column names.
1152
+ */
1153
+ getDisplayedColumns() {
1154
+ if (this.columnGroups.length === 0) {
1155
+ // No groups, place select at start and other action columns at the end
1156
+ const actionColumns = ['select', 'edit', 'popup', 'delete', 'freeze', 'hide', 'pin'];
1157
+ const visibleColumns = this.dynamicDisplayedColumns.filter((cd) => cd.show);
1158
+ const dataColumns = visibleColumns.filter((cd) => !actionColumns.includes(cd.name)).map((cd) => cd.name);
1159
+ const selectCol = visibleColumns.find((cd) => cd.name === 'select');
1160
+ const otherActionCols = visibleColumns.filter((cd) => actionColumns.includes(cd.name) && cd.name !== 'select').map((cd) => cd.name);
1161
+ const result = [];
1162
+ if (selectCol)
1163
+ result.push('select');
1164
+ result.push(...dataColumns);
1165
+ result.push(...otherActionCols);
1166
+ return result;
1167
+ }
1168
+ // When groups exist, reorder: select first, grouped columns, ungrouped columns, then other action columns
1169
+ const actionColumns = ['select', 'edit', 'popup', 'delete', 'freeze', 'hide', 'pin'];
1170
+ const groupedFields = new Set();
1171
+ // Collect all fields that belong to groups
1172
+ this.columnGroups.forEach(group => {
1173
+ group.columns.forEach(colField => groupedFields.add(colField));
1174
+ });
1175
+ const result = [];
1176
+ const visibleColumns = this.dynamicDisplayedColumns.filter((cd) => cd.show);
1177
+ // Add select column first if visible
1178
+ const selectCol = visibleColumns.find(c => c.name === 'select');
1179
+ if (selectCol) {
1180
+ result.push('select');
1181
+ }
1182
+ // Add grouped columns in the order they appear in groups
1183
+ this.columnGroups.forEach(group => {
1184
+ group.columns.forEach(colField => {
1185
+ const col = visibleColumns.find(c => c.name === colField);
1186
+ if (col && !result.includes(col.name)) {
1187
+ result.push(col.name);
1188
+ }
1189
+ });
1190
+ });
1191
+ // Add ungrouped data columns
1192
+ visibleColumns.forEach(col => {
1193
+ if (!actionColumns.includes(col.name) && !groupedFields.has(col.name) && !result.includes(col.name)) {
1194
+ result.push(col.name);
1195
+ }
1196
+ });
1197
+ // Add other action columns at the end (excluding select which is already at start)
1198
+ visibleColumns.forEach(col => {
1199
+ if (actionColumns.includes(col.name) && col.name !== 'select' && !result.includes(col.name)) {
1200
+ result.push(col.name);
1201
+ }
1202
+ });
1203
+ return result;
1204
+ }
1205
+ /**
1206
+ * @description This method returns the grouped column header definitions.
1207
+ * @returns list of grouped column definitions for header row.
1208
+ */
1209
+ getGroupedColumns() {
1210
+ if (this.columnGroups.length === 0)
1211
+ return [];
1212
+ const grouped = [];
1213
+ const groupedFields = new Set();
1214
+ const actionColumns = ['select', 'edit', 'popup', 'delete', 'freeze', 'hide', 'pin'];
1215
+ // Collect all fields that belong to groups
1216
+ this.columnGroups.forEach(group => {
1217
+ group.columns.forEach(colField => groupedFields.add(colField));
1218
+ });
1219
+ // Add group headers for groups with visible columns
1220
+ this.columnGroups.forEach(group => {
1221
+ const visibleColumnsInGroup = group.columns.filter(colField => {
1222
+ const displayCol = this.dynamicDisplayedColumns.find(dc => dc.name === colField);
1223
+ return displayCol && displayCol.show;
1224
+ });
1225
+ if (visibleColumnsInGroup.length > 0) {
1226
+ grouped.push('group-' + group.name);
1227
+ }
1228
+ });
1229
+ // Add empty header placeholders for ungrouped columns at the end
1230
+ this.columnsArray.forEach(col => {
1231
+ if (!groupedFields.has(col.field) && !actionColumns.includes(col.field)) {
1232
+ const displayCol = this.dynamicDisplayedColumns.find(dc => dc.name === col.field);
1233
+ if (displayCol && displayCol.show) {
1234
+ grouped.push('ungrouped-' + col.field);
1235
+ }
1236
+ }
1237
+ });
1238
+ // Add placeholders for visible action columns so group header row has cells to align with action columns
1239
+ const actionPlaceholders = ['select', 'edit', 'popup', 'delete', 'freeze', 'hide', 'pin'];
1240
+ actionPlaceholders.forEach(act => {
1241
+ const display = this.dynamicDisplayedColumns.find(dc => dc.name === act);
1242
+ if (display && display.show) {
1243
+ grouped.push('ungrouped-' + act);
1244
+ }
1245
+ });
1246
+ return grouped;
1247
+ }
1248
+ /**
1249
+ * @description Returns filter column IDs including placeholders for action columns
1250
+ * @returns Array of filter column IDs with action column placeholders
1251
+ */
1252
+ getFilterColumns() {
1253
+ const filters = [];
1254
+ const actionColumns = ['select', 'edit', 'popup', 'delete', 'freeze', 'hide', 'pin'];
1255
+ // Get visible columns in display order
1256
+ const displayedCols = this.getDisplayedColumns();
1257
+ displayedCols.forEach(colName => {
1258
+ if (actionColumns.includes(colName)) {
1259
+ // Add filter placeholder for action column
1260
+ filters.push('filter-' + colName);
1261
+ }
1262
+ else {
1263
+ // Find the actual filter ID from headersFiltersIds
1264
+ const filterCol = this.headersFiltersIds.find(id => id.startsWith(colName + '_'));
1265
+ if (filterCol) {
1266
+ filters.push(filterCol);
1267
+ }
1268
+ }
1269
+ });
1270
+ return this.columnFilter ? filters : [];
1271
+ }
1272
+ /**
1273
+ * @param menuType type of menu to open from toolbar.
1274
+ * @param event mouse event to open menu on that location.
1275
+ */
1276
+ openMenu(menuType, event) {
1277
+ this.menuX = event.clientX;
1278
+ this.menuY = event.clientY;
1279
+ switch (menuType) {
1280
+ case 'export': {
1281
+ this.exportMenuCtrl = true;
1282
+ this.menuTrigger.openMenu();
1283
+ break;
1284
+ }
1285
+ case 'hideShow': {
1286
+ this.hideShowMenuCtrl = true;
1287
+ this.openHideShowMenu(this.columnsArray);
1288
+ break;
1289
+ }
1290
+ case 'columnPin': {
1291
+ this.columnPinMenuCtrl = true;
1292
+ this.openHideShowMenu(this.columnsArray);
1293
+ break;
1294
+ }
1295
+ }
1296
+ }
1297
+ /**
1298
+ * @description triggers when menu is closed and reset the required controls.
1299
+ */
1300
+ menuClosed() {
1301
+ this.exportMenuCtrl = false;
1302
+ }
1303
+ /**
1304
+ * @description set list of columns to display in table.
1305
+ * @param columns columns array from user input.
1306
+ */
1307
+ setColumnsData(columns) {
1308
+ if (columns.length) {
1309
+ this.columnsArray = [...columns];
1310
+ this.setColumnsList(columns);
1311
+ this.setToolbarMenuControls(columns);
1312
+ }
1313
+ }
1314
+ /**
1315
+ * @description set list of columns to display in table.
1316
+ * @param columns columns array from user input with configurations.
1317
+ */
1318
+ setColumnsList(columns) {
1319
+ this.columnsList = [];
1320
+ this.displayedColumns = ['select', 'edit', 'popup', 'delete', 'freeze', 'hide', 'pin'];
1321
+ let columnsArray = [];
1322
+ columns.forEach((col) => {
1323
+ if (typeof col?.header == 'string') {
1324
+ this.columnsList.push(col?.header);
1325
+ this.displayedColumns.push(col?.field);
1326
+ columnsArray.push({ filter: true, name: col?.field, show: !col.hide });
1327
+ }
1328
+ });
1329
+ // Preserve the current state of action columns before resetting
1330
+ const currentActionColumns = this.dynamicDisplayedColumns.filter(dc => ['select', 'edit', 'popup', 'delete', 'freeze', 'hide', 'pin'].includes(dc.name));
1331
+ // Create new action columns array, preserving existing states
1332
+ const newActionColumns = [
1333
+ { filter: false, name: 'select', show: false },
1334
+ { filter: false, name: 'edit', show: false },
1335
+ { filter: false, name: 'popup', show: false },
1336
+ { filter: false, name: 'delete', show: false },
1337
+ { filter: false, name: 'freeze', show: false },
1338
+ { filter: false, name: 'hide', show: false },
1339
+ { filter: false, name: 'pin', show: false },
1340
+ ].map(actionCol => {
1341
+ const existing = currentActionColumns.find(c => c.name === actionCol.name);
1342
+ return existing ? { ...existing } : actionCol;
1343
+ });
1344
+ this.dynamicDisplayedColumns = columnsArray.concat(newActionColumns);
1345
+ // After updating columns, ensure sizes match the top header (if pinning enabled)
1346
+ if (this.enableRowPinning) {
1347
+ setTimeout(() => this.syncColumnSizesFromTop(), 80);
1348
+ }
1349
+ }
1350
+ /**
1351
+ * @description Take boolean value and name column and update its visibility status in table.
1352
+ * @param name name of the column to set visibility.
1353
+ * @param value boolean value to set visibility of the column.
1354
+ */
1355
+ showHideColumn(name, value) {
1356
+ const column = this.dynamicDisplayedColumns.filter((a) => a.name == name)[0];
1357
+ if (column) {
1358
+ column.show = value;
1359
+ if (this.enableRowPinning) {
1360
+ this.syncColumnSizesFromTop();
1361
+ }
1362
+ }
1363
+ if (this.columnFilter) {
1364
+ this.setColumnFilter(true);
1365
+ }
1366
+ }
1367
+ /**
1368
+ * @description Toggle hide state for a specific row
1369
+ * @param index The row index to hide/unhide
1370
+ */
1371
+ toggleRowHide(index) {
1372
+ const hiddenIndex = this.hiddenRowIndices.indexOf(index);
1373
+ if (hiddenIndex > -1) {
1374
+ // Unhide the row
1375
+ this.hiddenRowIndices.splice(hiddenIndex, 1);
1376
+ }
1377
+ else {
1378
+ // Hide the row
1379
+ this.hiddenRowIndices.push(index);
1380
+ }
1381
+ // Trigger change detection
1382
+ this.hiddenRowIndices = [...this.hiddenRowIndices];
1383
+ }
1384
+ /**
1385
+ * @description Check if a row index is in the hidden rows list or matches the filter function.
1386
+ * @param index The row index to check
1387
+ * @returns True if the row is hidden
1388
+ */
1389
+ isRowHidden(index) {
1390
+ // Check explicit hidden indices
1391
+ if (this.hiddenRowIndices.includes(index)) {
1392
+ return true;
1393
+ }
1394
+ // Check filter function if provided
1395
+ if (this.rowHidingFilterFn && this.dataSource?.data?.[index]) {
1396
+ return this.rowHidingFilterFn(this.dataSource.data[index], index);
1397
+ }
1398
+ return false;
1399
+ }
1400
+ /**
1401
+ * @description Unhide all hidden rows
1402
+ */
1403
+ unhideAllRows() {
1404
+ this.hiddenRowIndices = [];
1405
+ }
1406
+ /**
1407
+ * @description Open row pin menu
1408
+ * @param event Mouse event
1409
+ * @param row The row to pin
1410
+ */
1411
+ openRowPinMenu(event, row) {
1412
+ event.stopPropagation();
1413
+ this.rowPinMenuPosition = {
1414
+ x: event.clientX + 'px',
1415
+ y: event.clientY + 'px'
1416
+ };
1417
+ this.rowPinMenuRow = row;
1418
+ }
1419
+ /**
1420
+ * @description Close row pin menu
1421
+ */
1422
+ closeRowPinMenu() {
1423
+ this.rowPinMenuRow = null;
1424
+ }
1425
+ /**
1426
+ * @description Pin row to top or bottom
1427
+ * @param row The row to pin
1428
+ * @param position 'top' or 'bottom'
1429
+ */
1430
+ pinRow(row, position) {
1431
+ console.log('pinRow called:', { row, position, enableRowPinning: this.enableRowPinning });
1432
+ // Remove from other position if exists
1433
+ this.unpinRow(row);
1434
+ // Mark the row with pinning metadata
1435
+ row._pinnedPosition = position;
1436
+ // Add to the selected position
1437
+ if (position === 'top') {
1438
+ if (!this.pinnedTopRows.includes(row)) {
1439
+ this.pinnedTopRows.push(row);
1440
+ }
1441
+ this.pinnedTopDataSource = new MatTableDataSource(this.pinnedTopRows);
1442
+ }
1443
+ else {
1444
+ if (!this.pinnedBottomRows.includes(row)) {
1445
+ this.pinnedBottomRows.push(row);
1446
+ }
1447
+ this.pinnedBtmDataSource = new MatTableDataSource(this.pinnedBottomRows);
1448
+ }
1449
+ console.log('After pinning:', {
1450
+ pinnedTopRows: this.pinnedTopRows,
1451
+ pinnedBottomRows: this.pinnedBottomRows,
1452
+ topLength: this.pinnedTopRows.length,
1453
+ bottomLength: this.pinnedBottomRows.length
1454
+ });
1455
+ this.rowPinningChange.emit({ row, position });
1456
+ this.closeRowPinMenu();
1457
+ this.updateDataSourceForPinning();
1458
+ }
1459
+ /**
1460
+ * @description Unpin row from any position
1461
+ * @param row The row to unpin
1462
+ */
1463
+ unpinRow(row) {
1464
+ const topIndex = this.pinnedTopRows.indexOf(row);
1465
+ if (topIndex > -1) {
1466
+ this.pinnedTopRows.splice(topIndex, 1);
1467
+ this.pinnedTopDataSource = new MatTableDataSource(this.pinnedTopRows);
1468
+ }
1469
+ const bottomIndex = this.pinnedBottomRows.indexOf(row);
1470
+ if (bottomIndex > -1) {
1471
+ this.pinnedBottomRows.splice(bottomIndex, 1);
1472
+ this.pinnedBtmDataSource = new MatTableDataSource(this.pinnedBottomRows);
1473
+ }
1474
+ // Clear pinning metadata
1475
+ delete row._pinnedPosition;
1476
+ // Update the data source to trigger re-render
1477
+ this.updateDataSourceForPinning();
1478
+ this.rowPinningChange.emit({ row, position: null });
1479
+ this.closeRowPinMenu();
1480
+ }
1481
+ /**
1482
+ * @description Check if a row is pinned
1483
+ * @param row The row to check
1484
+ * @returns true if pinned
1485
+ */
1486
+ isRowPinned(row) {
1487
+ return this.pinnedTopRows.includes(row) || this.pinnedBottomRows.includes(row);
1488
+ }
1489
+ /**
1490
+ * @description Get row pin position
1491
+ * @param row The row to check
1492
+ * @returns 'top', 'bottom', or null
1493
+ */
1494
+ getRowPinPosition(row) {
1495
+ if (this.pinnedTopRows.includes(row))
1496
+ return 'top';
1497
+ if (this.pinnedBottomRows.includes(row))
1498
+ return 'bottom';
1499
+ return null;
1500
+ }
1501
+ /**
1502
+ * @description Get rows for main data section (excluding pinned rows)
1503
+ * @returns Array of non-pinned rows
1504
+ */
1505
+ getUnpinnedRows() {
1506
+ if (!this.dataSource?.data)
1507
+ return [];
1508
+ return this.dataSource.data.filter(row => !this.pinnedTopRows.includes(row) && !this.pinnedBottomRows.includes(row));
1509
+ }
1510
+ /**
1511
+ * @description Get combined data source with pinned rows
1512
+ */
1513
+ getCombinedDataSource() {
1514
+ if (!this.enableRowPinning || !this.dataSource?.data) {
1515
+ return this.dataSource?.data || [];
1516
+ }
1517
+ // Combine: pinnedTop + regular + pinnedBottom
1518
+ return [
1519
+ ...this.pinnedTopRows,
1520
+ ...this.dataSource.data.filter(row => !this.isRowPinned(row)),
1521
+ ...this.pinnedBottomRows
1522
+ ];
1523
+ }
1524
+ /**
1525
+ * @description Initialize pinned rows based on function
1526
+ */
1527
+ initializePinnedRows() {
1528
+ if (!this.rowPinningFn || !this.dataSource?.data)
1529
+ return;
1530
+ this.pinnedTopRows = [];
1531
+ this.pinnedBottomRows = [];
1532
+ this.dataSource.data.forEach((row, index) => {
1533
+ const position = this.rowPinningFn(row, index);
1534
+ if (position === 'top') {
1535
+ row._pinnedPosition = 'top';
1536
+ this.pinnedTopRows.push(row);
1537
+ }
1538
+ else if (position === 'bottom') {
1539
+ row._pinnedPosition = 'bottom';
1540
+ this.pinnedBottomRows.push(row);
1541
+ }
1542
+ });
1543
+ this.cdr.detectChanges();
1544
+ }
1545
+ /**
1546
+ * @description Update data source and recalculate pinned row offsets
1547
+ */
1548
+ updateDataSourceForPinning() {
1549
+ // Trigger change detection
1550
+ this.cdr.detectChanges();
1551
+ // Force table to re-render rows
1552
+ if (this.table) {
1553
+ this.table.renderRows();
1554
+ }
1555
+ // Update offsets for sticky positioning
1556
+ this.updatePinnedRowOffsets();
1557
+ }
1558
+ /**
1559
+ * @description This method will position the selection column to first and also update its visibility.
1560
+ * @param value value used to set visibility of the selection column.
1561
+ */
1562
+ updateSelectionColumnVisibility(value) {
1563
+ let columnName = 'select';
1564
+ let column = this.dynamicDisplayedColumns.filter((a) => a.name == columnName)[0];
1565
+ let index = this.dynamicDisplayedColumns.findIndex((column) => column.name == columnName);
1566
+ if (index > -1) {
1567
+ this.dynamicDisplayedColumns.splice(index, 1);
1568
+ this.dynamicDisplayedColumns.unshift(column);
1569
+ this.dynamicDisplayedColumns.filter((column) => column.name == columnName)[0].show = value;
1570
+ }
1571
+ }
1572
+ /**
1573
+ * @description This method is used to update the position of column in columns array according to its dropped position.
1574
+ * @param event CdkDragDrop used to update column position in columns array.
1575
+ */
1576
+ onDrop(event) {
1577
+ if (this.dndColumns) {
1578
+ let adjustedValue = 0;
1579
+ if (this.dynamicDisplayedColumns[0].name == 'select' &&
1580
+ this.dynamicDisplayedColumns[0].show == false) {
1581
+ adjustedValue = 1;
1582
+ }
1583
+ moveItemInArray(this.dynamicDisplayedColumns, event.previousIndex + adjustedValue, event.currentIndex + adjustedValue);
1584
+ if (this.enableRowPinning) {
1585
+ setTimeout(() => this.syncColumnSizesFromTop(), 80);
1586
+ }
1587
+ }
1588
+ }
1589
+ /**
1590
+ * @description This method create filter predicate function which will set search value to table filters
1591
+ * for both global and individual colum filtering.
1592
+ * @returns returns boolean value to filter rows in table.
1593
+ */
1594
+ createFilter() {
1595
+ const tableFilterPredicate = (data, filter) => {
1596
+ let result = true;
1597
+ // search all column fields
1598
+ if (this.globalFilter) {
1599
+ let expression = '';
1600
+ let keys = Object.keys(data);
1601
+ keys.forEach((key) => {
1602
+ expression =
1603
+ expression +
1604
+ `data.${key}.toString().trim().toLowerCase().indexOf(this.globalFilter.toLowerCase()) !== -1 ||`;
1605
+ });
1606
+ if (expression.charAt(expression.length - 2) +
1607
+ expression.charAt(expression.length - 1) ==
1608
+ '||') {
1609
+ expression = expression.substring(0, expression.length - 2);
1610
+ }
1611
+ result = eval(expression);
1612
+ }
1613
+ if (!result) {
1614
+ return false;
1615
+ }
1616
+ let searchString = JSON.parse(filter);
1617
+ //search single column field
1618
+ if (this.individualFilter) {
1619
+ return (data[this.individualFilter]
1620
+ .toString()
1621
+ .trim()
1622
+ .toLowerCase()
1623
+ .indexOf(searchString[this.individualFilter].toString().toLowerCase()) !== -1);
1624
+ }
1625
+ return true;
1626
+ };
1627
+ return tableFilterPredicate;
1628
+ }
1629
+ /**
1630
+ * @description assigns the search value to mat table data source to apply the filter.
1631
+ * @param searchValue value to be searched from table rows.
1632
+ */
1633
+ applyGlobalFilter(searchValue) {
1634
+ this.globalFilter = searchValue;
1635
+ let columns = {};
1636
+ this.columnsArray.forEach((column) => {
1637
+ if (column.field)
1638
+ columns[column.field] = searchValue;
1639
+ });
1640
+ this.dataSource.filter = JSON.stringify(columns);
1641
+ }
1642
+ /**
1643
+ * @description This method is used to apply column based filtering
1644
+ * @param searchValue value to be searched from table rows.
1645
+ * @param column filter will be applied based on this column field.
1646
+ */
1647
+ applyColumnFilter(searchValue, column) {
1648
+ this.individualFilter = column.field;
1649
+ this.filterValues[column.field] = searchValue[column.field];
1650
+ this.dataSource.filter = JSON.stringify(this.filterValues);
1651
+ if (this.enableRowPinning) {
1652
+ setTimeout(() => this.syncColumnSizesFromTop(), 80);
1653
+ }
1654
+ }
1655
+ /**
1656
+ * @description This method will take row and its index enable inline editing tools on that row.
1657
+ * @param row row on which user wants to do edit.
1658
+ * @param index index of the row where inline editing will be enabled.
1659
+ */
1660
+ enableInlineEditing(row, index) {
1661
+ // Check if another row is currently in edit mode
1662
+ const currentEditIndex = this.tableData.findIndex((r) => r.editable === true);
1663
+ if (currentEditIndex !== -1 && currentEditIndex !== index) {
1664
+ // Disable the previous row's edit mode
1665
+ this.tableData[currentEditIndex]['editable'] = false;
1666
+ // Clear the temporary data for the previous row
1667
+ this.rowDataTemp['e' + currentEditIndex] = {};
1668
+ // Restore original sizes when switching rows
1669
+ if (this.enableRowPinning && this.originalSizesBeforeEdit) {
1670
+ this.restoreOriginalSizes();
1671
+ }
1672
+ }
1673
+ const rowData = {};
1674
+ rowData['e' + index] = { ...row };
1675
+ this.rowDataTemp = rowData;
1676
+ setTimeout(() => {
1677
+ const wasEditable = this.tableData[index]['editable'];
1678
+ this.tableData[index]['editable'] = !this.tableData[index]['editable'];
1679
+ // If row is now in edit mode, sync sizes from this edited row
1680
+ if (this.tableData[index]['editable'] && this.enableRowPinning) {
1681
+ // Wait for DOM to update with edit controls
1682
+ setTimeout(() => {
1683
+ this.syncColumnSizesFromEditedRow(index);
1684
+ }, 100);
1685
+ }
1686
+ else if (!this.tableData[index]['editable'] && this.enableRowPinning) {
1687
+ // Row was disabled, restore original sizes
1688
+ this.restoreOriginalSizes();
1689
+ }
1690
+ }, 0);
1691
+ }
1692
+ /**
1693
+ * @description This method will create and return data to inline editing template.
1694
+ * @param row row on which user wants to do edit.
1695
+ * @param index index of the row where inline editing will be enabled.
1696
+ * @param column current column of the table.
1697
+ */
1698
+ getInlineEditingData(row, index, column) {
1699
+ this.inlineEditingTemplateRefData = {
1700
+ row: { ...row },
1701
+ column: { ...column },
1702
+ index: index,
1703
+ updateFunc: this.updateInlineTemplateData,
1704
+ };
1705
+ return this.inlineEditingTemplateRefData;
1706
+ }
1707
+ /**
1708
+ * @description This method set data for in-cell editing.
1709
+ * @param row row on which user wants to do edit.
1710
+ * @param index index of the row where inline editing will be enabled.
1711
+ */
1712
+ setCellData(row, index) {
1713
+ // If there's already an inline edit in progress, cancel it first
1714
+ if (this.currentRowIndex !== -1 && this.currentRowIndex !== index) {
1715
+ // Find and cancel the previous inline editing row
1716
+ const previousEditableRow = this.tableData.find((r, i) => i === this.currentRowIndex && r.editable);
1717
+ if (previousEditableRow) {
1718
+ previousEditableRow['editable'] = false;
1719
+ }
1720
+ // Clear previous cell editing states
1721
+ Object.keys(this.cellEditing).forEach(key => {
1722
+ if (key.startsWith(this.currentRowIndex + '_')) {
1723
+ delete this.cellEditing[key];
1724
+ }
1725
+ });
1726
+ this.rowDataTemp['e' + this.currentRowIndex] = {};
1727
+ // Restore sizes when switching from previous cell editing
1728
+ if (this.enableRowPinning) {
1729
+ this.restoreOriginalSizes();
1730
+ }
1731
+ }
1732
+ this.currentRow = { ...row };
1733
+ this.currentRowIndex = index;
1734
+ this.rowDataTemp['e' + index] = { ...row };
1735
+ // Sync column sizes from the edited row when cell editing starts
1736
+ if (this.enableRowPinning) {
1737
+ setTimeout(() => {
1738
+ this.syncColumnSizesFromEditedRow(index);
1739
+ }, 50);
1740
+ }
1741
+ }
1742
+ /**
1743
+ * @description This will restore the data and cencel the inline editing.
1744
+ * @param row row on which user wants to do edit.
1745
+ * @param index index of the row where inline editing will be enabled.
1746
+ */
1747
+ cancelInlineEditing(row, index) {
1748
+ this.tableData.filter((a, i) => i == index)[0]['editable'] =
1749
+ !this.tableData.filter((a, i) => i == index)[0]['editable'];
1750
+ this.dataSource = new MatTableDataSource(this.tableData);
1751
+ this.rowDataTemp['e' + index] = {};
1752
+ this.service.selectedRow.next(undefined);
1753
+ // Restore original sizes after canceling edit mode
1754
+ if (this.enableRowPinning) {
1755
+ this.restoreOriginalSizes();
1756
+ }
1757
+ }
1758
+ /**
1759
+ * @description This method will save and update the inline editing data and emit the update row and index.
1760
+ * @param row row on which user wants to do edit.
1761
+ * @param index index of the row where inline editing will be enabled.
1762
+ */
1763
+ saveInlineEditing(row, index) {
1764
+ if (!this.inlineEditingTemplateRef) {
1765
+ this.tableData[index] = { ...this.rowDataTemp['e' + index] };
1766
+ row = { ...this.rowDataTemp['e' + index] };
1767
+ }
1768
+ else {
1769
+ let changedData = this.service.selectedRow.value;
1770
+ if (changedData) {
1771
+ this.tableData[index] = { ...changedData };
1772
+ }
1773
+ }
1774
+ this.dataSource = new MatTableDataSource(this.tableData);
1775
+ this.rowDataTemp['e' + index] = {};
1776
+ let data = {
1777
+ row: row,
1778
+ index: index,
1779
+ };
1780
+ this.inlineChange.emit(data);
1781
+ this.tableData[index]['editable'] = false;
1782
+ // Restore original sizes after saving edit mode
1783
+ if (this.enableRowPinning) {
1784
+ this.restoreOriginalSizes();
1785
+ }
1786
+ }
1787
+ /**
1788
+ * @description This method will save and update the cell editing data and emit the update row and index.
1789
+ */
1790
+ saveCellEditing() {
1791
+ this.cellEditing = {};
1792
+ let index = this.currentRowIndex;
1793
+ if (index > -1) {
1794
+ if (this.cellEditingTemplateRef) {
1795
+ let changedData = this.service.selectedRow.value;
1796
+ if (changedData) {
1797
+ this.tableData[index] = { ...changedData };
1798
+ }
1799
+ }
1800
+ else {
1801
+ this.tableData[index] = { ...this.rowDataTemp['e' + index] };
1802
+ }
1803
+ this.dataSource = new MatTableDataSource(this.tableData);
1804
+ this.rowDataTemp['e' + index] = {};
1805
+ let data = {
1806
+ row: { ...this.tableData[index] },
1807
+ index: index,
1808
+ };
1809
+ this.currentRowIndex = -1;
1810
+ this.cellChange.emit(data);
1811
+ // Restore original sizes after saving cell edits
1812
+ if (this.enableRowPinning) {
1813
+ this.restoreOriginalSizes();
1814
+ }
1815
+ }
1816
+ }
1817
+ /**
1818
+ * @description This method will delete the row from the given index and emit the deleted row and index.
1819
+ * @param row row to be deleted.
1820
+ * @param index index of the row to be deleted.
1821
+ */
1822
+ deleteRow(row, index) {
1823
+ // this.tableData.splice(index, 1);
1824
+ // this.dataSource = new MatTableDataSource(this.tableData);
1825
+ // this.dataSource.paginator = this.paginator;
1826
+ // this.dataSource.sort = this.sort;
1827
+ this.rowDeleted.emit({ removedRow: row, fromIndex: index });
1828
+ }
1829
+ /**
1830
+ * @description This method will expand or collapse the row and emit expand event.
1831
+ * @param row row to be expanded or collapsed.
1832
+ * @param expand value used to expand or collapse the row.
1833
+ * @param index index of the row.
1834
+ */
1835
+ expandRow(row, expand, index) {
1836
+ if (this.expandRows) {
1837
+ this.expansionChange.emit({ data: row, expanded: expand, index: index });
1838
+ this.expandedElement = this.expandedElement === row ? null : row;
1839
+ }
1840
+ }
1841
+ /**
1842
+ * @description This method is used to set data for popup component and open editing dialog.
1843
+ * @param row row which used want to edit.
1844
+ */
1845
+ openEditingDialog(row) {
1846
+ const dialogConfig = new MatDialogConfig();
1847
+ dialogConfig.disableClose = true;
1848
+ dialogConfig.width = '40%';
1849
+ dialogConfig.height = '70%';
1850
+ dialogConfig.maxWidth = '100%';
1851
+ let rowData = { ...row };
1852
+ dialogConfig.data = {
1853
+ row: rowData,
1854
+ columns: [...this.columnsArray],
1855
+ templateRef: this.popupEditingTemplateRef,
1856
+ };
1857
+ this.dialog
1858
+ .open(EditingComponent, dialogConfig)
1859
+ .afterClosed()
1860
+ .subscribe((data) => {
1861
+ let index = this.tableData.indexOf(row);
1862
+ if (data && index > -1) {
1863
+ this.tableData[index] = data;
1864
+ this.dataSource = new MatTableDataSource(this.tableData);
1865
+ let dataChange = {
1866
+ row: data,
1867
+ index: index,
1868
+ };
1869
+ this.popupChange.emit(dataChange);
1870
+ if (this.enableRowPinning) {
1871
+ setTimeout(() => this.syncColumnSizesFromTop(), 80);
1872
+ }
1873
+ }
1874
+ });
1875
+ }
1876
+ /**
1877
+ * @description This method is used to open cell popup editing dialog for a single cell.
1878
+ * @param row row which contains the cell to edit.
1879
+ * @param column column definition of the cell to edit.
1880
+ * @param rowIndex index of the row.
1881
+ */
1882
+ openCellPopupDialog(row, column, rowIndex) {
1883
+ const dialogConfig = new MatDialogConfig();
1884
+ dialogConfig.disableClose = true;
1885
+ dialogConfig.width = '400px';
1886
+ dialogConfig.height = 'auto';
1887
+ dialogConfig.maxWidth = '100%';
1888
+ dialogConfig.data = {
1889
+ row: { ...row },
1890
+ column: column,
1891
+ rowIndex: rowIndex,
1892
+ isCellEdit: true,
1893
+ templateRef: this.cellPopupEditingTemplateRef,
1894
+ };
1895
+ this.dialog
1896
+ .open(EditingComponent, dialogConfig)
1897
+ .afterClosed()
1898
+ .subscribe((data) => {
1899
+ if (data && data.field && rowIndex > -1) {
1900
+ this.tableData[rowIndex][data.field] = data.value;
1901
+ this.dataSource = new MatTableDataSource(this.tableData);
1902
+ let dataChange = {
1903
+ row: { ...this.tableData[rowIndex] },
1904
+ index: rowIndex,
1905
+ };
1906
+ this.cellChange.emit(dataChange);
1907
+ if (this.enableRowPinning) {
1908
+ setTimeout(() => this.syncColumnSizesFromTop(), 80);
1909
+ }
1910
+ }
1911
+ });
1912
+ }
1913
+ /**
1914
+ * @description used to check whether all rows are selected.
1915
+ */
1916
+ isAllSelected() {
1917
+ const numSelected = this.selection.selected.length;
1918
+ const numRows = this.dataSource.data.length;
1919
+ return numSelected === numRows;
1920
+ }
1921
+ /**
1922
+ * @description this method is used to toggle the all and no rows selection.
1923
+ */
1924
+ toggleAllRows() {
1925
+ if (this.isAllSelected()) {
1926
+ this.selection.clear();
1927
+ return;
1928
+ }
1929
+ this.selection.select(...this.dataSource.data);
1930
+ }
1931
+ /**
1932
+ * @description This method is used return aria-label for selection column checkboxs.
1933
+ * @param row row from table.
1934
+ * @returns labels for selection column checkboxs.
1935
+ */
1936
+ checkboxLabel(row) {
1937
+ if (!row) {
1938
+ return `${this.isAllSelected() ? 'deselect' : 'select'} all`;
1939
+ }
1940
+ return `${this.selection.isSelected(row) ? 'deselect' : 'select'} row ${row.position + 1}`;
1941
+ }
1942
+ /**
1943
+ * @description create form control for columns for hiding and and pinning purpose
1944
+ * @param columns list of columns to be displayed
1945
+ */
1946
+ setToolbarMenuControls(columns) {
1947
+ if (columns.length > 0 && this.showToolbar) {
1948
+ const group = this.formBuilder.group({});
1949
+ columns.forEach((column) => {
1950
+ const control = this.formBuilder.control(true);
1951
+ group.addControl(column.field, control);
1952
+ });
1953
+ this.hideShowMenuGroup = group;
1954
+ }
1955
+ }
1956
+ /**
1957
+ * @param column current column
1958
+ * @param event mouse event used to set the menu position
1959
+ */
1960
+ openPinnablePropertyMenu(column, event) {
1961
+ this.menuX = event.clientX;
1962
+ this.menuY = event.clientY;
1963
+ let options = [
1964
+ {
1965
+ label: 'Pin Left',
1966
+ value: 'left',
1967
+ selected: false,
1968
+ field: column.field,
1969
+ },
1970
+ {
1971
+ label: 'Pin Right',
1972
+ value: 'right',
1973
+ selected: false,
1974
+ field: column.field,
1975
+ },
1976
+ { label: 'No Pin', value: null, selected: false, field: column.field },
1977
+ ];
1978
+ if (column.pinned && column.pinned !== null) {
1979
+ options.forEach((opt) => {
1980
+ if (opt.value === column.pinned) {
1981
+ opt.selected = true;
1982
+ }
1983
+ });
1984
+ }
1985
+ else if (column.pinned == null || column.pinned == 'null') {
1986
+ options[2].selected = true;
1987
+ }
1988
+ this.columnPinningOptions = options;
1989
+ this.columnMenuTrigger.openMenu();
1990
+ }
1991
+ /**
1992
+ * @description This method is used to reset menu checks when required.
1993
+ */
1994
+ resetMenuChecks() {
1995
+ this.hideShowMenuCtrl = false;
1996
+ this.showHideColumnsArray = [];
1997
+ this.columnPinMenuCtrl = false;
1998
+ this.columnPinningOptions = [];
1999
+ }
2000
+ /**
2001
+ * @description This method is used to filter columns for menus like pinning or hide show menu.
2002
+ * @param value search value to filter colunms
2003
+ */
2004
+ filterColumns(value) {
2005
+ if (value !== '') {
2006
+ this.showHideColumnsArray = this.columnsArray.filter((col) => {
2007
+ return col.header.toLowerCase().includes(value.toLowerCase());
2008
+ });
2009
+ }
2010
+ else {
2011
+ this.showHideColumnsArray = this.columnsArray;
2012
+ }
2013
+ }
2014
+ /**
2015
+ * @description This method is used to open hide show column menu.
2016
+ * @param columns columns array to display in hide show menu.
2017
+ */
2018
+ openHideShowMenu(columns) {
2019
+ this.showHideColumnsArray = [...columns];
2020
+ this.columnMenuTrigger.openMenu();
2021
+ }
2022
+ /**
2023
+ * @param values columns
2024
+ */
2025
+ updateColumnsHideShow(values) {
2026
+ let keys = Object.keys(values);
2027
+ keys.forEach((key) => {
2028
+ this.showHideColumn(key, values[key]);
2029
+ });
2030
+ }
2031
+ /**
2032
+ * @description This method is called when the table rows are scrolled.
2033
+ * @param event scroll event
2034
+ */
2035
+ onScroll(event) {
2036
+ this.scroll.emit(event);
2037
+ }
2038
+ /**
2039
+ * @param row row to be toggled
2040
+ * @param index index of toggled row
2041
+ */
2042
+ setSelectedRows(row, index) {
2043
+ this.selection.toggle(row);
2044
+ if (this.selection.isSelected(row)) {
2045
+ this.selectionChanged.emit({ row: row, index: index, isSelected: true });
2046
+ }
2047
+ else {
2048
+ this.selectionChanged.emit({ row: row, index: index, isSelected: false });
2049
+ }
2050
+ }
2051
+ /**
2052
+ * @description This method is used to display all hidden rows.
2053
+ */
2054
+ showHiddenRows() {
2055
+ this.hideRows = false;
2056
+ this.selection.clear();
2057
+ this.hiddenCtrl.clear();
2058
+ }
2059
+ /**
2060
+ * @description This method is used to hide all selected rows.
2061
+ */
2062
+ hideSelectedRows() {
2063
+ if (!this.selection.isEmpty()) {
2064
+ let values = [...this.selection.selected];
2065
+ values.forEach((value) => {
2066
+ if (!this.hiddenCtrl.isSelected(value)) {
2067
+ this.hiddenCtrl.toggle(value);
2068
+ }
2069
+ });
2070
+ this.selection.clear();
2071
+ this.hideRows = true;
2072
+ }
2073
+ }
2074
+ /**
2075
+ * @description This method is used to recalculate the required values for table.
2076
+ */
2077
+ reCal() {
2078
+ if (this.showPaginator) {
2079
+ this.dataSource.paginator = this.paginator;
2080
+ }
2081
+ if (this.sorting) {
2082
+ this.dataSource.sort = this.sort;
2083
+ if (this.enableRowPinning) {
2084
+ this.pinnedTopDataSource.sort = this.sort;
2085
+ this.pinnedBtmDataSource.sort = this.sort;
2086
+ }
2087
+ }
2088
+ if (this.columnFilter) {
2089
+ this.dataSource.filterPredicate = this.createFilter();
2090
+ this.pinnedTopDataSource.filterPredicate = this.createFilter();
2091
+ this.pinnedBtmDataSource.filterPredicate = this.createFilter();
2092
+ }
2093
+ this.cdr.detectChanges();
2094
+ }
2095
+ /**
2096
+ * @description This method is called in constructor method to add SVGs into icon registration.
2097
+ */
2098
+ addIconsToRegistry() {
2099
+ let y = this.domSanitizer.bypassSecurityTrustResourceUrl(`assets/pinRight.svg`);
2100
+ let iconNames = ['pinLeft', 'pinRight', 'pinNone', 'pinned', 'pinIcon'];
2101
+ iconNames.forEach((icon) => {
2102
+ this.matIconRegistry.addSvgIcon(icon, this.domSanitizer.bypassSecurityTrustResourceUrl(`assets/${icon}.svg`));
2103
+ });
2104
+ }
2105
+ /**
2106
+ * @description This method is used to export table data.
2107
+ * @param type type of file to be exported.
2108
+ */
2109
+ exportTable(type) {
2110
+ const actionColumns = ['select', 'edit', 'popup', 'delete', 'freeze', 'hide', 'pin'];
2111
+ // Get visible columns in the correct order (grouped first, ungrouped at end)
2112
+ let visibleColumns = [];
2113
+ if (this.columnGroups.length > 0) {
2114
+ const groupedFields = new Set();
2115
+ // Collect all fields that belong to groups
2116
+ this.columnGroups.forEach(group => {
2117
+ group.columns.forEach(colField => groupedFields.add(colField));
2118
+ });
2119
+ // Add grouped columns first (in group order)
2120
+ this.columnGroups.forEach(group => {
2121
+ group.columns.forEach(colField => {
2122
+ const col = this.columnsArray.find(c => c.field === colField);
2123
+ const displayCol = this.dynamicDisplayedColumns.find(dc => dc.name === colField);
2124
+ if (col && displayCol && displayCol.show && !visibleColumns.includes(col)) {
2125
+ visibleColumns.push(col);
2126
+ }
2127
+ });
2128
+ });
2129
+ // Add ungrouped columns at the end
2130
+ this.columnsArray.forEach(col => {
2131
+ const displayCol = this.dynamicDisplayedColumns.find(dc => dc.name === col.field);
2132
+ if (!groupedFields.has(col.field) && displayCol && displayCol.show &&
2133
+ !actionColumns.includes(col.field) && !visibleColumns.includes(col)) {
2134
+ visibleColumns.push(col);
2135
+ }
2136
+ });
2137
+ }
2138
+ else {
2139
+ // No groups, use default order
2140
+ visibleColumns = this.columnsArray.filter(col => {
2141
+ const displayCol = this.dynamicDisplayedColumns.find(dc => dc.name === col.field);
2142
+ return displayCol && displayCol.show && !actionColumns.includes(col.field);
2143
+ });
2144
+ }
2145
+ const data = [];
2146
+ // Add group headers if they exist
2147
+ if (this.columnGroups.length > 0) {
2148
+ const groupRow = [];
2149
+ const columnIndexMap = {};
2150
+ visibleColumns.forEach((col, idx) => {
2151
+ columnIndexMap[col.field] = idx;
2152
+ });
2153
+ // Initialize group row with empty strings
2154
+ for (let i = 0; i < visibleColumns.length; i++) {
2155
+ groupRow.push('');
2156
+ }
2157
+ // Fill in group labels
2158
+ this.columnGroups.forEach(group => {
2159
+ const groupCols = group.columns.filter(colField => visibleColumns.find(vc => vc.field === colField));
2160
+ if (groupCols.length > 0) {
2161
+ const firstColIndex = columnIndexMap[groupCols[0]];
2162
+ groupRow[firstColIndex] = group.label;
2163
+ }
2164
+ });
2165
+ data.push(groupRow);
2166
+ }
2167
+ // Add column headers
2168
+ data.push(visibleColumns.map(col => col.header || col.field));
2169
+ // Add data rows (exclude hidden rows)
2170
+ this.dataSource.data.forEach((row, index) => {
2171
+ // Skip hidden rows
2172
+ if (this.hiddenRowIndices.includes(index)) {
2173
+ return;
2174
+ }
2175
+ const rowData = visibleColumns.map(col => {
2176
+ const value = row[col.field];
2177
+ if (value === null || value === undefined)
2178
+ return '';
2179
+ if (typeof value === 'boolean')
2180
+ return value ? 'Yes' : 'No';
2181
+ if (value instanceof Date)
2182
+ return new Intl.DateTimeFormat('en-US').format(value);
2183
+ return value;
2184
+ });
2185
+ data.push(rowData);
2186
+ });
2187
+ const ws = XLSX.utils.aoa_to_sheet(data);
2188
+ // Add merge cells for group headers if they exist
2189
+ if (this.columnGroups.length > 0) {
2190
+ if (!ws['!merges']) {
2191
+ ws['!merges'] = [];
2192
+ }
2193
+ const columnIndexMap = {};
2194
+ visibleColumns.forEach((col, idx) => {
2195
+ columnIndexMap[col.field] = idx;
2196
+ });
2197
+ this.columnGroups.forEach(group => {
2198
+ const groupCols = group.columns.filter(colField => visibleColumns.find(vc => vc.field === colField));
2199
+ if (groupCols.length > 1 && ws['!merges']) {
2200
+ const firstColIndex = columnIndexMap[groupCols[0]];
2201
+ const lastColIndex = columnIndexMap[groupCols[groupCols.length - 1]];
2202
+ ws['!merges'].push({
2203
+ s: { r: 0, c: firstColIndex },
2204
+ e: { r: 0, c: lastColIndex }
2205
+ });
2206
+ }
2207
+ });
2208
+ }
2209
+ const wb = XLSX.utils.book_new();
2210
+ XLSX.utils.book_append_sheet(wb, ws, 'Sheet1');
2211
+ XLSX.writeFile(wb, `tablesheets.${type}`);
2212
+ }
2213
+ /**
2214
+ * @description This method is used to print the table with proper styling.
2215
+ */
2216
+ printTable() {
2217
+ const printContent = document.getElementById('matTableExt' + this.tableID);
2218
+ if (!printContent)
2219
+ return;
2220
+ const windowPrint = window.open('', '', 'width=900,height=650');
2221
+ if (!windowPrint)
2222
+ return;
2223
+ windowPrint.document.write('<html><head><title>Print Table</title>');
2224
+ windowPrint.document.write('<style>');
2225
+ windowPrint.document.write(`
2226
+ table { border-collapse: collapse; width: 100%; font-family: Arial, sans-serif; }
2227
+ th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
2228
+ th { background-color: #f2f2f2; font-weight: bold; }
2229
+ tr:nth-child(even) { background-color: #f9f9f9; }
2230
+ .mat-sort-header-container { display: inline; }
2231
+ .mat-sort-header-arrow, .mat-sort-header-indicator { display: none !important; }
2232
+ button, .mat-icon { display: none !important; }
2233
+ @media print {
2234
+ .mat-mdc-table { page-break-inside: auto; }
2235
+ tr { page-break-inside: avoid; page-break-after: auto; }
2236
+ thead { display: table-header-group; }
2237
+ }
2238
+ `);
2239
+ windowPrint.document.write('</style></head><body>');
2240
+ // Clone the table and remove all action columns
2241
+ const tableClone = printContent.cloneNode(true);
2242
+ // Define action column class selectors
2243
+ const actionColumnSelectors = [
2244
+ 'th.action-column-cells',
2245
+ 'td.inline-edit-column-cell',
2246
+ // Remove columns by checking for action column names
2247
+ '[matColumnDef="select"]',
2248
+ '[matColumnDef="edit"]',
2249
+ '[matColumnDef="popup"]',
2250
+ '[matColumnDef="delete"]',
2251
+ '[matColumnDef="freeze"]',
2252
+ '[matColumnDef="hide"]',
2253
+ ];
2254
+ // Remove all matching elements
2255
+ actionColumnSelectors.forEach(selector => {
2256
+ const elements = tableClone.querySelectorAll(selector);
2257
+ elements.forEach(el => el.remove());
2258
+ });
2259
+ // Also remove cells by index for action columns
2260
+ const actionColumnIndices = [];
2261
+ const headerRow = tableClone.querySelector('tr.mat-mdc-header-row');
2262
+ if (headerRow) {
2263
+ const headers = Array.from(headerRow.querySelectorAll('th'));
2264
+ headers.forEach((th, index) => {
2265
+ if (th.classList.contains('action-column-cells')) {
2266
+ actionColumnIndices.push(index);
2267
+ }
2268
+ });
2269
+ }
2270
+ // Remove cells at action column indices from all rows
2271
+ const rows = tableClone.querySelectorAll('tr');
2272
+ rows.forEach((row, rowIndex) => {
2273
+ // Remove hidden rows (accounting for header rows)
2274
+ const dataIndex = rowIndex - 1; // Subtract 1 for header row
2275
+ if (dataIndex >= 0 && this.hiddenRowIndices.includes(dataIndex)) {
2276
+ row.remove();
2277
+ return;
2278
+ }
2279
+ const cells = Array.from(row.querySelectorAll('th, td'));
2280
+ // Remove in reverse order to maintain correct indices
2281
+ for (let i = actionColumnIndices.length - 1; i >= 0; i--) {
2282
+ const index = actionColumnIndices[i];
2283
+ if (cells[index]) {
2284
+ cells[index].remove();
2285
+ }
2286
+ }
2287
+ });
2288
+ windowPrint.document.write(tableClone.outerHTML);
2289
+ windowPrint.document.write('</body></html>');
2290
+ windowPrint.document.close();
2291
+ setTimeout(() => {
2292
+ windowPrint.print();
2293
+ windowPrint.close();
2294
+ }, 250);
2295
+ }
2296
+ async exportToPDF() {
2297
+ try {
2298
+ // Correct jsPDF import
2299
+ const JsPDF = (await import('jspdf')).default;
2300
+ // Correct AutoTable import
2301
+ const autoTableModule = await import('jspdf-autotable');
2302
+ const autoTable = autoTableModule.autoTable || autoTableModule.default;
2303
+ // Create PDF with user-specified orientation
2304
+ const doc = new JsPDF({
2305
+ orientation: this.pdfOrientation,
2306
+ unit: 'mm',
2307
+ format: 'a4'
2308
+ });
2309
+ const actionColumns = ['select', 'edit', 'popup', 'delete', 'freeze', 'hide', 'pin'];
2310
+ // Get visible columns in the correct order (grouped first, ungrouped at end)
2311
+ let visibleColumns = [];
2312
+ if (this.columnGroups.length > 0) {
2313
+ const groupedFields = new Set();
2314
+ // Collect all fields that belong to groups
2315
+ this.columnGroups.forEach(group => {
2316
+ group.columns.forEach(colField => groupedFields.add(colField));
2317
+ });
2318
+ // Add grouped columns first (in group order)
2319
+ this.columnGroups.forEach(group => {
2320
+ group.columns.forEach(colField => {
2321
+ const col = this.columnsArray.find(c => c.field === colField);
2322
+ const displayCol = this.dynamicDisplayedColumns.find(dc => dc.name === colField);
2323
+ if (col && displayCol && displayCol.show && !visibleColumns.includes(col)) {
2324
+ visibleColumns.push(col);
2325
+ }
2326
+ });
2327
+ });
2328
+ // Add ungrouped columns at the end
2329
+ this.columnsArray.forEach(col => {
2330
+ const displayCol = this.dynamicDisplayedColumns.find(dc => dc.name === col.field);
2331
+ if (!groupedFields.has(col.field) && displayCol && displayCol.show &&
2332
+ !actionColumns.includes(col.field) && !visibleColumns.includes(col)) {
2333
+ visibleColumns.push(col);
2334
+ }
2335
+ });
2336
+ }
2337
+ else {
2338
+ // No groups, use default order
2339
+ visibleColumns = this.columnsArray.filter(col => {
2340
+ const displayCol = this.dynamicDisplayedColumns.find(dc => dc.name === col.field);
2341
+ return displayCol && displayCol.show && !actionColumns.includes(col.field);
2342
+ });
2343
+ }
2344
+ // Prepare group headers if column groups exist
2345
+ let groupHeaders = [];
2346
+ let columnIndexMap = {};
2347
+ let groupColSpans = {};
2348
+ if (this.columnGroups.length > 0) {
2349
+ // Build column index map
2350
+ visibleColumns.forEach((col, idx) => {
2351
+ columnIndexMap[col.field] = idx;
2352
+ });
2353
+ // Create group header row
2354
+ const groupRow = [];
2355
+ let currentIndex = 0;
2356
+ this.columnGroups.forEach(group => {
2357
+ const groupCols = group.columns.filter(colField => visibleColumns.find(vc => vc.field === colField));
2358
+ if (groupCols.length > 0) {
2359
+ const firstColIndex = columnIndexMap[groupCols[0]];
2360
+ // Add the group header cell with content and colspan
2361
+ groupRow.push({
2362
+ content: group.label,
2363
+ colSpan: groupCols.length,
2364
+ styles: { halign: 'center' }
2365
+ });
2366
+ groupColSpans[firstColIndex] = groupCols.length;
2367
+ currentIndex = firstColIndex + groupCols.length;
2368
+ }
2369
+ });
2370
+ // Add empty cells for ungrouped columns
2371
+ const groupedFields = new Set();
2372
+ this.columnGroups.forEach(group => {
2373
+ group.columns.forEach(colField => groupedFields.add(colField));
2374
+ });
2375
+ const ungroupedCount = visibleColumns.filter(col => !groupedFields.has(col.field)).length;
2376
+ for (let i = 0; i < ungroupedCount; i++) {
2377
+ groupRow.push({
2378
+ content: '',
2379
+ styles: { halign: 'center' }
2380
+ });
2381
+ }
2382
+ groupHeaders = [groupRow];
2383
+ }
2384
+ const headers = visibleColumns.map(col => col.header || col.field);
2385
+ const rows = this.dataSource.data
2386
+ .map((row, index) => ({
2387
+ row,
2388
+ index
2389
+ }))
2390
+ .filter(({ index }) => !this.hiddenRowIndices.includes(index))
2391
+ .map(({ row }) => visibleColumns.map(col => {
2392
+ const value = row[col.field];
2393
+ if (value === null || value === undefined)
2394
+ return '';
2395
+ if (typeof value === 'boolean')
2396
+ return value ? 'Yes' : 'No';
2397
+ if (value instanceof Date)
2398
+ return new Intl.DateTimeFormat('en-US').format(value);
2399
+ return String(value);
2400
+ }));
2401
+ let startY = 10;
2402
+ if (this.toolbarTitle) {
2403
+ doc.text(this.toolbarTitle, 14, 15);
2404
+ startY = 20;
2405
+ }
2406
+ // Extract header styles from actual mat-table
2407
+ let headerStyles = {
2408
+ fillColor: [245, 245, 245], // Default Material table header background (#f5f5f5)
2409
+ textColor: [0, 0, 0], // Default Material table header text (black)
2410
+ fontStyle: 'bold'
2411
+ };
2412
+ // If headerTemplateRef is defined, extract styles from the actual header cells
2413
+ if (this.headerTemplateRef) {
2414
+ const headerCells = this.tableElement?.nativeElement?.querySelectorAll('.mat-mdc-header-cell');
2415
+ if (headerCells && headerCells.length > 0) {
2416
+ const firstHeader = headerCells[0];
2417
+ const computedStyles = window.getComputedStyle(firstHeader);
2418
+ // Extract background color
2419
+ const bgColor = computedStyles.backgroundColor;
2420
+ if (bgColor && bgColor !== 'rgba(0, 0, 0, 0)' && bgColor !== 'transparent') {
2421
+ const rgb = bgColor.match(/\d+/g);
2422
+ if (rgb && rgb.length >= 3) {
2423
+ headerStyles.fillColor = [parseInt(rgb[0]), parseInt(rgb[1]), parseInt(rgb[2])];
2424
+ }
2425
+ }
2426
+ // Extract text color
2427
+ const textColor = computedStyles.color;
2428
+ if (textColor) {
2429
+ const rgb = textColor.match(/\d+/g);
2430
+ if (rgb && rgb.length >= 3) {
2431
+ headerStyles.textColor = [parseInt(rgb[0]), parseInt(rgb[1]), parseInt(rgb[2])];
2432
+ }
2433
+ }
2434
+ // Extract font weight
2435
+ const fontWeight = computedStyles.fontWeight;
2436
+ if (fontWeight && (fontWeight === 'bold' || parseInt(fontWeight) >= 600)) {
2437
+ headerStyles.fontStyle = 'bold';
2438
+ }
2439
+ else {
2440
+ headerStyles.fontStyle = 'normal';
2441
+ }
2442
+ }
2443
+ }
2444
+ // Extract group header styles if groups exist
2445
+ let groupHeaderStyles = null;
2446
+ if (groupHeaders.length > 0) {
2447
+ // Extract from group-header-cell elements
2448
+ const groupHeaderCells = this.tableElement?.nativeElement?.querySelectorAll('.group-header-cell');
2449
+ if (groupHeaderCells && groupHeaderCells.length > 0) {
2450
+ const firstGroupHeader = groupHeaderCells[0];
2451
+ const computedStyles = window.getComputedStyle(firstGroupHeader);
2452
+ groupHeaderStyles = {};
2453
+ // Extract background color
2454
+ const bgColor = computedStyles.backgroundColor;
2455
+ if (bgColor && bgColor !== 'rgba(0, 0, 0, 0)' && bgColor !== 'transparent') {
2456
+ const rgb = bgColor.match(/\d+/g);
2457
+ if (rgb && rgb.length >= 3) {
2458
+ groupHeaderStyles.fillColor = [parseInt(rgb[0]), parseInt(rgb[1]), parseInt(rgb[2])];
2459
+ }
2460
+ }
2461
+ else {
2462
+ // Default to same as header background
2463
+ groupHeaderStyles.fillColor = headerStyles.fillColor;
2464
+ }
2465
+ // Extract text color
2466
+ const textColor = computedStyles.color;
2467
+ if (textColor) {
2468
+ const rgb = textColor.match(/\d+/g);
2469
+ if (rgb && rgb.length >= 3) {
2470
+ groupHeaderStyles.textColor = [parseInt(rgb[0]), parseInt(rgb[1]), parseInt(rgb[2])];
2471
+ }
2472
+ }
2473
+ else {
2474
+ // Default to same as header text
2475
+ groupHeaderStyles.textColor = headerStyles.textColor;
2476
+ }
2477
+ // Extract font weight
2478
+ const fontWeight = computedStyles.fontWeight;
2479
+ if (fontWeight && (fontWeight === 'bold' || parseInt(fontWeight) >= 600)) {
2480
+ groupHeaderStyles.fontStyle = 'bold';
2481
+ }
2482
+ else {
2483
+ groupHeaderStyles.fontStyle = 'normal';
2484
+ }
2485
+ }
2486
+ else {
2487
+ // No group header cells found, use same as regular headers
2488
+ groupHeaderStyles = { ...headerStyles };
2489
+ }
2490
+ }
2491
+ // Build table config without default grid borders. We'll draw only
2492
+ // bottom dividers manually in `didDrawCell` so there are no left/right borders.
2493
+ const tableConfig = {
2494
+ head: groupHeaders.length > 0 ? [...groupHeaders, headers] : [headers],
2495
+ body: rows,
2496
+ startY: startY,
2497
+ // Use 'plain' so autowire doesn't draw full grid borders
2498
+ theme: 'plain',
2499
+ styles: {
2500
+ fontSize: 9,
2501
+ cellPadding: 3,
2502
+ // ensure autTable doesn't draw default lines
2503
+ lineWidth: 0
2504
+ },
2505
+ headStyles: headerStyles
2506
+ };
2507
+ // didParseCell: apply header/group header visual styles (background/text/font)
2508
+ tableConfig.didParseCell = (data) => {
2509
+ // Group header row styling (if present)
2510
+ if (data.section === 'head' && groupHeaders.length > 0 && data.row.index === 0 && groupHeaderStyles) {
2511
+ if (groupHeaderStyles.fillColor)
2512
+ data.cell.styles.fillColor = groupHeaderStyles.fillColor;
2513
+ if (groupHeaderStyles.textColor)
2514
+ data.cell.styles.textColor = groupHeaderStyles.textColor;
2515
+ if (groupHeaderStyles.fontStyle)
2516
+ data.cell.styles.fontStyle = groupHeaderStyles.fontStyle;
2517
+ data.cell.styles.halign = 'center';
2518
+ }
2519
+ // Final header row (column labels) should use headerStyles
2520
+ if (data.section === 'head' && data.row.index === (groupHeaders.length > 0 ? groupHeaders.length : 0)) {
2521
+ if (headerStyles.fillColor)
2522
+ data.cell.styles.fillColor = headerStyles.fillColor;
2523
+ if (headerStyles.textColor)
2524
+ data.cell.styles.textColor = headerStyles.textColor;
2525
+ if (headerStyles.fontStyle)
2526
+ data.cell.styles.fontStyle = headerStyles.fontStyle;
2527
+ }
2528
+ };
2529
+ // didDrawCell: draw only the bottom divider line for each cell
2530
+ tableConfig.didDrawCell = (data) => {
2531
+ try {
2532
+ const cell = data.cell;
2533
+ const docRef = doc;
2534
+ // Determine stroke color and width for divider
2535
+ const lineColor = [200, 200, 200];
2536
+ const lineWidth = 0.5;
2537
+ // Coordinates: draw a horizontal line across the bottom of the cell
2538
+ const x1 = cell.x;
2539
+ const x2 = cell.x + cell.width;
2540
+ const y = cell.y + cell.height;
2541
+ docRef.setDrawColor(lineColor[0], lineColor[1], lineColor[2]);
2542
+ docRef.setLineWidth(lineWidth);
2543
+ docRef.line(x1, y, x2, y);
2544
+ }
2545
+ catch (err) {
2546
+ // don't block export on draw errors
2547
+ }
2548
+ };
2549
+ autoTable(doc, tableConfig);
2550
+ doc.save(`${this.toolbarTitle || 'table-export'}.pdf`);
2551
+ }
2552
+ catch (error) {
2553
+ console.error('Error exporting to PDF:', error);
2554
+ }
2555
+ }
2556
+ /**
2557
+ * @description This method is used to split name of filter row header to get index.
2558
+ * @param value value to be splited for index.
2559
+ * @returns Will return index of column from value.
2560
+ */
2561
+ returnIndex(value) {
2562
+ return Number(value.split('_')[1]);
2563
+ }
2564
+ /**
2565
+ * @description This method is used to manage column filtering, expanded data for exporting.
2566
+ * @param ws work sheet
2567
+ * @returns custom generated worksheet to be used in export.
2568
+ */
2569
+ writeSheetData(ws) {
2570
+ let displayedColumns = this.getDisplayedColumns();
2571
+ var nMerges = this.getMergeIndex(ws['!merges'] || []);
2572
+ var merges = ws['!merges'] || [];
2573
+ let data = {
2574
+ '!cols': [],
2575
+ '!rows': [],
2576
+ '!merges': nMerges,
2577
+ };
2578
+ var range = XLSX.utils.decode_range(ws['!ref'] || '');
2579
+ let extracolumns = ['popup', 'delete', 'select', 'edit'];
2580
+ let keys = Object.keys(ws);
2581
+ let nKey = 'A';
2582
+ keys.forEach((key, i) => {
2583
+ if (ws[key]?.v && typeof ws[key]?.v === 'string') {
2584
+ if (!extracolumns.includes(ws[key].v.toLowerCase()) &&
2585
+ displayedColumns.includes(ws[key].v.toLowerCase())) {
2586
+ let lastRowIndex = range?.e?.r;
2587
+ data[key] = ws[key];
2588
+ let chr = key.charAt(0);
2589
+ for (let j = 2; j <= lastRowIndex; j++) {
2590
+ if (ws[chr + (j + 1)] !== undefined &&
2591
+ (typeof ws[chr + (j + 1)].v === 'string' ||
2592
+ typeof ws[chr + (j + 1)].v === 'number')) {
2593
+ data[nKey + j] = ws[chr + (j + 1)];
2594
+ }
2595
+ }
2596
+ nKey = String.fromCharCode(nKey.charCodeAt(0) + 1);
2597
+ }
2598
+ }
2599
+ });
2600
+ if (this.rowSelection) {
2601
+ let chr = 'A';
2602
+ for (let i = 1; i < range.e.c + 1; i++) {
2603
+ data[chr + 1] = data[String.fromCharCode(chr.charCodeAt(0) + 1) + 1];
2604
+ chr = String.fromCharCode(chr.charCodeAt(0) + 1);
2605
+ if (i == range.e.c) {
2606
+ data[chr + 1] = undefined;
2607
+ }
2608
+ }
2609
+ }
2610
+ if (this.rowSelection && this.expandRows) {
2611
+ merges.forEach((merge) => {
2612
+ data['A' + merge.s.r] = ws['A' + (merge.s.r + 1)];
2613
+ });
2614
+ }
2615
+ range.e.r--;
2616
+ let nRef = XLSX.utils.encode_range(range);
2617
+ data['!ref'] = nRef;
2618
+ data['!fullref'] = nRef;
2619
+ return data;
2620
+ }
2621
+ getMergeIndex(merges) {
2622
+ var arr = [];
2623
+ merges.forEach((element) => {
2624
+ arr.push({
2625
+ e: {
2626
+ r: element.e.r == 0 ? element.e.r : element.e.r - 1,
2627
+ c: element.e.c,
2628
+ },
2629
+ s: {
2630
+ r: element.s.r == 0 ? element.s.r : element.s.r - 1,
2631
+ c: element.s.c,
2632
+ },
2633
+ });
2634
+ });
2635
+ return arr;
2636
+ }
2637
+ 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 }); }
2638
+ 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-icon-button color=\"primary\"\n (click)=\"printTable()\" matTooltip=\"Print Table\">\n <mat-icon>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: [
2639
+ trigger('detailExpand', [
2640
+ state('collapsed', style({ height: '0px', minHeight: '0' })),
2641
+ state('expanded', style({ height: '*' })),
2642
+ transition('expanded <=> collapsed', animate('300ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
2643
+ ]),
2644
+ ], encapsulation: i0.ViewEncapsulation.None }); }
2645
+ }
2646
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.5", ngImport: i0, type: MatTableExtComponent, decorators: [{
2647
+ type: Component,
2648
+ args: [{ selector: 'mat-table-ext', encapsulation: ViewEncapsulation.None, standalone: true, imports: [
2649
+ CommonModule,
2650
+ FormsModule,
2651
+ ReactiveFormsModule,
2652
+ MatTableModule,
2653
+ MatFormFieldModule,
2654
+ MatInputModule,
2655
+ MatSelectModule,
2656
+ MatCheckboxModule,
2657
+ MatIconModule,
2658
+ MatPaginatorModule,
2659
+ MatSortModule,
2660
+ MatMenuModule,
2661
+ MatButtonModule,
2662
+ MatTooltipModule,
2663
+ MatToolbarModule,
2664
+ MatProgressBarModule,
2665
+ MatDatepickerModule,
2666
+ MatNativeDateModule,
2667
+ DragDropModule,
2668
+ ColumnPinningComponent,
2669
+ FilterColumnsComponentComponent,
2670
+ ResizeColumnDirective
2671
+ ], animations: [
2672
+ trigger('detailExpand', [
2673
+ state('collapsed', style({ height: '0px', minHeight: '0' })),
2674
+ state('expanded', style({ height: '*' })),
2675
+ transition('expanded <=> collapsed', animate('300ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
2676
+ ]),
2677
+ ], 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-icon-button color=\"primary\"\n (click)=\"printTable()\" matTooltip=\"Print Table\">\n <mat-icon>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"] }]
2678
+ }], ctorParameters: () => [{ type: i1$1.MatDialog }, { type: MatTableExtService }, { type: i3.FormBuilder }, { type: i4.DomSanitizer }, { type: i5$1.MatIconRegistry }, { type: i0.ChangeDetectorRef }], propDecorators: { menuTrigger: [{
2679
+ type: ViewChild,
2680
+ args: [MatMenuTrigger]
2681
+ }], columnMenuTrigger: [{
2682
+ type: ViewChild,
2683
+ args: ['columnMenuTrigger']
2684
+ }], paginator: [{
2685
+ type: ViewChild,
2686
+ args: [MatPaginator]
2687
+ }], sort: [{
2688
+ type: ViewChild,
2689
+ args: [MatSort]
2690
+ }], matTableRef: [{
2691
+ type: ViewChild,
2692
+ args: ['matTable', { read: ElementRef }]
2693
+ }], table: [{
2694
+ type: ViewChild,
2695
+ args: ['MyTable']
2696
+ }], tableElement: [{
2697
+ type: ViewChild,
2698
+ args: ['MyTable', { read: ElementRef }]
2699
+ }], dataSource: [{
2700
+ type: Input
2701
+ }], columns: [{
2702
+ type: Input
2703
+ }], columnResizable: [{
2704
+ type: Input
2705
+ }], stripedRows: [{
2706
+ type: Input
2707
+ }], rowHover: [{
2708
+ type: Input
2709
+ }], inlineRowEditing: [{
2710
+ type: Input
2711
+ }], inCellEditing: [{
2712
+ type: Input
2713
+ }], cellPopupEditing: [{
2714
+ type: Input
2715
+ }], popupRowEditing: [{
2716
+ type: Input
2717
+ }], enableDelete: [{
2718
+ type: Input
2719
+ }], rowSelection: [{
2720
+ type: Input
2721
+ }], multiRowSelection: [{
2722
+ type: Input
2723
+ }], stickyFooter: [{
2724
+ type: Input
2725
+ }], stickyHeader: [{
2726
+ type: Input
2727
+ }], showFooterRow: [{
2728
+ type: Input
2729
+ }], columnFilter: [{
2730
+ type: Input
2731
+ }], loadingIndicator: [{
2732
+ type: Input
2733
+ }], sorting: [{
2734
+ type: Input
2735
+ }], showToolbar: [{
2736
+ type: Input
2737
+ }], toolbarTitle: [{
2738
+ type: Input
2739
+ }], tableHeight: [{
2740
+ type: Input
2741
+ }], toolbarHeight: [{
2742
+ type: Input
2743
+ }], tableWidth: [{
2744
+ type: Input
2745
+ }], scrollbarH: [{
2746
+ type: Input
2747
+ }], toolbarTemplate: [{
2748
+ type: Input
2749
+ }], columnHidable: [{
2750
+ type: Input
2751
+ }], columnPinnable: [{
2752
+ type: Input
2753
+ }], globalSearch: [{
2754
+ type: Input
2755
+ }], expandRows: [{
2756
+ type: Input
2757
+ }], dndColumns: [{
2758
+ type: Input
2759
+ }], showPaginator: [{
2760
+ type: Input
2761
+ }], showFirstLastButtons: [{
2762
+ type: Input
2763
+ }], exportButtonEnable: [{
2764
+ type: Input
2765
+ }], printButtonEnable: [{
2766
+ type: Input
2767
+ }], pageSizeOptions: [{
2768
+ type: Input
2769
+ }], toolbarTemplateRef: [{
2770
+ type: Input
2771
+ }], headerTemplateRef: [{
2772
+ type: Input
2773
+ }], cellTemplateRef: [{
2774
+ type: Input
2775
+ }], expansionTemplateRef: [{
2776
+ type: Input
2777
+ }], popupEditingTemplateRef: [{
2778
+ type: Input
2779
+ }], inlineEditingTemplateRef: [{
2780
+ type: Input
2781
+ }], cellEditingTemplateRef: [{
2782
+ type: Input
2783
+ }], cellPopupEditingTemplateRef: [{
2784
+ type: Input
2785
+ }], cellTemplateRefMap: [{
2786
+ type: Input
2787
+ }], tableClassName: [{
2788
+ type: Input
2789
+ }], columnGroups: [{
2790
+ type: Input
2791
+ }], hiddenRowIndices: [{
2792
+ type: Input
2793
+ }], enableRowHiding: [{
2794
+ type: Input
2795
+ }], enableRowPinning: [{
2796
+ type: Input
2797
+ }], topPinnedMaxHeight: [{
2798
+ type: Input
2799
+ }], bottomPinnedMaxHeight: [{
2800
+ type: Input
2801
+ }], rowPinningFn: [{
2802
+ type: Input
2803
+ }], rowHidingFilterFn: [{
2804
+ type: Input
2805
+ }], pdfOrientation: [{
2806
+ type: Input
2807
+ }], inlineChange: [{
2808
+ type: Output
2809
+ }], cellChange: [{
2810
+ type: Output
2811
+ }], popupChange: [{
2812
+ type: Output
2813
+ }], rowDeleted: [{
2814
+ type: Output
2815
+ }], scroll: [{
2816
+ type: Output
2817
+ }], selectionChanged: [{
2818
+ type: Output
2819
+ }], expansionChange: [{
2820
+ type: Output
2821
+ }], rowPinningChange: [{
2822
+ type: Output
2823
+ }] } });
2824
+
2825
+ class MatTableExtModule {
2826
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.5", ngImport: i0, type: MatTableExtModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
2827
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.5", ngImport: i0, type: MatTableExtModule, imports: [CommonModule, i1$2.TranslateModule, MatTableModule,
2828
+ FormsModule,
2829
+ ReactiveFormsModule,
2830
+ MatNativeDateModule,
2831
+ A11yModule,
2832
+ CdkAccordionModule,
2833
+ ClipboardModule,
2834
+ CdkStepperModule,
2835
+ CdkTableModule,
2836
+ CdkTreeModule,
2837
+ DragDropModule,
2838
+ MatAutocompleteModule,
2839
+ MatBadgeModule,
2840
+ MatBottomSheetModule,
2841
+ MatButtonModule,
2842
+ MatButtonToggleModule,
2843
+ MatCardModule,
2844
+ MatCheckboxModule,
2845
+ MatChipsModule,
2846
+ MatStepperModule,
2847
+ MatDatepickerModule,
2848
+ MatDialogModule,
2849
+ MatDividerModule,
2850
+ MatExpansionModule,
2851
+ MatGridListModule,
2852
+ MatIconModule,
2853
+ MatInputModule,
2854
+ MatListModule,
2855
+ MatMenuModule,
2856
+ MatNativeDateModule,
2857
+ MatPaginatorModule,
2858
+ MatProgressBarModule,
2859
+ MatProgressSpinnerModule,
2860
+ MatRadioModule,
2861
+ MatRippleModule,
2862
+ MatSelectModule,
2863
+ MatSidenavModule,
2864
+ MatSliderModule,
2865
+ MatSlideToggleModule,
2866
+ MatSnackBarModule,
2867
+ MatSortModule,
2868
+ MatTabsModule,
2869
+ MatToolbarModule,
2870
+ MatTooltipModule,
2871
+ MatTreeModule,
2872
+ PortalModule,
2873
+ ScrollingModule,
2874
+ MatFormFieldModule,
2875
+ MatTableExtComponent,
2876
+ ResizeColumnDirective,
2877
+ ColumnPinningComponent,
2878
+ EditingComponent,
2879
+ FilterColumnsComponentComponent], exports: [MatTableExtComponent,
2880
+ ResizeColumnDirective,
2881
+ ColumnPinningComponent,
2882
+ EditingComponent,
2883
+ FilterColumnsComponentComponent] }); }
2884
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.5", ngImport: i0, type: MatTableExtModule, imports: [CommonModule,
2885
+ TranslateModule.forChild(),
2886
+ MatTableModule,
2887
+ FormsModule,
2888
+ ReactiveFormsModule,
2889
+ MatNativeDateModule,
2890
+ A11yModule,
2891
+ CdkAccordionModule,
2892
+ ClipboardModule,
2893
+ CdkStepperModule,
2894
+ CdkTableModule,
2895
+ CdkTreeModule,
2896
+ DragDropModule,
2897
+ MatAutocompleteModule,
2898
+ MatBadgeModule,
2899
+ MatBottomSheetModule,
2900
+ MatButtonModule,
2901
+ MatButtonToggleModule,
2902
+ MatCardModule,
2903
+ MatCheckboxModule,
2904
+ MatChipsModule,
2905
+ MatStepperModule,
2906
+ MatDatepickerModule,
2907
+ MatDialogModule,
2908
+ MatDividerModule,
2909
+ MatExpansionModule,
2910
+ MatGridListModule,
2911
+ MatIconModule,
2912
+ MatInputModule,
2913
+ MatListModule,
2914
+ MatMenuModule,
2915
+ MatNativeDateModule,
2916
+ MatPaginatorModule,
2917
+ MatProgressBarModule,
2918
+ MatProgressSpinnerModule,
2919
+ MatRadioModule,
2920
+ MatRippleModule,
2921
+ MatSelectModule,
2922
+ MatSidenavModule,
2923
+ MatSliderModule,
2924
+ MatSlideToggleModule,
2925
+ MatSnackBarModule,
2926
+ MatSortModule,
2927
+ MatTabsModule,
2928
+ MatToolbarModule,
2929
+ MatTooltipModule,
2930
+ MatTreeModule,
2931
+ PortalModule,
2932
+ ScrollingModule,
2933
+ MatFormFieldModule,
2934
+ MatTableExtComponent,
2935
+ ColumnPinningComponent,
2936
+ EditingComponent,
2937
+ FilterColumnsComponentComponent] }); }
2938
+ }
2939
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.5", ngImport: i0, type: MatTableExtModule, decorators: [{
2940
+ type: NgModule,
2941
+ args: [{
2942
+ declarations: [],
2943
+ imports: [
2944
+ CommonModule,
2945
+ TranslateModule.forChild(),
2946
+ MatTableModule,
2947
+ FormsModule,
2948
+ ReactiveFormsModule,
2949
+ MatNativeDateModule,
2950
+ A11yModule,
2951
+ CdkAccordionModule,
2952
+ ClipboardModule,
2953
+ CdkStepperModule,
2954
+ CdkTableModule,
2955
+ CdkTreeModule,
2956
+ DragDropModule,
2957
+ MatAutocompleteModule,
2958
+ MatBadgeModule,
2959
+ MatBottomSheetModule,
2960
+ MatButtonModule,
2961
+ MatButtonToggleModule,
2962
+ MatCardModule,
2963
+ MatCheckboxModule,
2964
+ MatChipsModule,
2965
+ MatStepperModule,
2966
+ MatDatepickerModule,
2967
+ MatDialogModule,
2968
+ MatDividerModule,
2969
+ MatExpansionModule,
2970
+ MatGridListModule,
2971
+ MatIconModule,
2972
+ MatInputModule,
2973
+ MatListModule,
2974
+ MatMenuModule,
2975
+ MatNativeDateModule,
2976
+ MatPaginatorModule,
2977
+ MatProgressBarModule,
2978
+ MatProgressSpinnerModule,
2979
+ MatRadioModule,
2980
+ MatRippleModule,
2981
+ MatSelectModule,
2982
+ MatSidenavModule,
2983
+ MatSliderModule,
2984
+ MatSlideToggleModule,
2985
+ MatSnackBarModule,
2986
+ MatSortModule,
2987
+ MatTabsModule,
2988
+ MatToolbarModule,
2989
+ MatTooltipModule,
2990
+ MatTreeModule,
2991
+ PortalModule,
2992
+ ScrollingModule,
2993
+ MatFormFieldModule,
2994
+ MatTableExtComponent,
2995
+ ResizeColumnDirective,
2996
+ ColumnPinningComponent,
2997
+ EditingComponent,
2998
+ FilterColumnsComponentComponent,
2999
+ ],
3000
+ exports: [
3001
+ MatTableExtComponent,
3002
+ ResizeColumnDirective,
3003
+ ColumnPinningComponent,
3004
+ EditingComponent,
3005
+ FilterColumnsComponentComponent,
3006
+ ],
3007
+ }]
3008
+ }] });
3009
+
3010
+ /*
3011
+ * Public API Surface of mat-table-ext
3012
+ */
3013
+
3014
+ /**
3015
+ * Generated bundle index. Do not edit.
3016
+ */
3017
+
3018
+ export { ColumnPinningComponent, EditingComponent, FilterColumnsComponentComponent, MatTableExtComponent, MatTableExtModule, MatTableExtService, ResizeColumnDirective };
3019
+ //# sourceMappingURL=mat-table-ext-test1.mjs.map