@wavemaker/app-ng-runtime 11.15.4-rc.250 → 11.15.5-rc.253

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 (53) hide show
  1. package/components/base/bundles/index.umd.js +4 -13
  2. package/components/base/esm2022/utils/widget-utils.mjs +5 -4
  3. package/components/base/esm2022/widgets/common/base/base.component.mjs +1 -11
  4. package/components/base/fesm2022/index.mjs +4 -13
  5. package/components/base/fesm2022/index.mjs.map +1 -1
  6. package/components/containers/tabs/bundles/index.umd.js +1 -1
  7. package/components/containers/tabs/esm2022/tabs.animator.mjs +2 -2
  8. package/components/containers/tabs/fesm2022/index.mjs +1 -1
  9. package/components/containers/tabs/fesm2022/index.mjs.map +1 -1
  10. package/components/data/form/bundles/index.umd.js +6 -3
  11. package/components/data/form/esm2022/form.component.mjs +5 -2
  12. package/components/data/form/esm2022/live-form/live-form.directive.mjs +3 -3
  13. package/components/data/form/fesm2022/index.mjs +6 -3
  14. package/components/data/form/fesm2022/index.mjs.map +1 -1
  15. package/components/data/form/live-form/live-form.directive.d.ts +1 -1
  16. package/components/data/list/bundles/index.umd.js +6 -0
  17. package/components/data/list/esm2022/list.component.mjs +7 -1
  18. package/components/data/list/fesm2022/index.mjs +6 -0
  19. package/components/data/list/fesm2022/index.mjs.map +1 -1
  20. package/components/data/pagination/bundles/index.umd.js +45 -7
  21. package/components/data/pagination/esm2022/pagination.component.mjs +46 -8
  22. package/components/data/pagination/fesm2022/index.mjs +45 -7
  23. package/components/data/pagination/fesm2022/index.mjs.map +1 -1
  24. package/components/data/pagination/pagination.component.d.ts +1 -0
  25. package/components/data/table/bundles/index.umd.js +228 -20
  26. package/components/data/table/esm2022/table-column/table-column.directive.mjs +6 -1
  27. package/components/data/table/esm2022/table-cud.directive.mjs +14 -3
  28. package/components/data/table/esm2022/table-filter.directive.mjs +6 -1
  29. package/components/data/table/esm2022/table.component.mjs +206 -19
  30. package/components/data/table/fesm2022/index.mjs +229 -21
  31. package/components/data/table/fesm2022/index.mjs.map +1 -1
  32. package/components/data/table/table.component.d.ts +16 -1
  33. package/core/bundles/index.umd.js +7 -1
  34. package/core/esm2022/utils/dom.mjs +4 -2
  35. package/core/esm2022/utils/utils.mjs +5 -1
  36. package/core/fesm2022/index.mjs +7 -1
  37. package/core/fesm2022/index.mjs.map +1 -1
  38. package/npm-shrinkwrap.json +2 -2
  39. package/package-lock.json +2 -2
  40. package/package.json +1 -1
  41. package/runtime/base/bundles/index.umd.js +45 -12
  42. package/runtime/base/components/app-component/app.component.d.ts +1 -1
  43. package/runtime/base/esm2022/components/app-component/app.component.mjs +23 -12
  44. package/runtime/base/esm2022/guards/role.guard.mjs +2 -2
  45. package/runtime/base/esm2022/services/app.manager.service.mjs +23 -1
  46. package/runtime/base/fesm2022/index.mjs +45 -12
  47. package/runtime/base/fesm2022/index.mjs.map +1 -1
  48. package/runtime/base/services/app.manager.service.d.ts +5 -0
  49. package/scripts/datatable/datatable.js +282 -44
  50. package/transpiler/bundles/index.umd.js +3 -0
  51. package/transpiler/esm2022/build.mjs +4 -1
  52. package/transpiler/fesm2022/index.mjs +3 -0
  53. package/transpiler/fesm2022/index.mjs.map +1 -1
@@ -15,7 +15,7 @@ import { register, PROP_BOOLEAN, PROP_STRING, PROP_NUMBER, PROP_ANY, StylableCom
15
15
  import { PaginationComponent } from '@wm/components/data/pagination';
16
16
  import * as i3 from '@wm/components/data/list';
17
17
  import { debounceTime } from 'rxjs/operators';
18
- import { isEmpty, floor, debounce, isUndefined, isNaN as isNaN$1, extend, pullAllWith, isEqual, get, remove, findIndex, some, set, forEach, isArray, isObject, indexOf, keys, find, toNumber, includes, split, startsWith, omitBy, values, map, parseInt as parseInt$1, last, toString, isNull, filter, range, endsWith, toLower, head, orderBy, round, sum, max, min, mean, cloneDeep } from 'lodash-es';
18
+ import { get, isEmpty, floor, debounce, isUndefined, isNaN as isNaN$1, extend, pullAllWith, isEqual, remove, findIndex, some, set, forEach, isArray, isObject, indexOf, keys, find, toNumber, includes, split, startsWith, omitBy, values, map, parseInt as parseInt$1, last, toString, isNull, filter, range, endsWith, toLower, head, orderBy, round, sum, max, min, mean, cloneDeep } from 'lodash-es';
19
19
  import * as i6 from 'ngx-bootstrap/dropdown';
20
20
  import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
21
21
  import * as momentLib from 'moment';
@@ -96,6 +96,8 @@ const exportIconMapping = {
96
96
  CSV: 'fa fa-file-text-o'
97
97
  };
98
98
  const ROW_OPS_FIELD = 'rowOperations';
99
+ /** Same default as `table.props.ts` — used when `pagesizeoptions` cannot be parsed to integers. */
100
+ const DEFAULT_PAGE_SIZE_OPTIONS = '5,10,20,50,100';
99
101
  const noop = () => { };
100
102
  const isInputBodyWrapper = target => {
101
103
  const classes = ['.dropdown-menu', '.uib-typeahead-match', '.modal-dialog', '.toast'];
@@ -119,6 +121,19 @@ const isInputBodyWrapper = target => {
119
121
  };
120
122
  class TableComponent extends StylableComponent {
121
123
  static { this.initializeProps = registerProps$5(); }
124
+ /** wm.Variable + inline or quickedit (editmode is string from markup; normalize case). */
125
+ isModelVariableInlineOrQuickEdit() {
126
+ if (get(this.datasource, 'category') !== 'wm.Variable') {
127
+ return false;
128
+ }
129
+ const em = String(this.editmode || '').toLowerCase();
130
+ return em === 'quickedit' || em === 'inline';
131
+ }
132
+ /** True while an inline/quickedit row save is updating the grid (incl. delayed navigator emit). */
133
+ shouldSoftRefreshAfterModelVarRowSave() {
134
+ return this.isModelVariableInlineOrQuickEdit()
135
+ && (this._isInlineEditSave || this._modelVarEditSoftRefreshActiveUntil > Date.now());
136
+ }
122
137
  set gridData(newValue) {
123
138
  this.isDataLoading = false;
124
139
  // Fix for [WMS-24012]: hide no datafound msg when variableInflight is true and dataset is empty
@@ -186,7 +201,14 @@ class TableComponent extends StylableComponent {
186
201
  console.warn('Error in beforedatarender event callback, continuing with table rendering:', error);
187
202
  }
188
203
  }
189
- this.setDataGridOption('data', getClonedObject(this._gridData));
204
+ if (this.shouldSoftRefreshAfterModelVarRowSave()) {
205
+ const clonedData = getClonedObject(this._gridData);
206
+ this.gridOptions.data = clonedData;
207
+ this.callDataGridMethod('softRefreshData', clonedData);
208
+ }
209
+ else {
210
+ this.setDataGridOption('data', getClonedObject(this._gridData));
211
+ }
190
212
  }
191
213
  }
192
214
  get gridData() {
@@ -239,6 +261,8 @@ class TableComponent extends StylableComponent {
239
261
  this.formfields = {};
240
262
  this.enablesort = true;
241
263
  this.showviewlessbutton = false;
264
+ /** Covers async navigator/dataset updates after inline/quickedit save (wm.Variable). */
265
+ this._modelVarEditSoftRefreshActiveUntil = 0;
242
266
  this.primaryKey = [];
243
267
  this.selectedItems = [];
244
268
  this.selectedItemChange = new Subject();
@@ -314,10 +338,14 @@ class TableComponent extends StylableComponent {
314
338
  showviewlessbutton: false,
315
339
  ondemandmessage: '',
316
340
  allowpagesizechange: false,
317
- pagesizeoptions: '',
341
+ pagesizeoptions: DEFAULT_PAGE_SIZE_OPTIONS,
318
342
  viewlessmessage: '',
319
343
  loadingdatamsg: '',
320
344
  isNextPageData: undefined,
345
+ enableSort: true,
346
+ multiselect: false,
347
+ showRadioColumn: false,
348
+ enableColumnSelection: false,
321
349
  multiselecttitle: '',
322
350
  multiselectarialabel: '',
323
351
  radioselecttitle: '',
@@ -577,10 +605,24 @@ class TableComponent extends StylableComponent {
577
605
  this.prevData = getClonedObject(row);
578
606
  },
579
607
  afterRowUpdate: (row, e, callBack, options) => {
608
+ const isModelVarInlineOrQuick = this.isModelVariableInlineOrQuickEdit();
609
+ if (isModelVarInlineOrQuick) {
610
+ this._isInlineEditSave = true;
611
+ // Inline save triggers navigatePage / dataset emit asynchronously; a
612
+ // microtask timeout cleared the flag before gridData ran → full rerender.
613
+ this._modelVarEditSoftRefreshActiveUntil = Date.now() + 550;
614
+ }
580
615
  muteWatchers();
581
- this.updateRecord(extend({}, options, { row, 'prevData': options.rowindex ? options.rowindex : this.prevData, 'event': e, 'callBack': callBack }));
616
+ const v = get(this.datasource, 'category') === 'wm.Variable' && options && options.rowindex != null;
617
+ this.updateRecord(extend({}, options, { row, prevData: v ? options.rowindex : this.prevData, event: e, callBack }));
582
618
  setTimeout(() => {
583
619
  unMuteWatchers();
620
+ if (isModelVarInlineOrQuick) {
621
+ setTimeout(() => {
622
+ this._isInlineEditSave = false;
623
+ this._modelVarEditSoftRefreshActiveUntil = 0;
624
+ }, 520);
625
+ }
584
626
  }, 10);
585
627
  },
586
628
  onBeforeRowUpdate: (row, e, options) => {
@@ -653,11 +695,67 @@ class TableComponent extends StylableComponent {
653
695
  this.customExprCompiledTl = {};
654
696
  this.customExprCompiledSummaryTl = {};
655
697
  },
698
+ updateCustomExpressionContexts: (preparedData) => {
699
+ const viewCount = this.customExprViewRef.length;
700
+ for (let i = 0; i < viewCount; i++) {
701
+ const viewRef = this.customExprViewRef.get(i);
702
+ if (!viewRef || !viewRef.context || !viewRef.context.row || viewRef.context.row.$index === undefined) {
703
+ continue;
704
+ }
705
+ const existingRow = viewRef.context.row;
706
+ const rowIndex = existingRow.$index - 1;
707
+ const dataRow = preparedData[rowIndex];
708
+ if (!dataRow) {
709
+ continue;
710
+ }
711
+ Object.keys(dataRow).forEach(key => {
712
+ if (key !== '$$index' && key !== '$$pk') {
713
+ existingRow[key] = dataRow[key];
714
+ }
715
+ });
716
+ existingRow.$isFirst = existingRow.$index === 1;
717
+ existingRow.$isLast = this.gridData.length === existingRow.$index;
718
+ viewRef.markForCheck();
719
+ }
720
+ },
656
721
  clearRowDetailExpression: () => {
657
722
  this.rowDetailViewRef.clear();
658
723
  this.rowDefMap = {};
659
724
  this.rowDefInstances = {};
660
725
  },
726
+ invalidateRowDetailCache: (preparedData) => {
727
+ this.rowDefMap = {};
728
+ this.rowDefInstances = {};
729
+ // Update existing row detail view contexts in-place so currently
730
+ // expanded partials pick up the new row data via change detection.
731
+ const viewCount = this.rowDetailViewRef.length;
732
+ for (let i = 0; i < viewCount; i++) {
733
+ const viewRef = this.rowDetailViewRef.get(i);
734
+ if (!viewRef || !viewRef.context || !viewRef.context.row) {
735
+ continue;
736
+ }
737
+ const existingRow = viewRef.context.row;
738
+ const rowIndex = existingRow.$index - 1;
739
+ const dataRow = preparedData[rowIndex];
740
+ if (!dataRow) {
741
+ continue;
742
+ }
743
+ Object.keys(dataRow).forEach(key => {
744
+ if (key !== '$$index' && key !== '$$pk') {
745
+ existingRow[key] = dataRow[key];
746
+ }
747
+ });
748
+ viewRef.markForCheck();
749
+ }
750
+ },
751
+ refreshSelectedItems: () => {
752
+ const selectedRows = this.callDataGridMethod('getSelectedRows');
753
+ if (selectedRows.length) {
754
+ this.items.length = 0;
755
+ selectedRows.forEach(row => this.items.push(row));
756
+ this.selectedItemChange.next(selectedRows);
757
+ }
758
+ },
661
759
  generateCustomExpressions: (rowData, index, summaryRow) => {
662
760
  const row = this.getClonedRowObject(rowData);
663
761
  const compileTemplate = (tmpl) => {
@@ -1082,7 +1180,8 @@ class TableComponent extends StylableComponent {
1082
1180
  this.gridOptions.ondemandmessage = this.ondemandmessage;
1083
1181
  this.gridOptions.viewlessmessage = this.viewlessmessage;
1084
1182
  this.gridOptions.loadingdatamsg = this.loadingdatamsg;
1085
- this.gridOptions.pagesizeoptions = this.pagesizeoptions;
1183
+ this.gridOptions.pagesizeoptions = this.sanitizeCommaSeparatedIntegers(this.pagesizeoptions);
1184
+ this.pagesizeoptions = this.gridOptions.pagesizeoptions;
1086
1185
  this.gridOptions.multiselecttitle = this.multiselecttitle;
1087
1186
  this.gridOptions.multiselectarialabel = this.multiselectarialabel;
1088
1187
  this.gridOptions.radioselecttitle = this.radioselecttitle;
@@ -1359,6 +1458,8 @@ class TableComponent extends StylableComponent {
1359
1458
  }
1360
1459
  }
1361
1460
  ngOnDestroy() {
1461
+ this._modelVarEditSoftRefreshActiveUntil = 0;
1462
+ this._isInlineEditSave = false;
1362
1463
  // MEMORY LEAK FIX: Remove document click listener
1363
1464
  document.removeEventListener('click', this.documentClickBind);
1364
1465
  // MEMORY LEAK FIX: Unsubscribe from navigator watches
@@ -1512,6 +1613,7 @@ class TableComponent extends StylableComponent {
1512
1613
  row.$isLast = this.gridData.length === row.$index;
1513
1614
  delete row.$$index;
1514
1615
  delete row.$$pk;
1616
+ delete row.$$wmSourceListIndex;
1515
1617
  return row;
1516
1618
  }
1517
1619
  handleLoading(data) {
@@ -1611,10 +1713,13 @@ class TableComponent extends StylableComponent {
1611
1713
  }
1612
1714
  setDataGridOption(optionName, newVal, forceSet = false) {
1613
1715
  if (!this.datagridElement || !this.datagridElement.datatable || !this.datagridElement.datatable('instance')) {
1716
+ // Bound properties can update before the jQuery widget is initialized.
1717
+ // Keep gridOptions in sync so the initial datatable() call sees the latest value.
1718
+ this.gridOptions[optionName] = newVal;
1614
1719
  return;
1615
1720
  }
1616
1721
  const option = {};
1617
- if (isDefined && (!isEqual(newVal, this.gridOptions[optionName]) || forceSet)) {
1722
+ if (isDefined(newVal) && (!isEqual(newVal, this.gridOptions[optionName]) || forceSet)) {
1618
1723
  option[optionName] = newVal;
1619
1724
  this.datagridElement.datatable('option', option);
1620
1725
  this.gridOptions[optionName] = newVal;
@@ -1753,6 +1858,14 @@ class TableComponent extends StylableComponent {
1753
1858
  // Apply filter and sort, if data is refreshed through Refresh data method
1754
1859
  if (!this.isNavigationEnabled() && this._isClientSearch) {
1755
1860
  data = getClonedObject(serviceData);
1861
+ if (isObject(data) && !isArray(data)) {
1862
+ data = [data];
1863
+ }
1864
+ if (get(this.datasource, 'category') === 'wm.Variable' && isArray(data)) {
1865
+ for (let i = 0; i < data.length; i++) {
1866
+ data[i].$$wmSourceListIndex = i;
1867
+ }
1868
+ }
1756
1869
  data = this.getSearchResult(data, this.filterInfo);
1757
1870
  data = this.getSortResult(data, this.sortInfo);
1758
1871
  this.serverData = data;
@@ -2049,13 +2162,48 @@ class TableComponent extends StylableComponent {
2049
2162
  case 'allowpagesizechange':
2050
2163
  this.gridOptions.allowpagesizechange = nv;
2051
2164
  this.allowpagesizechange = nv;
2165
+ this.dataNavigator.allowpagesizechange = nv;
2166
+ if (nv) {
2167
+ const pagesizeoptions = this.sanitizeCommaSeparatedIntegers(this.pagesizeoptions);
2168
+ this.gridOptions.pagesizeoptions = pagesizeoptions;
2169
+ this.pagesizeoptions = pagesizeoptions;
2170
+ this.prevPagesizeoptions = '';
2171
+ this.setDefaultPageSize(this.pagesize || this.actualPageSize || this.gridOptions.getPageSize());
2172
+ }
2052
2173
  break;
2053
2174
  case 'pagesizeoptions':
2054
2175
  this.prevPagesizeoptions = this.sanitizeCommaSeparatedIntegers(ov);
2055
2176
  this.gridOptions.pagesizeoptions = this.sanitizeCommaSeparatedIntegers(nv);
2056
- this.pagesizeoptions = this.sanitizeCommaSeparatedIntegers(nv);
2057
- if (this.allowpagesizechange)
2058
- this.setDefaultPageSize(nv);
2177
+ this.pagesizeoptions = this.gridOptions.pagesizeoptions;
2178
+ if (this.allowpagesizechange) {
2179
+ this.setDefaultPageSize(this.pagesize || this.actualPageSize || this.gridOptions.getPageSize());
2180
+ if (get(this.datasource, 'category') !== 'wm.Variable') {
2181
+ this.dataNavigator.onPageSizeChange(undefined, this.dataNavigator.pageSizeOptions[0] || this.pagesize);
2182
+ }
2183
+ }
2184
+ break;
2185
+ case 'showheader':
2186
+ this.setDataGridOption('showHeader', nv);
2187
+ break;
2188
+ case 'showheader':
2189
+ this.setDataGridOption('showHeader', nv);
2190
+ break;
2191
+ case 'enablesort':
2192
+ this.setDataGridOption('enableSort', nv);
2193
+ break;
2194
+ case 'enablecolumnselection':
2195
+ // this.enablecolumnselection = nv;
2196
+ //this.gridOptions.enableColumnSelection = nv;
2197
+ this.setDataGridOption('enableColumnSelection', nv);
2198
+ break;
2199
+ case 'isrowselectable':
2200
+ this.setDataGridOption('isrowselectable', nv);
2201
+ break;
2202
+ case 'multiselect':
2203
+ this.setDataGridOption('multiselect', nv);
2204
+ break;
2205
+ case 'radioselect':
2206
+ this.setDataGridOption('showRadioColumn', nv);
2059
2207
  break;
2060
2208
  case 'multiselecttitle':
2061
2209
  this.setDataGridOption('multiselecttitle', nv);
@@ -2090,17 +2238,22 @@ class TableComponent extends StylableComponent {
2090
2238
  setDefaultPageSize(nv) {
2091
2239
  let widgetState = this.statePersistence.getWidgetState(this);
2092
2240
  if (this.gridOptions.allowpagesizechange) {
2093
- if (get(widgetState, 'pagesize')) {
2241
+ const normalizedPageSizeOptions = this.getNormalizedPageSizeOptionsArray(this.pagesizeoptions);
2242
+ if (this.isPageSizeOptionsChanged() && normalizedPageSizeOptions.length) { // if pagesize options are changed, then update the pagesize without checking for statepersistence
2243
+ nv = normalizedPageSizeOptions[0];
2244
+ this.pagesize = nv;
2245
+ }
2246
+ else if (get(widgetState, 'pagesize')) {
2094
2247
  nv = get(widgetState, 'pagesize');
2095
2248
  this.pagesize = nv; // updating the default pagesize to user selected pagesize
2096
2249
  }
2097
- else if (this.pagesizeoptions) {
2098
- nv = this.pagesizeoptions?.split(',').map(Number).sort((a, b) => a - b)[0];
2250
+ else if (this.pagesizeoptions && normalizedPageSizeOptions.length) {
2251
+ nv = normalizedPageSizeOptions[0];
2099
2252
  this.pagesize = nv;
2100
2253
  }
2101
2254
  this.updatedPageSize = nv;
2102
2255
  if (this.isPageSizeOptionsChanged()) {
2103
- this.dataNavigator.defaultPageSizeOptions = this.pagesizeoptions?.split(',').map(Number).sort((a, b) => a - b) || [];
2256
+ this.dataNavigator.defaultPageSizeOptions = normalizedPageSizeOptions;
2104
2257
  this.dataNavigator.pageSizeOptions = [...this.dataNavigator.defaultPageSizeOptions];
2105
2258
  }
2106
2259
  }
@@ -2126,14 +2279,43 @@ class TableComponent extends StylableComponent {
2126
2279
  this.dataNavigator.onPageSizeChange(undefined, pagesize);
2127
2280
  }
2128
2281
  sanitizeCommaSeparatedIntegers(input) {
2129
- if (!input)
2130
- return "";
2131
- const uniqueNumbers = Array.from(new Set(input
2132
- .split(",")
2133
- .map(v => v.trim())
2282
+ if (input === null || input === undefined || input === '') {
2283
+ return DEFAULT_PAGE_SIZE_OPTIONS;
2284
+ }
2285
+ let arr;
2286
+ if (Array.isArray(input)) {
2287
+ arr = input;
2288
+ }
2289
+ else if (typeof input === "string") {
2290
+ const trimmed = input.trim();
2291
+ if (trimmed.startsWith("[") && trimmed.endsWith("]")) {
2292
+ try {
2293
+ arr = JSON.parse(trimmed);
2294
+ }
2295
+ catch {
2296
+ arr = [];
2297
+ }
2298
+ }
2299
+ else {
2300
+ arr = trimmed.split(",");
2301
+ }
2302
+ }
2303
+ else {
2304
+ return DEFAULT_PAGE_SIZE_OPTIONS;
2305
+ }
2306
+ const uniqueNumbers = Array.from(new Set(arr
2307
+ .map(v => String(v).trim())
2134
2308
  .filter(v => /^-?\d+$/.test(v))
2135
2309
  .map(v => Math.abs(parseInt(v, 10)))));
2136
- return uniqueNumbers.join(",");
2310
+ const joined = uniqueNumbers.join(",");
2311
+ return joined || DEFAULT_PAGE_SIZE_OPTIONS;
2312
+ }
2313
+ getNormalizedPageSizeOptionsArray(input) {
2314
+ return this.sanitizeCommaSeparatedIntegers(input)
2315
+ .split(',')
2316
+ .map(Number)
2317
+ .filter(v => !isNaN$1(v))
2318
+ .sort((a, b) => a - b);
2137
2319
  }
2138
2320
  onDataSourceChange() {
2139
2321
  this.fieldDefs.forEach(col => {
@@ -2261,6 +2443,11 @@ class TableComponent extends StylableComponent {
2261
2443
  if (isObject(data) && !isArray(data)) {
2262
2444
  data = [data];
2263
2445
  }
2446
+ if (get(this.datasource, 'category') === 'wm.Variable' && isArray(data)) {
2447
+ for (let i = 0; i < data.length; i++) {
2448
+ data[i].$$wmSourceListIndex = i;
2449
+ }
2450
+ }
2264
2451
  data = this.getSearchResult(data, this.filterInfo);
2265
2452
  data = this.getSortResult(data, this.sortInfo);
2266
2453
  return data;
@@ -2688,7 +2875,11 @@ class TableCUDDirective {
2688
2875
  if (dataSource.execute(DataSource.Operation.SUPPORTS_CRUD) || !dataSource.execute(DataSource.Operation.IS_API_AWARE) || dataSource.category === 'wm.CrudVariable') {
2689
2876
  if (!dataSource.execute(DataSource.Operation.IS_API_AWARE)) {
2690
2877
  const extraOptions = this.generatePath(this.table.binddataset);
2691
- dataSource.execute(DataSource.Operation.SET_ITEM, { prevItem: options.prevData, item: options.row, path: extraOptions.path, parentIndex: extraOptions.index });
2878
+ const item = options.row;
2879
+ if (dataSource.category === 'wm.Variable' && item) {
2880
+ delete item['$$wmSourceListIndex'];
2881
+ }
2882
+ dataSource.execute(DataSource.Operation.SET_ITEM, { prevItem: options.prevData, item, path: extraOptions.path, parentIndex: extraOptions.index });
2692
2883
  this.updateSuccessHandler(options.row, options);
2693
2884
  return;
2694
2885
  }
@@ -2771,7 +2962,14 @@ class TableCUDDirective {
2771
2962
  if (dataSource.execute(DataSource.Operation.SUPPORTS_CRUD) || !dataSource.execute(DataSource.Operation.IS_API_AWARE) || this.table._isDependent || dataSource.category === 'wm.CrudVariable') {
2772
2963
  if (!dataSource.execute(DataSource.Operation.IS_API_AWARE)) {
2773
2964
  const extraOptions = this.generatePath(this.table.binddataset);
2774
- dataSource.execute(DataSource.Operation.REMOVE_ITEM, { item: options.row, path: extraOptions.path, parentIndex: extraOptions.index });
2965
+ let item = options.row;
2966
+ if (dataSource.category === 'wm.Variable' && options.rowindex != null) {
2967
+ item = options.rowindex;
2968
+ }
2969
+ else if (dataSource.category === 'wm.Variable' && item) {
2970
+ delete item['$$wmSourceListIndex'];
2971
+ }
2972
+ dataSource.execute(DataSource.Operation.REMOVE_ITEM, { item, path: extraOptions.path, parentIndex: extraOptions.index });
2775
2973
  this.deleteSuccessHandler(options.row, undefined, options.evt, options.callBack);
2776
2974
  return;
2777
2975
  }
@@ -3312,6 +3510,11 @@ class TableFilterSortDirective {
3312
3510
  if (isObject(data) && !isArray(data)) {
3313
3511
  data = [data];
3314
3512
  }
3513
+ if (get(this.table.datasource, 'category') === 'wm.Variable' && isArray(data)) {
3514
+ for (let i = 0; i < data.length; i++) {
3515
+ data[i].$$wmSourceListIndex = i;
3516
+ }
3517
+ }
3315
3518
  /*Both the functions return same 'data' if arguments are undefined*/
3316
3519
  data = this.getSearchResult(data, this.table.filterInfo);
3317
3520
  data = this.getSortResult(data, this.table.sortInfo);
@@ -4525,6 +4728,11 @@ class TableColumnDirective extends BaseComponent {
4525
4728
  case 'showinfilter':
4526
4729
  this.showinfilter = nv;
4527
4730
  break;
4731
+ case 'sortable':
4732
+ if (this.table) {
4733
+ this.table.callDataGridMethod('refreshSortHeader');
4734
+ }
4735
+ break;
4528
4736
  default:
4529
4737
  if (inlineWidgetProps.includes(key)) {
4530
4738
  this.setInlineWidgetProp('inlineInstance', key, nv);