igniteui-angular-sovn
Version:
Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps
252 lines (231 loc) • 9.56 kB
text/typescript
import { Injectable} from '@angular/core';
import { IgxSummaryResult } from './grid-summary';
import { DataUtil } from '../../data-operations/data-util';
import { cloneArray, resolveNestedPath } from '../../core/utils';
import { GridType, FlatGridType, TreeGridType } from '../common/grid.interface';
/** @hidden */
export class IgxGridSummaryService {
public grid: GridType;
public rootSummaryID = 'igxGridRootSummary';
public summaryHeight = 0;
public maxSummariesLenght = 0;
public groupingExpressions = [];
public retriggerRootPipe = 0;
public deleteOperation = false;
protected summaryCacheMap: Map<string, Map<string, any[]>> = new Map<string, Map<string, IgxSummaryResult[]>>();
public recalculateSummaries() {
this.resetSummaryHeight();
this.grid.notifyChanges(true);
}
public clearSummaryCache(args?) {
if (!this.summaryCacheMap.size) {
return;
}
if (!args) {
this.summaryCacheMap.clear();
if (this.grid && this.grid.rootSummariesEnabled) {
this.retriggerRootPipe++;
}
return;
}
if (args.data) {
const rowID = this.grid.primaryKey ? args.data[this.grid.primaryKey] : args.data;
this.removeSummaries(rowID);
}
if (args.rowID !== undefined && args.rowID !== null) {
let columnName = args.cellID ? this.grid.columns.find(col => col.index === args.cellID.columnID).field : undefined;
if (columnName && this.grid.rowEditable) {
return;
}
const isGroupedColumn = (this.grid as FlatGridType).groupingExpressions &&
(this.grid as FlatGridType).groupingExpressions.map(expr => expr.fieldName).indexOf(columnName) !== -1;
if (columnName && isGroupedColumn ) {
columnName = undefined;
}
this.removeSummaries(args.rowID, columnName);
}
}
public removeSummaries(rowID, columnName?) {
this.deleteSummaryCache(this.rootSummaryID, columnName);
if (this.summaryCacheMap.size === 1 && this.summaryCacheMap.has(this.rootSummaryID)) {
return;
}
if (this.isTreeGrid) {
if (this.grid.transactions.enabled && this.deleteOperation) {
this.deleteOperation = false;
// TODO: this.removeChildRowSummaries(rowID, columnName);
this.summaryCacheMap.clear();
return;
}
this.removeAllTreeGridSummaries(rowID, columnName);
} else if (this.isHierarchicalGrid) {
if (this.grid.transactions.enabled && this.deleteOperation) {
this.deleteOperation = false;
this.summaryCacheMap.clear();
}
} else {
const summaryIds = this.getSummaryID(rowID, (this.grid as FlatGridType).groupingExpressions);
summaryIds.forEach(id => {
this.deleteSummaryCache(id, columnName);
});
}
}
public removeSummariesCachePerColumn(columnName) {
this.summaryCacheMap.forEach((cache) => {
if (cache.get(columnName)) {
cache.delete(columnName);
}
});
if (this.grid.rootSummariesEnabled) {
this.retriggerRootPipe++;
}
}
public calcMaxSummaryHeight() {
if (this.summaryHeight) {
return this.summaryHeight;
}
if (!this.grid.data) {
return this.summaryHeight = 0;
}
let maxSummaryLength = 0;
this.grid.columns.filter((col) => col.hasSummary && !col.hidden).forEach((column) => {
const getCurrentSummaryColumn = column.summaries.operate([], [], column.field).length;
if (getCurrentSummaryColumn) {
if (maxSummaryLength < getCurrentSummaryColumn) {
maxSummaryLength = getCurrentSummaryColumn;
}
}
});
this.maxSummariesLenght = maxSummaryLength;
this.summaryHeight = maxSummaryLength * this.grid.defaultSummaryHeight;
return this.summaryHeight;
}
public calculateSummaries(rowID, data, groupRecord) {
let rowSummaries = this.summaryCacheMap.get(rowID);
if (!rowSummaries) {
rowSummaries = new Map<string, IgxSummaryResult[]>();
this.summaryCacheMap.set(rowID, rowSummaries);
}
if (!this.hasSummarizedColumns || !data) {
return rowSummaries;
}
this.grid.columns.filter(col => col.hasSummary).forEach((column) => {
if (!rowSummaries.get(column.field)) {
const summaryResult = column.summaries.operate(data.map(r => resolveNestedPath(r, column.field)),
data, column.field, groupRecord, this.grid.locale, column.pipeArgs);
rowSummaries.set(column.field, summaryResult);
}
});
return rowSummaries;
}
public resetSummaryHeight() {
this.summaryHeight = 0;
this.grid.summaryPipeTrigger++;
if (this.grid.rootSummariesEnabled) {
this.retriggerRootPipe++;
Promise.resolve().then(() => this.grid.notifyChanges(true));
}
}
public updateSummaryCache(groupingArgs) {
if (this.summaryCacheMap.size === 0 || !this.hasSummarizedColumns) {
return;
}
if (this.groupingExpressions.length === 0) {
this.groupingExpressions = groupingArgs.expressions.map(record => record.fieldName);
return;
}
if (groupingArgs.length === 0) {
this.groupingExpressions = [];
this.clearSummaryCache();
return;
}
this.compareGroupingExpressions(this.groupingExpressions, groupingArgs);
this.groupingExpressions = groupingArgs.expressions.map(record => record.fieldName);
}
public get hasSummarizedColumns(): boolean {
const summarizedColumns = this.grid.columns.filter(col => col.hasSummary && !col.hidden);
return summarizedColumns.length > 0;
}
private deleteSummaryCache(id, columnName) {
if (this.summaryCacheMap.get(id)) {
const filteringApplied = columnName && this.grid.filteringExpressionsTree &&
this.grid.filteringExpressionsTree.filteringOperands.map((expr) => expr.fieldName).indexOf(columnName) !== -1;
if (columnName && this.summaryCacheMap.get(id).get(columnName) && !filteringApplied) {
this.summaryCacheMap.get(id).delete(columnName);
} else {
this.summaryCacheMap.delete(id);
}
if (id === this.rootSummaryID && this.grid.rootSummariesEnabled) {
this.retriggerRootPipe++;
}
}
}
private getSummaryID(rowID, groupingExpressions) {
if (groupingExpressions.length === 0) {
return [];
}
const summaryIDs = [];
let data = this.grid.data;
if (this.grid.transactions.enabled) {
data = DataUtil.mergeTransactions(
cloneArray(this.grid.data),
this.grid.transactions.getAggregatedChanges(true),
this.grid.primaryKey,
this.grid.dataCloneStrategy
);
}
const rowData = this.grid.primaryKey ? data.find(rec => rec[this.grid.primaryKey] === rowID) : rowID;
let id = '{ ';
groupingExpressions.forEach(expr => {
id += `'${expr.fieldName}': '${rowData[expr.fieldName]}'`;
summaryIDs.push(id.concat(' }'));
id += ', ';
});
return summaryIDs;
}
private removeAllTreeGridSummaries(rowID, columnName?) {
let row = (this.grid as TreeGridType).records.get(rowID);
if (!row) {
return;
}
row = row.children ? row : row.parent;
while (row) {
rowID = row.key;
this.deleteSummaryCache(rowID, columnName);
row = row.parent;
}
}
// TODO: remove only deleted rows
// private removeChildRowSummaries(rowID, columnName?) {
// }
private compareGroupingExpressions(current, groupingArgs) {
const newExpressions = groupingArgs.expressions.map(record => record.fieldName);
const removedCols = groupingArgs.ungroupedColumns;
if (current.length <= newExpressions.length) {
const newExpr = newExpressions.slice(0, current.length).toString();
if (current.toString() !== newExpr) {
this.clearSummaryCache();
}
} else {
const currExpr = current.slice(0, newExpressions.length).toString();
if (currExpr !== newExpressions.toString()) {
this.clearSummaryCache();
return;
}
removedCols.map(col => col.field).forEach(colName => {
this.summaryCacheMap.forEach((cache, id) => {
if (id.indexOf(colName) !== -1) {
this.summaryCacheMap.delete(id);
}
});
});
}
}
private get isTreeGrid() {
return this.grid.nativeElement.tagName.toLowerCase() === 'igx-tree-grid';
}
private get isHierarchicalGrid() {
return this.grid.nativeElement.tagName.toLowerCase() === 'igx-hierarchical-grid';
}
}