@wavemaker/app-ng-runtime 11.14.1-1.6289 → 11.14.1-10.6348
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/base/bundles/index.umd.js +86 -17
- package/components/base/esm2022/pipes/custom-pipes.mjs +10 -10
- package/components/base/esm2022/utils/widget-utils.mjs +3 -3
- package/components/base/esm2022/widgets/common/base/base.component.mjs +67 -7
- package/components/base/esm2022/widgets/common/lazy-load/lazy-load.directive.mjs +7 -3
- package/components/base/esm2022/widgets/framework/property-change-handler.mjs +7 -2
- package/components/base/fesm2022/index.mjs +87 -18
- package/components/base/fesm2022/index.mjs.map +1 -1
- package/components/base/pipes/custom-pipes.d.ts +5 -5
- package/components/basic/label/bundles/index.umd.js +9 -1
- package/components/basic/label/esm2022/label.directive.mjs +10 -2
- package/components/basic/label/fesm2022/index.mjs +9 -1
- package/components/basic/label/fesm2022/index.mjs.map +1 -1
- package/components/data/pagination/bundles/index.umd.js +4 -0
- package/components/data/pagination/esm2022/pagination.component.mjs +5 -1
- package/components/data/pagination/fesm2022/index.mjs +4 -0
- package/components/data/pagination/fesm2022/index.mjs.map +1 -1
- package/components/data/table/bundles/index.umd.js +371 -15
- package/components/data/table/esm2022/table-action/table-action.directive.mjs +8 -1
- package/components/data/table/esm2022/table-column/table-column.directive.mjs +107 -3
- package/components/data/table/esm2022/table-column-group/table-column-group.directive.mjs +9 -1
- package/components/data/table/esm2022/table-cud.directive.mjs +8 -2
- package/components/data/table/esm2022/table-filter.directive.mjs +12 -2
- package/components/data/table/esm2022/table-row/table-row.directive.mjs +8 -1
- package/components/data/table/esm2022/table-row-action/table-row-action.directive.mjs +8 -1
- package/components/data/table/esm2022/table.component.mjs +219 -12
- package/components/data/table/fesm2022/index.mjs +371 -15
- package/components/data/table/fesm2022/index.mjs.map +1 -1
- package/components/data/table/table-action/table-action.directive.d.ts +3 -2
- package/components/data/table/table-column/table-column.directive.d.ts +3 -2
- package/components/data/table/table-column-group/table-column-group.directive.d.ts +3 -2
- package/components/data/table/table-cud.directive.d.ts +3 -1
- package/components/data/table/table-filter.directive.d.ts +3 -1
- package/components/data/table/table-row/table-row.directive.d.ts +3 -2
- package/components/data/table/table-row-action/table-row-action.directive.d.ts +3 -2
- package/components/data/table/table.component.d.ts +6 -2
- package/components/navigation/menu/bundles/index.umd.js +5 -0
- package/components/navigation/menu/esm2022/menu.component.mjs +6 -1
- package/components/navigation/menu/fesm2022/index.mjs +5 -0
- package/components/navigation/menu/fesm2022/index.mjs.map +1 -1
- package/components/navigation/popover/bundles/index.umd.js +6 -6
- package/components/navigation/popover/esm2022/popover.component.mjs +4 -4
- package/components/navigation/popover/fesm2022/index.mjs +3 -3
- package/components/navigation/popover/fesm2022/index.mjs.map +1 -1
- package/components/navigation/popover/popover.component.d.ts +6 -0
- package/core/bundles/index.umd.js +411 -82
- package/core/esm2022/public_api.mjs +3 -3
- package/core/esm2022/utils/utils.mjs +6 -2
- package/core/esm2022/utils/watcher.mjs +402 -81
- package/core/fesm2022/index.mjs +410 -84
- package/core/fesm2022/index.mjs.map +1 -1
- package/core/public_api.d.ts +2 -2
- package/core/utils/utils.d.ts +1 -0
- package/core/utils/watcher.d.ts +28 -5
- package/npm-shrinkwrap.json +2 -2
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/runtime/base/bundles/index.umd.js +22 -2
- package/runtime/base/esm2022/components/app-component/app.component.mjs +4 -2
- package/runtime/base/esm2022/components/base-page.component.mjs +6 -2
- package/runtime/base/esm2022/components/base-partial.component.mjs +7 -2
- package/runtime/base/esm2022/components/base-prefab.component.mjs +7 -2
- package/runtime/base/esm2022/components/base-spa-page.component.mjs +6 -2
- package/runtime/base/esm2022/services/pipe-provider.service.mjs +4 -4
- package/runtime/base/fesm2022/index.mjs +23 -3
- package/runtime/base/fesm2022/index.mjs.map +1 -1
- package/scripts/datatable/datatable.js +101 -15
|
@@ -176,8 +176,15 @@ class TableComponent extends StylableComponent {
|
|
|
176
176
|
this.setDataGridOption('colDefs', getClonedObject(this.fieldDefs));
|
|
177
177
|
}
|
|
178
178
|
// If data and colDefs are present, call on before data render event
|
|
179
|
+
// Note: Errors in beforedatarender should not prevent table rendering
|
|
179
180
|
if (!this.isdynamictable && !isEmpty(newValue) && gridOptions.colDefs.length) {
|
|
180
|
-
|
|
181
|
+
try {
|
|
182
|
+
this.invokeEventCallback('beforedatarender', { $data: this._gridData, $columns: this.columns, data: this._gridData, columns: this.columns });
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
// Log error but continue with rendering - beforedatarender errors should not block table rendering
|
|
186
|
+
console.warn('Error in beforedatarender event callback, continuing with table rendering:', error);
|
|
187
|
+
}
|
|
181
188
|
}
|
|
182
189
|
this.setDataGridOption('data', getClonedObject(this._gridData));
|
|
183
190
|
}
|
|
@@ -570,7 +577,7 @@ class TableComponent extends StylableComponent {
|
|
|
570
577
|
this.prevData = getClonedObject(row);
|
|
571
578
|
},
|
|
572
579
|
afterRowUpdate: (row, e, callBack, options) => {
|
|
573
|
-
this.updateRecord(extend({}, options, { row, 'prevData': this.prevData, 'event': e, 'callBack': callBack }));
|
|
580
|
+
this.updateRecord(extend({}, options, { row, 'prevData': options.rowindex ? options.rowindex : this.prevData, 'event': e, 'callBack': callBack }));
|
|
574
581
|
},
|
|
575
582
|
onBeforeRowUpdate: (row, e, options) => {
|
|
576
583
|
return this.invokeEventCallback('beforerowupdate', { $event: e, $data: row, row, options: options });
|
|
@@ -1224,6 +1231,10 @@ class TableComponent extends StylableComponent {
|
|
|
1224
1231
|
return this.actualPageSize || 5;
|
|
1225
1232
|
}
|
|
1226
1233
|
watchVariableDataSet(newVal) {
|
|
1234
|
+
// Guard against component destruction
|
|
1235
|
+
if (this.isDestroyed) {
|
|
1236
|
+
return;
|
|
1237
|
+
}
|
|
1227
1238
|
let result;
|
|
1228
1239
|
// Check for Variable filters if applied
|
|
1229
1240
|
if (this.gridOptions.isNavTypeScrollOrOndemand()) {
|
|
@@ -1281,6 +1292,12 @@ class TableComponent extends StylableComponent {
|
|
|
1281
1292
|
}
|
|
1282
1293
|
/*Return if data is invalid.*/
|
|
1283
1294
|
if (!this.isDataValid()) {
|
|
1295
|
+
// If data is invalid and variableInflight is still true, clear loading state
|
|
1296
|
+
// This prevents tables from getting stuck in loading when data is invalid
|
|
1297
|
+
if (this.variableInflight) {
|
|
1298
|
+
this.variableInflight = false;
|
|
1299
|
+
this.setGridData([]);
|
|
1300
|
+
}
|
|
1284
1301
|
return;
|
|
1285
1302
|
}
|
|
1286
1303
|
// If value is empty or in studio mode, dont enable the navigation
|
|
@@ -1308,7 +1325,13 @@ class TableComponent extends StylableComponent {
|
|
|
1308
1325
|
// @ts-ignore
|
|
1309
1326
|
if (!isObject(newVal) || newVal === '' || (newVal && newVal.dataValue === '')) {
|
|
1310
1327
|
if (!this.variableInflight) {
|
|
1311
|
-
// If variable has finished loading and resultSet is empty,
|
|
1328
|
+
// If variable has finished loading and resultSet is empty, render empty data
|
|
1329
|
+
this.setGridData([]);
|
|
1330
|
+
}
|
|
1331
|
+
else {
|
|
1332
|
+
// If variableInflight is still true but we have invalid/empty data, clear loading state
|
|
1333
|
+
// This handles cases where data never arrives or is invalid
|
|
1334
|
+
this.variableInflight = false;
|
|
1312
1335
|
this.setGridData([]);
|
|
1313
1336
|
}
|
|
1314
1337
|
return;
|
|
@@ -1318,13 +1341,143 @@ class TableComponent extends StylableComponent {
|
|
|
1318
1341
|
}
|
|
1319
1342
|
}
|
|
1320
1343
|
ngOnDestroy() {
|
|
1344
|
+
// MEMORY LEAK FIX: Remove document click listener
|
|
1321
1345
|
document.removeEventListener('click', this.documentClickBind);
|
|
1346
|
+
// MEMORY LEAK FIX: Unsubscribe from navigator watches
|
|
1322
1347
|
if (this.navigatorResultWatch) {
|
|
1323
1348
|
this.navigatorResultWatch.unsubscribe();
|
|
1349
|
+
this.navigatorResultWatch = null;
|
|
1324
1350
|
}
|
|
1325
1351
|
if (this.navigatorMaxResultWatch) {
|
|
1326
1352
|
this.navigatorMaxResultWatch.unsubscribe();
|
|
1353
|
+
this.navigatorMaxResultWatch = null;
|
|
1354
|
+
}
|
|
1355
|
+
// MEMORY LEAK FIX: Clear all ViewContainerRef embedded views
|
|
1356
|
+
// These hold references to row data, custom expressions, and inline widgets
|
|
1357
|
+
if (this.customExprViewRef) {
|
|
1358
|
+
this.customExprViewRef.clear();
|
|
1359
|
+
}
|
|
1360
|
+
if (this.rowActionsViewRef) {
|
|
1361
|
+
this.rowActionsViewRef.clear();
|
|
1362
|
+
}
|
|
1363
|
+
if (this.filterViewRef) {
|
|
1364
|
+
this.filterViewRef.clear();
|
|
1365
|
+
}
|
|
1366
|
+
if (this.inlineEditViewRef) {
|
|
1367
|
+
this.inlineEditViewRef.clear();
|
|
1368
|
+
}
|
|
1369
|
+
if (this.inlineEditNewViewRef) {
|
|
1370
|
+
this.inlineEditNewViewRef.clear();
|
|
1371
|
+
}
|
|
1372
|
+
if (this.rowDetailViewRef) {
|
|
1373
|
+
this.rowDetailViewRef.clear();
|
|
1374
|
+
}
|
|
1375
|
+
if (this.rowExpansionActionViewRef) {
|
|
1376
|
+
this.rowExpansionActionViewRef.clear();
|
|
1377
|
+
}
|
|
1378
|
+
if (this.dynamicTableRef) {
|
|
1379
|
+
this.dynamicTableRef.clear();
|
|
1380
|
+
}
|
|
1381
|
+
// MEMORY LEAK FIX: Clear compiled template caches
|
|
1382
|
+
this.rowActionsCompiledTl = {};
|
|
1383
|
+
this.rowFilterCompliedTl = {};
|
|
1384
|
+
this.inlineCompliedTl = {};
|
|
1385
|
+
this.inlineNewCompliedTl = {};
|
|
1386
|
+
this.customExprCompiledTl = {};
|
|
1387
|
+
this.customExprCompiledSummaryTl = {};
|
|
1388
|
+
this.rowDefInstances = {};
|
|
1389
|
+
this.rowDefMap = {};
|
|
1390
|
+
this.rowExpansionActionTl = {};
|
|
1391
|
+
// MEMORY LEAK FIX: Clear dynamic context
|
|
1392
|
+
if (this._dynamicContext) {
|
|
1393
|
+
Object.keys(this._dynamicContext).forEach(key => {
|
|
1394
|
+
delete this._dynamicContext[key];
|
|
1395
|
+
});
|
|
1396
|
+
this._dynamicContext = null;
|
|
1397
|
+
}
|
|
1398
|
+
// MEMORY LEAK FIX: Clear data arrays
|
|
1399
|
+
this._gridData = [];
|
|
1400
|
+
this.items = [];
|
|
1401
|
+
this.selectedItems = [];
|
|
1402
|
+
this.fieldDefs = [];
|
|
1403
|
+
this.fullFieldDefs = [];
|
|
1404
|
+
this.gridData = [];
|
|
1405
|
+
this.__fullData = null;
|
|
1406
|
+
// MEMORY LEAK FIX: Destroy jQuery datatable widget before clearing gridOptions
|
|
1407
|
+
if (this.datagridElement && this.datagridElement.datatable) {
|
|
1408
|
+
try {
|
|
1409
|
+
this.datagridElement.datatable('destroy');
|
|
1410
|
+
}
|
|
1411
|
+
catch (e) {
|
|
1412
|
+
// Ignore errors during destroy
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
// MEMORY LEAK FIX: Clear gridOptions to release all function closures and data
|
|
1416
|
+
// gridOptions holds many closures that capture 'this' and prevent GC
|
|
1417
|
+
if (this.gridOptions) {
|
|
1418
|
+
// Clear data array
|
|
1419
|
+
if (this.gridOptions.data) {
|
|
1420
|
+
this.gridOptions.data = [];
|
|
1421
|
+
}
|
|
1422
|
+
// Clear column definitions
|
|
1423
|
+
if (this.gridOptions.colDefs) {
|
|
1424
|
+
this.gridOptions.colDefs = [];
|
|
1425
|
+
}
|
|
1426
|
+
// Clear row actions
|
|
1427
|
+
if (this.gridOptions.rowActions) {
|
|
1428
|
+
this.gridOptions.rowActions = [];
|
|
1429
|
+
}
|
|
1430
|
+
// Clear header config
|
|
1431
|
+
if (this.gridOptions.headerConfig) {
|
|
1432
|
+
this.gridOptions.headerConfig = [];
|
|
1433
|
+
}
|
|
1434
|
+
// Nullify all function references to break closures
|
|
1435
|
+
Object.keys(this.gridOptions).forEach(key => {
|
|
1436
|
+
if (typeof this.gridOptions[key] === 'function') {
|
|
1437
|
+
this.gridOptions[key] = null;
|
|
1438
|
+
}
|
|
1439
|
+
});
|
|
1327
1440
|
}
|
|
1441
|
+
// MEMORY LEAK FIX: Clear other data structures
|
|
1442
|
+
this.columns = {};
|
|
1443
|
+
this.formfields = {};
|
|
1444
|
+
this.rowFilter = {};
|
|
1445
|
+
this.actions = [];
|
|
1446
|
+
this._actions = { header: [], footer: [] };
|
|
1447
|
+
this.exportOptions = [];
|
|
1448
|
+
this.headerConfig = [];
|
|
1449
|
+
this.rowActions = [];
|
|
1450
|
+
// MEMORY LEAK FIX: Clear all @ContentChildren QueryLists holding template references
|
|
1451
|
+
// These QueryLists hold TemplateRef instances that create circular references to the parent LView
|
|
1452
|
+
if (this.rowActionTmpl) {
|
|
1453
|
+
this.rowActionTmpl.reset([]);
|
|
1454
|
+
}
|
|
1455
|
+
if (this.filterTmpl) {
|
|
1456
|
+
this.filterTmpl.reset([]);
|
|
1457
|
+
}
|
|
1458
|
+
if (this.inlineWidgetTmpl) {
|
|
1459
|
+
this.inlineWidgetTmpl.reset([]);
|
|
1460
|
+
}
|
|
1461
|
+
if (this.inlineWidgetNewTmpl) {
|
|
1462
|
+
this.inlineWidgetNewTmpl.reset([]);
|
|
1463
|
+
}
|
|
1464
|
+
if (this.customExprTmpl) {
|
|
1465
|
+
this.customExprTmpl.reset([]);
|
|
1466
|
+
}
|
|
1467
|
+
if (this.rowExpansionActionTmpl) {
|
|
1468
|
+
this.rowExpansionActionTmpl.reset([]);
|
|
1469
|
+
}
|
|
1470
|
+
// MEMORY LEAK FIX: Clear @ContentChild template reference
|
|
1471
|
+
this.rowExpansionTmpl = null;
|
|
1472
|
+
// MEMORY LEAK FIX: Complete and clear subjects
|
|
1473
|
+
if (this.selectedItemChange) {
|
|
1474
|
+
this.selectedItemChange.complete();
|
|
1475
|
+
this.selectedItemChange = null;
|
|
1476
|
+
}
|
|
1477
|
+
// MEMORY LEAK FIX: Clear ViewChild references
|
|
1478
|
+
this.dataNavigator = null;
|
|
1479
|
+
this._tableElement = null;
|
|
1480
|
+
// console.log("table component destroyed");
|
|
1328
1481
|
super.ngOnDestroy();
|
|
1329
1482
|
}
|
|
1330
1483
|
addRowIndex(row) {
|
|
@@ -1395,6 +1548,9 @@ class TableComponent extends StylableComponent {
|
|
|
1395
1548
|
if (!key.endsWith('_filter') && ((key.endsWith('_new') && newRow) || (!key.endsWith('_new') && !newRow))) {
|
|
1396
1549
|
ctrls[key].setValue('');
|
|
1397
1550
|
this.resetFormControl(ctrls[key]);
|
|
1551
|
+
// MEMORY LEAK FIX: Clear validators to release references
|
|
1552
|
+
ctrls[key].clearValidators();
|
|
1553
|
+
ctrls[key].clearAsyncValidators();
|
|
1398
1554
|
}
|
|
1399
1555
|
});
|
|
1400
1556
|
}
|
|
@@ -1714,7 +1870,14 @@ class TableComponent extends StylableComponent {
|
|
|
1714
1870
|
defaultFieldDefs.forEach(col => {
|
|
1715
1871
|
this.columns[col.field] = col;
|
|
1716
1872
|
});
|
|
1717
|
-
|
|
1873
|
+
// Note: Errors in beforedatarender should not prevent table rendering
|
|
1874
|
+
try {
|
|
1875
|
+
this.invokeEventCallback('beforedatarender', { $data: data, $columns: this.columns, data: data, columns: this.columns });
|
|
1876
|
+
}
|
|
1877
|
+
catch (error) {
|
|
1878
|
+
// Log error but continue with rendering - beforedatarender errors should not block table rendering
|
|
1879
|
+
console.warn('Error in beforedatarender event callback, continuing with table rendering:', error);
|
|
1880
|
+
}
|
|
1718
1881
|
defaultFieldDefs = [];
|
|
1719
1882
|
// Apply the changes made by the user
|
|
1720
1883
|
forEach(this.columns, val => {
|
|
@@ -1753,23 +1916,30 @@ class TableComponent extends StylableComponent {
|
|
|
1753
1916
|
return sortExp || '';
|
|
1754
1917
|
}
|
|
1755
1918
|
onPropertyChange(key, nv, ov) {
|
|
1919
|
+
// Guard against property changes after component destruction
|
|
1920
|
+
if (this.isDestroyed) {
|
|
1921
|
+
return;
|
|
1922
|
+
}
|
|
1756
1923
|
let enableNewRow, widgetState;
|
|
1757
1924
|
switch (key) {
|
|
1758
1925
|
case 'datasource':
|
|
1759
1926
|
// Fix for [WMS-23653] when startUpdate is false (request on page load property is unchecked),
|
|
1760
1927
|
// then set status msg as "No data found"
|
|
1761
|
-
if (this.allowpagesizechange) {
|
|
1928
|
+
if (this.allowpagesizechange && this.datasource) {
|
|
1762
1929
|
this.datasource.maxResults = this.pagesize || this.datasource.maxResults;
|
|
1763
1930
|
}
|
|
1764
|
-
if (nv.startUpdate === false) {
|
|
1931
|
+
if (nv && nv.startUpdate === false) {
|
|
1765
1932
|
this.variableInflight = false;
|
|
1766
1933
|
this.callDataGridMethod('setStatus', 'nodata', this.nodatamessage);
|
|
1767
1934
|
}
|
|
1768
|
-
if (get(this.datasource, 'category') !== 'wm.Variable') {
|
|
1935
|
+
if (this.datasource && get(this.datasource, 'category') !== 'wm.Variable') {
|
|
1769
1936
|
this.headerselectall = false;
|
|
1770
1937
|
this.setDataGridOption("headerselectall", false);
|
|
1771
1938
|
}
|
|
1772
|
-
|
|
1939
|
+
// Process dataset when datasource is set, especially if dataset was previously skipped
|
|
1940
|
+
if (this.datasource && this.dataset !== undefined) {
|
|
1941
|
+
this.watchVariableDataSet(this.dataset);
|
|
1942
|
+
}
|
|
1773
1943
|
this.onDataSourceChange();
|
|
1774
1944
|
break;
|
|
1775
1945
|
case 'dataset':
|
|
@@ -1777,6 +1947,12 @@ class TableComponent extends StylableComponent {
|
|
|
1777
1947
|
this.gridOptions.setIsNextPageData(false);
|
|
1778
1948
|
}
|
|
1779
1949
|
if (this.binddatasource && !this.datasource) {
|
|
1950
|
+
// If datasource is not set yet, clear loading state and show no data
|
|
1951
|
+
// This prevents tables from being stuck in loading state
|
|
1952
|
+
if (this.variableInflight) {
|
|
1953
|
+
this.variableInflight = false;
|
|
1954
|
+
this.callDataGridMethod('setStatus', 'nodata', this.nodatamessage);
|
|
1955
|
+
}
|
|
1780
1956
|
return;
|
|
1781
1957
|
}
|
|
1782
1958
|
// if table is inside list then table dataset will be set as "item.XXX" and there is no datasource.
|
|
@@ -1880,9 +2056,11 @@ class TableComponent extends StylableComponent {
|
|
|
1880
2056
|
this.allowpagesizechange = nv;
|
|
1881
2057
|
break;
|
|
1882
2058
|
case 'pagesizeoptions':
|
|
1883
|
-
this.
|
|
1884
|
-
this.pagesizeoptions = nv;
|
|
1885
|
-
this.
|
|
2059
|
+
this.prevPagesizeoptions = this.sanitizeCommaSeparatedIntegers(ov);
|
|
2060
|
+
this.gridOptions.pagesizeoptions = this.sanitizeCommaSeparatedIntegers(nv);
|
|
2061
|
+
this.pagesizeoptions = this.sanitizeCommaSeparatedIntegers(nv);
|
|
2062
|
+
if (this.allowpagesizechange)
|
|
2063
|
+
this.setDefaultPageSize(nv);
|
|
1886
2064
|
break;
|
|
1887
2065
|
case 'multiselecttitle':
|
|
1888
2066
|
this.setDataGridOption('multiselecttitle', nv);
|
|
@@ -1926,12 +2104,41 @@ class TableComponent extends StylableComponent {
|
|
|
1926
2104
|
this.pagesize = nv;
|
|
1927
2105
|
}
|
|
1928
2106
|
this.updatedPageSize = nv;
|
|
2107
|
+
if (this.isPageSizeOptionsChanged()) {
|
|
2108
|
+
this.dataNavigator.defaultPageSizeOptions = this.pagesizeoptions?.split(',').map(Number).sort((a, b) => a - b) || [];
|
|
2109
|
+
this.dataNavigator.pageSizeOptions = [...this.dataNavigator.defaultPageSizeOptions];
|
|
2110
|
+
}
|
|
1929
2111
|
}
|
|
1930
2112
|
this.dataNavigator.options = {
|
|
1931
2113
|
maxResults: nv
|
|
1932
2114
|
};
|
|
1933
2115
|
this.dataNavigator.widget.maxResults = nv;
|
|
1934
2116
|
this.dataNavigator.maxResults = nv;
|
|
2117
|
+
if (this.datasource) {
|
|
2118
|
+
this.datasource.maxResults = this.pagesize || this.datasource.maxResults;
|
|
2119
|
+
}
|
|
2120
|
+
}
|
|
2121
|
+
isPageSizeOptionsChanged() {
|
|
2122
|
+
return !isEqual(this.prevPagesizeoptions, this.pagesizeoptions);
|
|
2123
|
+
}
|
|
2124
|
+
selectPageSize(pagesize) {
|
|
2125
|
+
if (!this.allowpagesizechange && !pagesize)
|
|
2126
|
+
return;
|
|
2127
|
+
if (pagesize < this.dataNavigator.pageSizeOptions[0] || pagesize > this.dataNavigator.pageSizeOptions[this.dataNavigator.pageSizeOptions.length - 1]
|
|
2128
|
+
|| !this.dataNavigator.pageSizeOptions.includes(Number(pagesize))) {
|
|
2129
|
+
pagesize = this.dataNavigator.pageSizeOptions[0];
|
|
2130
|
+
}
|
|
2131
|
+
this.dataNavigator.onPageSizeChange(undefined, pagesize);
|
|
2132
|
+
}
|
|
2133
|
+
sanitizeCommaSeparatedIntegers(input) {
|
|
2134
|
+
if (!input)
|
|
2135
|
+
return "";
|
|
2136
|
+
const uniqueNumbers = Array.from(new Set(input
|
|
2137
|
+
.split(",")
|
|
2138
|
+
.map(v => v.trim())
|
|
2139
|
+
.filter(v => /^-?\d+$/.test(v))
|
|
2140
|
+
.map(v => Math.abs(parseInt(v, 10)))));
|
|
2141
|
+
return uniqueNumbers.join(",");
|
|
1935
2142
|
}
|
|
1936
2143
|
onDataSourceChange() {
|
|
1937
2144
|
this.fieldDefs.forEach(col => {
|
|
@@ -2457,7 +2664,7 @@ class TableCUDDirective {
|
|
|
2457
2664
|
this.updateVariable(response, options.callBack);
|
|
2458
2665
|
}
|
|
2459
2666
|
else if (!this.table.datasource.execute(DataSource.Operation.IS_API_AWARE)) {
|
|
2460
|
-
this.table.initiateSelectItem('current', response, undefined,
|
|
2667
|
+
this.table.initiateSelectItem('current', response, undefined, this.table.datasource.category === 'wm.Variable', options.callBack);
|
|
2461
2668
|
}
|
|
2462
2669
|
triggerFn(options.success, response);
|
|
2463
2670
|
this.table.invokeEventCallback('rowupdate', { $event: options.event, $data: response, row: response });
|
|
@@ -2707,6 +2914,12 @@ class TableCUDDirective {
|
|
|
2707
2914
|
this.table.callDataGridMethod('cancelEdit', $row);
|
|
2708
2915
|
}
|
|
2709
2916
|
}
|
|
2917
|
+
ngOnDestroy() {
|
|
2918
|
+
// MEMORY LEAK FIX: Clear all references
|
|
2919
|
+
this.table = null;
|
|
2920
|
+
this.dialogService = null;
|
|
2921
|
+
this.app = null;
|
|
2922
|
+
}
|
|
2710
2923
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TableCUDDirective, deps: [{ token: TableComponent, self: true }, { token: i2.AbstractDialogService }, { token: i2.App }], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
2711
2924
|
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: TableCUDDirective, isStandalone: true, selector: "[wmTableCUD]", ngImport: i0 }); }
|
|
2712
2925
|
}
|
|
@@ -3019,6 +3232,12 @@ class TableFilterSortDirective {
|
|
|
3019
3232
|
// Function that checks if a given string is a valid date and returns the timestamp if it is, or NaN if it's not.
|
|
3020
3233
|
parseDateString(dateString) {
|
|
3021
3234
|
const timestamp = Date.parse(dateString);
|
|
3235
|
+
// handling case when string starts with string and end with number
|
|
3236
|
+
const trimmed = dateString.trim();
|
|
3237
|
+
const monthRegex = /\b(?:Jan(?:uary)?|Feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)?|May|Jun(?:e)?|Jul(?:y)?|Aug(?:ust)?|Sep(?:t(?:ember)?)?|Oct(?:ober)?|Nov(?:ember)?|Dec(?:ember)?)\b/i;
|
|
3238
|
+
if (/^[A-Za-z]+/.test(trimmed) && /\d+$/.test(trimmed) && !monthRegex.test(trimmed)) {
|
|
3239
|
+
return NaN;
|
|
3240
|
+
}
|
|
3022
3241
|
if (!isNaN(timestamp)) {
|
|
3023
3242
|
return timestamp;
|
|
3024
3243
|
}
|
|
@@ -3034,7 +3253,7 @@ class TableFilterSortDirective {
|
|
|
3034
3253
|
const fieldValue = get(find(data, sortObj.field), sortObj.field);
|
|
3035
3254
|
const isValidDateString = typeof fieldValue === 'string' ? this.parseDateString(fieldValue) : NaN;
|
|
3036
3255
|
if (!isNaN(isValidDateString)) { // if the field is a date string
|
|
3037
|
-
data = orderBy(data, [(item) => this.parseDateString(item
|
|
3256
|
+
data = orderBy(data, [(item) => this.parseDateString(get(item, sortObj.field))], [sortObj.direction]);
|
|
3038
3257
|
}
|
|
3039
3258
|
else if (sortObj.sortBy ? this.table.columns[sortObj.sortBy]?.caseinsensitive : this.table.columns[sortObj.field]?.caseinsensitive) {
|
|
3040
3259
|
//Fix for [WMS-27505]: Added case-insensitive sorting so that uppercase and lowercase letters are treated the same when sorting.
|
|
@@ -3396,6 +3615,10 @@ class TableFilterSortDirective {
|
|
|
3396
3615
|
condition: logicalOp
|
|
3397
3616
|
});
|
|
3398
3617
|
}
|
|
3618
|
+
ngOnDestroy() {
|
|
3619
|
+
// MEMORY LEAK FIX: Clear table reference
|
|
3620
|
+
this.table = null;
|
|
3621
|
+
}
|
|
3399
3622
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TableFilterSortDirective, deps: [{ token: TableComponent, self: true }], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
3400
3623
|
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: TableFilterSortDirective, isStandalone: true, selector: "[wmTableFilterSort]", ngImport: i0 }); }
|
|
3401
3624
|
}
|
|
@@ -3482,6 +3705,13 @@ class TableActionDirective extends BaseComponent {
|
|
|
3482
3705
|
this.buttonDef[key] = nv;
|
|
3483
3706
|
}
|
|
3484
3707
|
}
|
|
3708
|
+
ngOnDestroy() {
|
|
3709
|
+
// MEMORY LEAK FIX: Clear table and buttonDef references
|
|
3710
|
+
this.table = null;
|
|
3711
|
+
this.buttonDef = null;
|
|
3712
|
+
// Call parent ngOnDestroy (BaseComponent has cleanup)
|
|
3713
|
+
super.ngOnDestroy();
|
|
3714
|
+
}
|
|
3485
3715
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TableActionDirective, deps: [{ token: i0.Injector }, { token: TableComponent, optional: true }, { token: 'EXPLICIT_CONTEXT', optional: true }], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
3486
3716
|
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: TableActionDirective, isStandalone: true, selector: "[wmTableAction]", providers: [
|
|
3487
3717
|
provideAsWidgetRef(TableActionDirective)
|
|
@@ -3646,6 +3876,14 @@ class TableColumnGroupDirective extends BaseComponent {
|
|
|
3646
3876
|
const fieldName = this.group && this.group.name;
|
|
3647
3877
|
setHeaderConfigForTable(this.table.headerConfig, this.config, fieldName, fieldName ? colIndex : headerIndex);
|
|
3648
3878
|
}
|
|
3879
|
+
ngOnDestroy() {
|
|
3880
|
+
// MEMORY LEAK FIX: Clear table, group, and config references
|
|
3881
|
+
this.table = null;
|
|
3882
|
+
this.group = null;
|
|
3883
|
+
this.config = null;
|
|
3884
|
+
// Call parent ngOnDestroy (BaseComponent has cleanup)
|
|
3885
|
+
super.ngOnDestroy();
|
|
3886
|
+
}
|
|
3649
3887
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TableColumnGroupDirective, deps: [{ token: i0.Injector }, { token: TableColumnGroupDirective, optional: true, skipSelf: true }, { token: TableComponent, optional: true }, { token: 'EXPLICIT_CONTEXT', optional: true }], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
3650
3888
|
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: TableColumnGroupDirective, isStandalone: true, selector: "[wmTableColumnGroup]", providers: [
|
|
3651
3889
|
provideAsWidgetRef(TableColumnGroupDirective)
|
|
@@ -3840,6 +4078,10 @@ class TableColumnDirective extends BaseComponent {
|
|
|
3840
4078
|
}
|
|
3841
4079
|
// Remove validators for the inline widget and set form to untouched
|
|
3842
4080
|
removeValidations() {
|
|
4081
|
+
// Guard against component destruction or table/ngform being null
|
|
4082
|
+
if (this.isDestroyed || !this.table || !this.table.ngform) {
|
|
4083
|
+
return;
|
|
4084
|
+
}
|
|
3843
4085
|
this.table.ngform.markAsUntouched();
|
|
3844
4086
|
const control = this.getFormControl();
|
|
3845
4087
|
if (!control) {
|
|
@@ -3851,6 +4093,10 @@ class TableColumnDirective extends BaseComponent {
|
|
|
3851
4093
|
}
|
|
3852
4094
|
// Apply default|sync|async|prop validators for QuickEdit new row form control
|
|
3853
4095
|
applyNewRowValidations() {
|
|
4096
|
+
// Guard against component destruction or table/ngform being null
|
|
4097
|
+
if (this.isDestroyed || !this.table || !this.table.ngform) {
|
|
4098
|
+
return;
|
|
4099
|
+
}
|
|
3854
4100
|
if (!this._checkNewEditableRowControl()) {
|
|
3855
4101
|
return;
|
|
3856
4102
|
}
|
|
@@ -3867,22 +4113,37 @@ class TableColumnDirective extends BaseComponent {
|
|
|
3867
4113
|
}
|
|
3868
4114
|
// Remove validators for the QuickEdit new row widget and set form to untouched
|
|
3869
4115
|
removeNewRowValidations() {
|
|
4116
|
+
// Guard against component destruction or table/ngform being null
|
|
4117
|
+
if (this.isDestroyed || !this.table || !this.table.ngform) {
|
|
4118
|
+
return;
|
|
4119
|
+
}
|
|
3870
4120
|
this.table.ngform.markAsUntouched();
|
|
3871
4121
|
if (!this._checkNewEditableRowControl()) {
|
|
3872
4122
|
return;
|
|
3873
4123
|
}
|
|
3874
4124
|
const control = this.getFormControl('_new');
|
|
4125
|
+
if (!control) {
|
|
4126
|
+
return;
|
|
4127
|
+
}
|
|
3875
4128
|
control.clearValidators();
|
|
3876
4129
|
control.clearAsyncValidators();
|
|
3877
4130
|
control.updateValueAndValidity();
|
|
3878
4131
|
}
|
|
3879
4132
|
addFormControl(suffix) {
|
|
4133
|
+
// Guard against component destruction or table/ngform being null
|
|
4134
|
+
if (this.isDestroyed || !this.table || !this.table.ngform) {
|
|
4135
|
+
return;
|
|
4136
|
+
}
|
|
3880
4137
|
const ctrlName = suffix ? (this.binding + suffix) : this.binding;
|
|
3881
4138
|
this.table.ngform.addControl(ctrlName, this.table.fb.control(''));
|
|
3882
4139
|
}
|
|
3883
4140
|
getFormControl(suffix) {
|
|
4141
|
+
// Guard against component destruction or table/ngform being null
|
|
4142
|
+
if (this.isDestroyed || !this.table || !this.table.ngform) {
|
|
4143
|
+
return null;
|
|
4144
|
+
}
|
|
3884
4145
|
const ctrlName = suffix ? (this.binding + suffix) : this.binding;
|
|
3885
|
-
return this.table.ngform.controls[ctrlName];
|
|
4146
|
+
return this.table.ngform.controls[ctrlName] || null;
|
|
3886
4147
|
}
|
|
3887
4148
|
_checkNewEditableRowControl() {
|
|
3888
4149
|
return this._isNewEditableRow && this.getFormControl('_new');
|
|
@@ -3956,12 +4217,16 @@ class TableColumnDirective extends BaseComponent {
|
|
|
3956
4217
|
}
|
|
3957
4218
|
// On field value change, apply cascading filter and set validation message
|
|
3958
4219
|
onValueChange(val, widget) {
|
|
4220
|
+
// Guard against component destruction or table being null
|
|
4221
|
+
if (this.isDestroyed || !this.table) {
|
|
4222
|
+
return;
|
|
4223
|
+
}
|
|
3959
4224
|
if (val !== null) {
|
|
3960
4225
|
applyFilterOnField(this.table.datasource, this.widget, this.table.fieldDefs, val, {
|
|
3961
4226
|
widget: 'edit-widget-type'
|
|
3962
4227
|
});
|
|
3963
4228
|
}
|
|
3964
|
-
if (this.table.ngform.touched) {
|
|
4229
|
+
if (this.table.ngform && this.table.ngform.touched) {
|
|
3965
4230
|
this.activeControlType = widget;
|
|
3966
4231
|
if (widget === 'inlineInstance') {
|
|
3967
4232
|
this.notifyChanges();
|
|
@@ -4252,6 +4517,83 @@ class TableColumnDirective extends BaseComponent {
|
|
|
4252
4517
|
this.table.redraw(true);
|
|
4253
4518
|
}
|
|
4254
4519
|
}
|
|
4520
|
+
ngOnDestroy() {
|
|
4521
|
+
// MEMORY LEAK FIX: Clear ContentChildren QueryLists
|
|
4522
|
+
if (this._filterInstances) {
|
|
4523
|
+
try {
|
|
4524
|
+
this._filterInstances.reset([]);
|
|
4525
|
+
}
|
|
4526
|
+
catch (e) {
|
|
4527
|
+
// Silently handle cleanup errors - QueryList might already be destroyed
|
|
4528
|
+
}
|
|
4529
|
+
}
|
|
4530
|
+
if (this._inlineInstances) {
|
|
4531
|
+
try {
|
|
4532
|
+
this._inlineInstances.reset([]);
|
|
4533
|
+
}
|
|
4534
|
+
catch (e) {
|
|
4535
|
+
// Silently handle cleanup errors - QueryList might already be destroyed
|
|
4536
|
+
}
|
|
4537
|
+
}
|
|
4538
|
+
if (this._inlineInstancesNew) {
|
|
4539
|
+
try {
|
|
4540
|
+
this._inlineInstancesNew.reset([]);
|
|
4541
|
+
}
|
|
4542
|
+
catch (e) {
|
|
4543
|
+
// Silently handle cleanup errors - QueryList might already be destroyed
|
|
4544
|
+
}
|
|
4545
|
+
}
|
|
4546
|
+
// MEMORY LEAK FIX: Clear all widget instance references
|
|
4547
|
+
this.filterInstance = null;
|
|
4548
|
+
this.inlineInstance = null;
|
|
4549
|
+
this.inlineInstanceNew = null;
|
|
4550
|
+
// MEMORY LEAK FIX: Clear template references
|
|
4551
|
+
this.customExprTmpl = null;
|
|
4552
|
+
this.inlineWidthTempRef = null;
|
|
4553
|
+
this.filterTemplateRef = null;
|
|
4554
|
+
// MEMORY LEAK FIX: Clear dataset references
|
|
4555
|
+
this._filterDataSet = null;
|
|
4556
|
+
this.dataset = null;
|
|
4557
|
+
this._dataoptions = null;
|
|
4558
|
+
this._datasource = null;
|
|
4559
|
+
// MEMORY LEAK FIX: Clear validation objects
|
|
4560
|
+
if (this.fieldValidations) {
|
|
4561
|
+
try {
|
|
4562
|
+
this.fieldValidations.destroy();
|
|
4563
|
+
}
|
|
4564
|
+
catch (e) {
|
|
4565
|
+
// Silently handle cleanup errors
|
|
4566
|
+
}
|
|
4567
|
+
this.fieldValidations = null;
|
|
4568
|
+
}
|
|
4569
|
+
if (this.fieldValidations_new) {
|
|
4570
|
+
try {
|
|
4571
|
+
this.fieldValidations_new.destroy();
|
|
4572
|
+
}
|
|
4573
|
+
catch (e) {
|
|
4574
|
+
// Silently handle cleanup errors
|
|
4575
|
+
}
|
|
4576
|
+
this.fieldValidations_new = null;
|
|
4577
|
+
}
|
|
4578
|
+
this.syncValidators = [];
|
|
4579
|
+
this.asyncValidators = [];
|
|
4580
|
+
// MEMORY LEAK FIX: Clear filter control reference
|
|
4581
|
+
this.filterControl = null;
|
|
4582
|
+
// MEMORY LEAK FIX: Clear notify fields array
|
|
4583
|
+
if (this.notifyForFields) {
|
|
4584
|
+
this.notifyForFields = [];
|
|
4585
|
+
}
|
|
4586
|
+
// MEMORY LEAK FIX: Clear observe fields array
|
|
4587
|
+
if (this.observeOnFields) {
|
|
4588
|
+
this.observeOnFields = [];
|
|
4589
|
+
}
|
|
4590
|
+
// MEMORY LEAK FIX: Clear table and group references
|
|
4591
|
+
// Note: These are injected dependencies, but clearing helps GC
|
|
4592
|
+
this.table = null;
|
|
4593
|
+
this.group = null;
|
|
4594
|
+
// Call parent ngOnDestroy
|
|
4595
|
+
super.ngOnDestroy();
|
|
4596
|
+
}
|
|
4255
4597
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TableColumnDirective, deps: [{ token: i0.Injector }, { token: i2.AppDefaults }, { token: TableComponent, optional: true }, { token: TableColumnGroupDirective, optional: true }, { token: 'filterdataset.bind', attribute: true }, { token: 'dataset.bind', attribute: true }, { token: 'EXPLICIT_CONTEXT', optional: true }], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
4256
4598
|
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: TableColumnDirective, isStandalone: true, selector: "[wmTableColumn]", providers: [
|
|
4257
4599
|
provideAsWidgetRef(TableColumnDirective)
|
|
@@ -4346,6 +4688,13 @@ class TableRowDirective extends BaseComponent {
|
|
|
4346
4688
|
this.config.content = this.content;
|
|
4347
4689
|
}
|
|
4348
4690
|
}
|
|
4691
|
+
ngOnDestroy() {
|
|
4692
|
+
// MEMORY LEAK FIX: Clear table and config references
|
|
4693
|
+
this.table = null;
|
|
4694
|
+
this.config = null;
|
|
4695
|
+
// Call parent ngOnDestroy (BaseComponent has cleanup)
|
|
4696
|
+
super.ngOnDestroy();
|
|
4697
|
+
}
|
|
4349
4698
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TableRowDirective, deps: [{ token: i0.Injector }, { token: TableComponent, optional: true, skipSelf: true }, { token: 'EXPLICIT_CONTEXT', optional: true }], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
4350
4699
|
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: TableRowDirective, isStandalone: true, selector: "[wmTableRow]", providers: [
|
|
4351
4700
|
provideAsWidgetRef(TableRowDirective)
|
|
@@ -4427,6 +4776,13 @@ class TableRowActionDirective extends BaseComponent {
|
|
|
4427
4776
|
this.populateAction();
|
|
4428
4777
|
this.table.registerRowActions(this.buttonDef);
|
|
4429
4778
|
}
|
|
4779
|
+
ngOnDestroy() {
|
|
4780
|
+
// MEMORY LEAK FIX: Clear table reference and button definition
|
|
4781
|
+
this.table = null;
|
|
4782
|
+
this.buttonDef = null;
|
|
4783
|
+
// Call parent ngOnDestroy (BaseComponent has cleanup)
|
|
4784
|
+
super.ngOnDestroy();
|
|
4785
|
+
}
|
|
4430
4786
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TableRowActionDirective, deps: [{ token: i0.Injector }, { token: TableComponent, optional: true }, { token: Context, self: true }, { token: 'EXPLICIT_CONTEXT', optional: true }], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
4431
4787
|
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: TableRowActionDirective, isStandalone: true, selector: "[wmTableRowAction]", providers: [
|
|
4432
4788
|
provideAsWidgetRef(TableRowActionDirective),
|