Skip to content

Commit

Permalink
refactor(tree-grid): apply transaction in one iteration, #2921
Browse files Browse the repository at this point in the history
By the help of transaction.path we are able to going trough all the changes
now and update the cloned data source without need of recursion.
  • Loading branch information
wnvko committed Nov 13, 2018
1 parent 8802b28 commit a4b9cfb
Show file tree
Hide file tree
Showing 10 changed files with 124 additions and 65 deletions.
6 changes: 2 additions & 4 deletions projects/igniteui-angular/src/lib/core/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
72 changes: 48 additions & 24 deletions projects/igniteui-angular/src/lib/data-operations/data-util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
32 changes: 19 additions & 13 deletions projects/igniteui-angular/src/lib/grids/api.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -316,9 +316,9 @@ export class GridBaseAPIService <T extends IgxGridBaseComponent> {
}
const args = {
rowID,
oldValue: oldValue,
newValue: editValue,
cancel: false
oldValue: oldValue,
newValue: editValue,
cancel: false
};
if (cellObj) {
Object.assign(args, {
Expand Down Expand Up @@ -360,25 +360,31 @@ export class GridBaseAPIService <T extends IgxGridBaseComponent> {
// 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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<IgxTreeGridComponent> {
public get_all_data(id: string, transactions?: boolean): any[] {
Expand Down Expand Up @@ -122,4 +124,22 @@ export class IgxTreeGridAPIService extends GridBaseAPIService<IgxTreeGridCompone
public should_apply_number_style(column: IgxColumnComponent): boolean {
return column.dataType === DataType.Number && column.visibleIndex !== 0;
}

protected updateCellData(grid: IgxTreeGridComponent, rowID: any, rowValue: any, rowData: any, newValue: {[x: string]: any}) {
if (grid.transactions.enabled) {
const record: ITreeGridRecord = grid.records.get(rowID);
const path = [...record.path];
path.push(rowID);
const transaction: HierarchicalTransaction = {
id: rowID,
type: TransactionType.UPDATE,
newValue,
path: path
};
grid.transactions.add(transaction, rowData);
} else {
mergeObjects(rowValue, newValue);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -368,9 +368,11 @@ export class IgxTreeGridComponent extends IgxGridBaseComponent {
const childKey = this.childDataKey;
if (this.transactions.enabled) {
const rowId = this.primaryKey ? data[this.primaryKey] : data;
const path = [...parentRecord.path];
path.push(parentRowID);
this.transactions.add({
id: rowId,
parentId: parentRowID,
path: path,
newValue: data,
type: TransactionType.ADD
} as HierarchicalTransaction,
Expand All @@ -397,13 +399,13 @@ export class IgxTreeGridComponent extends IgxGridBaseComponent {
* @hidden
*/
public deleteRowById(rowId: any) {
if (this.transactions.enabled && this.cascadeOnDelete) {
if (this.transactions.enabled && this.foreignKey && this.cascadeOnDelete) {
this.transactions.startPending();
}

super.deleteRowById(rowId);

if (this.transactions.enabled && this.cascadeOnDelete) {
if (this.transactions.enabled && this.foreignKey && this.cascadeOnDelete) {
this.transactions.endPending(true);
}
}
Expand All @@ -430,13 +432,15 @@ export class IgxTreeGridComponent extends IgxGridBaseComponent {
index = this.primaryKey ? childData.map(c => 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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@ export class IgxHierarchicalTransactionService<T extends HierarchicalTransaction
this._states.forEach((state: S, key: any) => {
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;
}

protected updateState(states: Map<any, S>, 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;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export interface Transaction {

/** @experimental @hidden */
export interface HierarchicalTransaction extends Transaction {
parentId: any;
path: any[];
}

export interface State {
Expand All @@ -25,7 +25,7 @@ export interface State {

/** @experimental @hidden */
export interface HierarchicalState extends State {
parentId: any;
path: any[];
}

export interface TransactionService<T extends Transaction, S extends State> {
Expand Down
2 changes: 2 additions & 0 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -131,6 +132,7 @@ const components = [
GridWithTransactionsComponent,
TreeGridSampleComponent,
TreeGridFlatDataSampleComponent,
TreeGridWithTransactionsComponent,
CustomContentComponent,
ColorsSampleComponent,
ShadowsSampleComponent,
Expand Down
24 changes: 13 additions & 11 deletions src/app/tree-grid/tree-grid.sample.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,18 @@
<div class="density-chooser" style="margin-bottom: 16px">
<igx-buttongroup [values]="displayDensities" (onSelect)="selectDensity($event)" style="display: block; width: 500px"></igx-buttongroup>
</div>
<igx-tree-grid #grid1 [data]="data" childDataKey="ChildCompanies" primaryKey="ID" expansionDepth="1"
rowSelectable="true" [paging]="false" [displayDensity]="density" [width]="'900px'" [height]="'500px'"
[showToolbar]="true" [columnHiding]="true" [columnPinning]="true" [exportExcel]="true" [exportCsv]="true"
exportText="Export" exportExcelText="Export to Excel" exportCsvText="Export to CSV">
<igx-column *ngFor="let c of columns" [field]="c.field" [header]="c.field" [pinned]="c.pinned"
[movable]="c.movable" [groupable]="false" [resizable]="c.resizable" [width]="c.width"
[sortable]="true" [filterable]="true" [editable]="true" [hidden]="c.hidden" [hasSummary]="c.summary"
[minWidth]="c.minWidth" [maxWidth]="c.maxWidth">
</igx-column>
</igx-tree-grid>
<app-tree-grid-with-transactions>
<igx-tree-grid #grid1 [data]="data" childDataKey="ChildCompanies" primaryKey="ID" expansionDepth="1"
rowSelectable="true" [paging]="false" [displayDensity]="density" [width]="'900px'" [height]="'500px'"
[showToolbar]="true" [columnHiding]="true" [columnPinning]="true" [exportExcel]="true" [exportCsv]="true"
exportText="Export" exportExcelText="Export to Excel" exportCsvText="Export to CSV">
<igx-column *ngFor="let c of columns" [field]="c.field" [header]="c.field" [pinned]="c.pinned"
[movable]="c.movable" [groupable]="false" [resizable]="c.resizable" [width]="c.width"
[sortable]="true" [filterable]="true" [editable]="true" [hidden]="c.hidden" [hasSummary]="c.summary"
[minWidth]="c.minWidth" [maxWidth]="c.maxWidth">
</igx-column>
</igx-tree-grid>
</app-tree-grid-with-transactions>

<div class="topMargin">
<igx-switch [(ngModel)]="grid1.paging">Enable Paging</igx-switch>
Expand All @@ -32,4 +34,4 @@
</div>
</div>
</div>
</div>
</div>

0 comments on commit a4b9cfb

Please sign in to comment.