diff --git a/projects/igniteui-angular/src/lib/core/utils.ts b/projects/igniteui-angular/src/lib/core/utils.ts index 96301bbfc2f..61451d83813 100644 --- a/projects/igniteui-angular/src/lib/core/utils.ts +++ b/projects/igniteui-angular/src/lib/core/utils.ts @@ -24,13 +24,11 @@ export function cloneHierarchicalArray(array: any[], childDataKey: any): any[] { } for (const item of array) { + const clonedItem = cloneValue(item); if (Array.isArray(item[childDataKey])) { - const clonedItem = cloneValue(item); clonedItem[childDataKey] = cloneHierarchicalArray(clonedItem[childDataKey], childDataKey); - result.push(clonedItem); - } else { - result.push(item); } + result.push(clonedItem); } return result; } diff --git a/projects/igniteui-angular/src/lib/data-operations/data-util.ts b/projects/igniteui-angular/src/lib/data-operations/data-util.ts index 58a2616dc0f..ab191538643 100644 --- a/projects/igniteui-angular/src/lib/data-operations/data-util.ts +++ b/projects/igniteui-angular/src/lib/data-operations/data-util.ts @@ -242,35 +242,59 @@ export class DataUtil { data: any[], transactions: HierarchicalTransaction[], childDataKey: any, - primaryKey?: any, - parentKey?: any): any[] { + primaryKey?: any): any[] { - for (let index = 0; index < data.length; index++) { - const dataItem = data[index]; - const rowId = primaryKey ? dataItem[primaryKey] : dataItem; - const updateTransaction = transactions.filter(t => t.type === TransactionType.UPDATE).find(t => t.id === rowId); - const addedTransactions = transactions.filter(t => t.type === TransactionType.ADD).filter(t => t.parentId === rowId); - if (updateTransaction || addedTransactions.length > 0) { - data[index] = mergeObjects(cloneValue(dataItem), updateTransaction && updateTransaction.newValue); - } - if (addedTransactions.length > 0) { - if (!data[index][childDataKey]) { - data[index][childDataKey] = []; + for (let i = 0; i < transactions.length; i++) { + const transaction = transactions[i]; + const path = transaction.path; + + if (path) { + // We need to get parent data row. If there is a path and path contains this row id, + // this is the case for UPDATE and DELETE transactions type, remove the last id from + // the path + if (path.find(id => id === transaction.id)) { + path.splice(-1, 1); } - for (const addedTransaction of addedTransactions) { - data[index][childDataKey].push(addedTransaction.newValue); + const dataRow = this.getDataRowFromPath(data, primaryKey, childDataKey, path); + switch (transaction.type) { + case TransactionType.ADD: + // if there is no dataRow, but there is a path this is ADD row added to + // DELETED ADD row - we just skip this + if (dataRow) { + if (!dataRow[childDataKey]) { + dataRow[childDataKey] = []; + } + if (!dataRow[childDataKey].find(r => r[primaryKey] === transaction.id)) { + dataRow[childDataKey].push(transaction.newValue); + } + } + break; + case TransactionType.UPDATE: + const index = dataRow[childDataKey].findIndex(r => r[primaryKey] === transaction.id); + const dataItem = dataRow[childDataKey][index]; + dataRow[childDataKey][index] = mergeObjects(cloneValue(dataItem), transaction.newValue); + break; } - } - if (data[index][childDataKey]) { - data[index][childDataKey] = this.mergeHierarchicalTransactions( - data[index][childDataKey], - transactions, - childDataKey, - primaryKey, - rowId - ); + } else { + // if there is no path this is ADD row in root. Push the newValue to data + data.push(transaction.newValue); } } return data; } + + private static getDataRowFromPath(data: any[], primaryKey: any, childDataKey: any, path: any[]): any { + let collection: any[] = data; + let result: any; + for (let i = 0; i < path.length; i++) { + const rowIndex = collection ? collection.findIndex(r => r[primaryKey] === path[i]) : undefined; + result = collection ? collection[rowIndex] : undefined; + if (!result) { + break; + } + collection = result[childDataKey]; + } + + return result; + } } diff --git a/projects/igniteui-angular/src/lib/grids/api.service.ts b/projects/igniteui-angular/src/lib/grids/api.service.ts index 10cd6fea868..684c1e549ad 100644 --- a/projects/igniteui-angular/src/lib/grids/api.service.ts +++ b/projects/igniteui-angular/src/lib/grids/api.service.ts @@ -316,9 +316,9 @@ export class GridBaseAPIService { } const args = { rowID, - oldValue: oldValue, - newValue: editValue, - cancel: false + oldValue: oldValue, + newValue: editValue, + cancel: false }; if (cellObj) { Object.assign(args, { @@ -360,25 +360,31 @@ export class GridBaseAPIService { // if edit (new) value is same as old value do nothing here if (emittedArgs.oldValue !== undefined && isEqual(emittedArgs.oldValue, emittedArgs.newValue)) { return; } - const transaction: Transaction = { - id: rowID, type: TransactionType.UPDATE, newValue: { [column.field]: emittedArgs.newValue } - }; - if (grid.transactions.enabled) { - grid.transactions.add(transaction, currentGridEditState.rowData); - } else { - const rowValue = this.get_all_data(id)[rowIndex]; - mergeObjects(rowValue, {[column.field]: emittedArgs.newValue }); - } + const rowValue = this.get_all_data(id)[rowIndex]; + this.updateCellData(grid, rowID, rowValue, currentGridEditState.rowData, { [column.field]: emittedArgs.newValue }); if (grid.primaryKey === column.field && currentGridEditState.isRowSelected) { grid.selection.deselect_item(id, rowID); grid.selection.select_item(id, emittedArgs.newValue); } - if (!grid.rowEditable || !grid.rowInEditMode || grid.rowInEditMode.rowID !== rowID) { + if (!grid.rowEditable || !grid.rowInEditMode || grid.rowInEditMode.rowID !== rowID || !grid.transactions.enabled) { (grid as any)._pipeTrigger++; } } } + protected updateCellData(grid, rowID, rowValue: any, rowData: any, newValue: {[x: string]: any}) { + if (grid.transactions.enabled) { + const transaction: Transaction = { + id: rowID, + type: TransactionType.UPDATE, + newValue + }; + grid.transactions.add(transaction, rowData); + } else { + mergeObjects(rowValue, newValue); + } + } + public update_row(value: any, id: string, rowID: any, gridState?: { args: IGridEditEventArgs, isRowSelected: boolean, diff --git a/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid-api.service.ts b/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid-api.service.ts index 85114348e66..df81b3fde75 100644 --- a/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid-api.service.ts +++ b/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid-api.service.ts @@ -5,6 +5,8 @@ import { ITreeGridRecord } from './tree-grid.interfaces'; import { IRowToggleEventArgs } from './tree-grid.interfaces'; import { IgxColumnComponent } from '../column.component'; import { first } from 'rxjs/operators'; +import { HierarchicalTransaction, TransactionType } from '../../services'; +import { mergeObjects } from '../../core/utils'; export class IgxTreeGridAPIService extends GridBaseAPIService { public get_all_data(id: string, transactions?: boolean): any[] { @@ -122,4 +124,22 @@ export class IgxTreeGridAPIService extends GridBaseAPIService c[this.primaryKey]).indexOf(rowID) : childData.indexOf(rowID); if (this.transactions.enabled) { + const path = [...record.path]; + path.push(rowID); this.transactions.add({ id: rowID, type: TransactionType.DELETE, newValue: null, - parentId: record.parent ? record.parent.rowID : undefined + path: path }, - this.data); + childData[index]); } else { childData.splice(index, 1); } diff --git a/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid.pipes.ts b/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid.pipes.ts index 7054c766465..0f59b4379d7 100644 --- a/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid.pipes.ts +++ b/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid.pipes.ts @@ -265,8 +265,10 @@ export class IgxTreeGridTransactionPipe implements PipeTransform { } transform(collection: any[], id: string, pipeTrigger: number): any[] { + console.log(collection); const grid: IgxTreeGridComponent = this.gridAPI.get(id); - if (collection && grid.transactions.enabled) { + const aggregatedChanges = grid.transactions.getAggregatedChanges(true); + if (collection && aggregatedChanges.length > 0) { const primaryKey = grid.primaryKey; if (!primaryKey) { return collection; @@ -281,9 +283,10 @@ export class IgxTreeGridTransactionPipe implements PipeTransform { grid.transactions.getAggregatedChanges(true), grid.primaryKey); } else if (childDataKey) { + const clone = cloneHierarchicalArray(collection, childDataKey); return DataUtil.mergeHierarchicalTransactions( - cloneHierarchicalArray(collection, childDataKey), - grid.transactions.getAggregatedChanges(true), + clone, + aggregatedChanges, childDataKey, grid.primaryKey ); diff --git a/projects/igniteui-angular/src/lib/services/transaction/igx-hierarchical-transaction.ts b/projects/igniteui-angular/src/lib/services/transaction/igx-hierarchical-transaction.ts index 8fbf81657b1..4b6f6a8e537 100644 --- a/projects/igniteui-angular/src/lib/services/transaction/igx-hierarchical-transaction.ts +++ b/projects/igniteui-angular/src/lib/services/transaction/igx-hierarchical-transaction.ts @@ -12,7 +12,7 @@ export class IgxHierarchicalTransactionService { const value = mergeChanges ? this.mergeValues(state.recordRef, state.value) : state.value; this.clearArraysFromObject(value); - result.push({ id: key, parentId: state.parentId, newValue: value, type: state.type } as T); + result.push({ id: key, path: state.path, newValue: value, type: state.type } as T); }); return result; } @@ -20,8 +20,8 @@ export class IgxHierarchicalTransactionService, transaction: T, recordRef?: any): void { super.updateState(states, transaction, recordRef); const currentState = states.get(transaction.id); - if (currentState && transaction.type === TransactionType.ADD) { - currentState.parentId = transaction.parentId; + if (currentState) { + currentState.path = transaction.path; } } diff --git a/projects/igniteui-angular/src/lib/services/transaction/transaction.ts b/projects/igniteui-angular/src/lib/services/transaction/transaction.ts index 09164322d56..5bc55a04357 100644 --- a/projects/igniteui-angular/src/lib/services/transaction/transaction.ts +++ b/projects/igniteui-angular/src/lib/services/transaction/transaction.ts @@ -14,7 +14,7 @@ export interface Transaction { /** @experimental @hidden */ export interface HierarchicalTransaction extends Transaction { - parentId: any; + path: any[]; } export interface State { @@ -25,7 +25,7 @@ export interface State { /** @experimental @hidden */ export interface HierarchicalState extends State { - parentId: any; + path: any[]; } export interface TransactionService { diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 83ad99ef0bf..25273a080da 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -74,6 +74,7 @@ import { GridRowEditSampleComponent } from './grid-row-edit/grid-row-edit-sample import { GridWithTransactionsComponent } from './grid-row-edit/grid-with-transactions.component'; import { TreeGridSampleComponent } from './tree-grid/tree-grid.sample'; import { TreeGridFlatDataSampleComponent } from './tree-grid-flat-data/tree-grid-flat-data.sample'; +import { TreeGridWithTransactionsComponent } from './tree-grid/tree-grid-with-transactions.component'; const components = [ AppComponent, @@ -131,6 +132,7 @@ const components = [ GridWithTransactionsComponent, TreeGridSampleComponent, TreeGridFlatDataSampleComponent, + TreeGridWithTransactionsComponent, CustomContentComponent, ColorsSampleComponent, ShadowsSampleComponent, diff --git a/src/app/tree-grid/tree-grid.sample.html b/src/app/tree-grid/tree-grid.sample.html index edd5d50e4a4..a1418693e32 100644 --- a/src/app/tree-grid/tree-grid.sample.html +++ b/src/app/tree-grid/tree-grid.sample.html @@ -10,16 +10,18 @@
- - - - + + + + + +
Enable Paging @@ -32,4 +34,4 @@
- + \ No newline at end of file