igniteui-angular
Version:
Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps
1,085 lines • 113 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
import { Component, ChangeDetectionStrategy, Input, Output, EventEmitter, ContentChild, ViewChildren, QueryList, ViewChild, ElementRef, TemplateRef, NgZone, ChangeDetectorRef, ComponentFactoryResolver, IterableDiffers, ViewContainerRef, Inject, HostBinding, forwardRef, Optional } from '@angular/core';
import { GridBaseAPIService } from '../api.service';
import { IgxGridBaseComponent, IgxGridTransaction } from '../grid-base.component';
import { IgxGridNavigationService } from '../grid-navigation.service';
import { IgxGridAPIService } from './grid-api.service';
import { cloneArray } from '../../core/utils';
import { IgxGroupByRowTemplateDirective } from './grid.directives';
import { IgxGridGroupByRowComponent } from './groupby-row.component';
import { DisplayDensityToken } from '../../core/displayDensity';
import { DataUtil } from '../../data-operations/data-util';
import { IgxSelectionAPIService } from '../../core/selection';
import { DOCUMENT } from '@angular/common';
import { takeUntil } from 'rxjs/operators';
import { IgxFilteringService } from '../filtering/grid-filtering.service';
import { IgxColumnResizingService } from '../grid-column-resizing.service';
import { IgxGridSummaryService } from '../summaries/grid-summary.service';
import { IgxGridSelectionService, IgxGridCRUDService } from '../../core/grid-selection';
import { IgxOverlayService } from '../../services/index';
import { IgxForOfSyncService } from '../../directives/for-of/for_of.sync.service';
/** @type {?} */
let NEXT_ID = 0;
/**
* @record
*/
export function IGridFocusChangeEventArgs() { }
if (false) {
/** @type {?} */
IGridFocusChangeEventArgs.prototype.groupRow;
}
/**
* @record
*/
export function IGroupingDoneEventArgs() { }
if (false) {
/** @type {?} */
IGroupingDoneEventArgs.prototype.expressions;
/** @type {?} */
IGroupingDoneEventArgs.prototype.groupedColumns;
/** @type {?} */
IGroupingDoneEventArgs.prototype.ungroupedColumns;
}
/**
* **Ignite UI for Angular Grid** -
* [Documentation](https://www.infragistics.com/products/ignite-ui-angular/angular/components/grid.html)
*
* The Ignite UI Grid is used for presenting and manipulating tabular data in the simplest way possible. Once data
* has been bound, it can be manipulated through filtering, sorting & editing operations.
*
* Example:
* ```html
* <igx-grid [data]="employeeData" autoGenerate="false">
* <igx-column field="first" header="First Name"></igx-column>
* <igx-column field="last" header="Last Name"></igx-column>
* <igx-column field="role" header="Role"></igx-column>
* </igx-grid>
* ```
*/
export class IgxGridComponent extends IgxGridBaseComponent {
/**
* @param {?} selectionService
* @param {?} crudService
* @param {?} colResizingService
* @param {?} gridAPI
* @param {?} selection
* @param {?} _transactions
* @param {?} elementRef
* @param {?} zone
* @param {?} document
* @param {?} cdr
* @param {?} resolver
* @param {?} differs
* @param {?} viewRef
* @param {?} navigation
* @param {?} filteringService
* @param {?} overlayService
* @param {?} summaryService
* @param {?} _displayDensityOptions
*/
constructor(selectionService, crudService, colResizingService, gridAPI, selection, _transactions, elementRef, zone, document, cdr, resolver, differs, viewRef, navigation, filteringService, overlayService, summaryService, _displayDensityOptions) {
super(selectionService, crudService, gridAPI, selection, _transactions, elementRef, zone, document, cdr, resolver, differs, viewRef, navigation, filteringService, overlayService, summaryService, _displayDensityOptions);
this.colResizingService = colResizingService;
this.document = document;
this.overlayService = overlayService;
this._displayDensityOptions = _displayDensityOptions;
this._id = `igx-grid-${NEXT_ID++}`;
/**
* @hidden
*/
this._groupingExpressions = [];
/**
* @hidden
*/
this._groupingExpandState = [];
this._hideGroupedColumns = false;
this._dropAreaMessage = null;
this._filteredData = null;
/**
* An \@Input property that determines whether created groups are rendered expanded or collapsed.
* The default rendered state is expanded.
* ```html
* <igx-grid #grid [data]="Data" [groupsExpanded]="false" [autoGenerate]="true"></igx-grid>
* ```
* \@memberof IgxGridComponent
*/
this.groupsExpanded = true;
/**
* A hierarchical representation of the group by records.
* ```typescript
* let groupRecords = this.grid.groupsRecords;
* ```
* \@memberof IgxGridComponent
*/
this.groupsRecords = [];
/**
* Emitted when a new `IgxColumnComponent` gets grouped/ungrouped, or multiple columns get
* grouped/ungrouped at once by using the Group By API.
* The `onGroupingDone` event would be raised only once if several columns get grouped at once by calling
* the `groupBy()` or `clearGrouping()` API methods and passing an array as an argument.
* The event arguments provide the `expressions`, `groupedColumns` and `ungroupedColumns` properties, which contain
* the `ISortingExpression` and the `IgxColumnComponent` related to the grouping/ungrouping operation.
* Please note that `groupedColumns` and `ungroupedColumns` show only the **newly** changed columns (affected by the **last**
* grouping/ungrouping operation), not all columns which are currently grouped/ungrouped.
* columns.
* ```typescript
* groupingDone(event: IGroupingDoneEventArgs){
* const expressions = event.expressions;
* //the newly grouped columns
* const groupedColumns = event.groupedColumns;
* //the newly ungrouped columns
* const ungroupedColumns = event.ungroupedColumns;
* }
* ```
* ```html
* <igx-grid #grid [data]="localData" (onGroupingDone)="groupingDone($event)" [autoGenerate]="true"></igx-grid>
* ```
* \@memberof IgxGridComponent
*/
this.onGroupingDone = new EventEmitter();
this.onFocusChange = new EventEmitter();
this._gridAPI = (/** @type {?} */ (gridAPI));
}
/**
* An \@Input property that sets the value of the `id` attribute. If not provided it will be automatically generated.
* ```html
* <igx-grid [id]="'igx-grid-1'" [data]="Data" [autoGenerate]="true"></igx-grid>
* ```
* \@memberof IgxGridComponent
* @return {?}
*/
get id() {
return this._id;
}
/**
* @param {?} value
* @return {?}
*/
set id(value) {
this._id = value;
}
/**
* An \@Input property that lets you fill the `IgxGridComponent` with an array of data.
* ```html
* <igx-grid [data]="Data" [autoGenerate]="true"></igx-grid>
* ```
* \@memberof IgxGridBaseComponent
* @return {?}
*/
get data() {
return this._data;
}
/**
* @param {?} value
* @return {?}
*/
set data(value) {
this._data = value;
if (this._ngAfterViewInitPassed &&
this.calcHeight === null &&
this.isPercentHeight) {
/* the body should be auto-sized in this case before igxFor renders the whole data */
/** @type {?} */
const bodyHeight = this.defaultTargetBodyHeight;
this.calcHeight = bodyHeight > 0 ? bodyHeight : null;
}
this.summaryService.clearSummaryCache();
if (this.shouldGenerate) {
this.setupColumns();
this.reflow();
}
this.cdr.markForCheck();
}
/**
* Returns an array of objects containing the filtered data in the `IgxGridComponent`.
* ```typescript
* let filteredData = this.grid.filteredData;
* ```
* \@memberof IgxGridComponent
* @return {?}
*/
get filteredData() {
return this._filteredData;
}
/**
* Sets an array of objects containing the filtered data in the `IgxGridComponent`.
* ```typescript
* this.grid.filteredData = [{
* ID: 1,
* Name: "A"
* }];
* ```
* \@memberof IgxGridComponent
* @param {?} value
* @return {?}
*/
set filteredData(value) {
this._filteredData = value;
if (this.rowSelectable) {
this.updateHeaderCheckboxStatusOnFilter(this._filteredData);
}
}
/**
* Returns the group by state of the `IgxGridComponent`.
* ```typescript
* let groupByState = this.grid.groupingExpressions;
* ```
* \@memberof IgxGridComponent
* @return {?}
*/
get groupingExpressions() {
return this._groupingExpressions;
}
/**
* Sets the group by state of the `IgxGridComponent` and emits the `onGroupingDone`
* event with the appropriate arguments.
* ```typescript
* this.grid.groupingExpressions = [{
* fieldName: "ID",
* dir: SortingDirection.Asc,
* ignoreCase: false
* }];
* ```
* \@memberof IgxGridComponent
* @param {?} value
* @return {?}
*/
set groupingExpressions(value) {
if (value && value.length > 10) {
throw Error('Maximum amount of grouped columns is 10.');
}
/** @type {?} */
const oldExpressions = this.groupingExpressions;
/** @type {?} */
const newExpressions = value;
this._groupingExpressions = cloneArray(value);
this.chipsGoupingExpressions = cloneArray(value);
if (this._gridAPI.grid) {
/* grouping should work in conjunction with sorting
and without overriding separate sorting expressions */
this._applyGrouping();
this._gridAPI.arrange_sorting_expressions();
this.cdr.markForCheck();
}
else {
// setter called before grid is registered in grid API service
this.sortingExpressions.unshift.apply(this.sortingExpressions, this._groupingExpressions);
}
if (JSON.stringify(oldExpressions) !== JSON.stringify(newExpressions) && this.columnList) {
/** @type {?} */
const groupedCols = [];
/** @type {?} */
const ungroupedCols = [];
/** @type {?} */
const groupedColsArr = newExpressions.filter((obj) => {
return !oldExpressions.some((obj2) => {
return obj.fieldName === obj2.fieldName;
});
});
groupedColsArr.forEach((elem) => {
groupedCols.push(this.getColumnByName(elem.fieldName));
}, this);
/** @type {?} */
const ungroupedColsArr = oldExpressions.filter((obj) => {
return !newExpressions.some((obj2) => {
return obj.fieldName === obj2.fieldName;
});
});
ungroupedColsArr.forEach((elem) => {
ungroupedCols.push(this.getColumnByName(elem.fieldName));
}, this);
this.cdr.detectChanges();
/** @type {?} */
const groupingDoneArgs = {
expressions: newExpressions,
groupedColumns: groupedCols,
ungroupedColumns: ungroupedCols
};
this.onGroupingDone.emit(groupingDoneArgs);
}
}
/**
* Returns a list of expansion states for group rows.
* Includes only states that differ from the default one (controlled through groupsExpanded and states that the user has changed.
* Contains the expansion state (expanded: boolean) and the unique identifier for the group row (Array).
* ```typescript
* const groupExpState = this.grid.groupingExpansionState;
* ```
* \@memberof IgxGridComponent
* @return {?}
*/
get groupingExpansionState() {
return this._groupingExpandState;
}
/**
* Sets a list of expansion states for group rows.
* ```typescript
* this.grid.groupingExpansionState = [{
* expanded: false,
* hierarchy: [{ fieldName: 'ID', value: 1 }]
* }];
* // You can use DataUtil.getHierarchy(groupRow) to get the group `IgxGridRowComponent` hierarchy.
* ```
* \@memberof IgxGridComponent
* @param {?} value
* @return {?}
*/
set groupingExpansionState(value) {
this._groupingExpandState = cloneArray(value);
this.cdr.detectChanges();
}
/**
* An \@Input property that sets whether the grouped columns should be hidden as well.
* The default value is "false"
* ```html
* <igx-grid #grid [data]="localData" [hideGroupedColumns]="true" [autoGenerate]="true"></igx-grid>
* ```
* \@memberof IgxGridComponent
* @return {?}
*/
get hideGroupedColumns() {
return this._hideGroupedColumns;
}
/**
* @param {?} value
* @return {?}
*/
set hideGroupedColumns(value) {
if (value) {
this.groupingDiffer = this.differs.find(this.groupingExpressions).create();
}
else {
this.groupingDiffer = null;
}
if (this.columnList && this.groupingExpressions) {
this._setGroupColsVisibility(value);
}
this._hideGroupedColumns = value;
}
/**
* An \@Input property that sets the message displayed inside the GroupBy drop area where columns can be dragged on.
* Note: The grid needs to have at least one groupable column in order the GroupBy area to be displayed.
* ```html
* <igx-grid dropAreaMessage="Drop here to group!">
* <igx-column [groupable]="true" field="ID"></igx-column>
* </igx-grid>
* ```
* \@memberof IgxGridComponent
* @param {?} value
* @return {?}
*/
set dropAreaMessage(value) {
this._dropAreaMessage = value;
}
/**
* An accessor that returns the message displayed inside the GroupBy drop area where columns can be dragged on.
* @return {?}
*/
get dropAreaMessage() {
return this._dropAreaMessage || this.resourceStrings.igx_grid_groupByArea_message;
}
/**
* A list of all group rows.
* ```typescript
* const groupList = this.grid.groupsRowList;
* ```
* \@memberof IgxGridComponent
* @return {?}
*/
get groupsRowList() {
/** @type {?} */
const res = new QueryList();
if (!this._groupsRowList) {
return res;
}
/** @type {?} */
const rList = this._groupsRowList.filter((item) => {
return item.element.nativeElement.parentElement !== null;
});
res.reset(rList);
return res;
}
/**
* @hidden
* @return {?}
*/
get groupAreaHostClass() {
return this.getComponentDensityClass('igx-drop-area');
}
/**
* Returns the template reference of the `IgxGridComponent`'s group row.
* ```
* const groupRowTemplate = this.grid.groupRowTemplate;
* ```
* \@memberof IgxGridComponent
* @return {?}
*/
get groupRowTemplate() {
return this._groupRowTemplate;
}
/**
* Sets the template reference of the `IgxGridComponent`'s group `IgxGridRowComponent`.
* ```typescript
* this.grid.groupRowTemplate = myRowTemplate.
* ```
* \@memberof IgxGridComponent
* @param {?} template
* @return {?}
*/
set groupRowTemplate(template) {
this._groupRowTemplate = template;
this.markForCheck();
}
/**
* Returns the template reference of the `IgxGridComponent`'s group area.
* ```typescript
* const groupAreaTemplate = this.grid.groupAreaTemplate;
* ```
* \@memberof IgxGridComponent
* @return {?}
*/
get groupAreaTemplate() {
return this._groupAreaTemplate;
}
/**
* Sets the template reference of the `IgxGridComponent`'s group area.
* ```typescript
* this.grid.groupAreaTemplate = myAreaTemplate.
* ```
* \@memberof IgxGridComponent
* @param {?} template
* @return {?}
*/
set groupAreaTemplate(template) {
this._groupAreaTemplate = template;
this.markForCheck();
}
/**
* Groups by a new `IgxColumnComponent` based on the provided expression, or modifies an existing one.
* Also allows for multiple columns to be grouped at once if an array of `ISortingExpression` is passed.
* The onGroupingDone event would get raised only **once** if this method gets called multiple times with the same arguments.
* ```typescript
* this.grid.groupBy({ fieldName: name, dir: SortingDirection.Asc, ignoreCase: false });
* this.grid.groupBy([
* { fieldName: name1, dir: SortingDirection.Asc, ignoreCase: false },
* { fieldName: name2, dir: SortingDirection.Desc, ignoreCase: true },
* { fieldName: name3, dir: SortingDirection.Desc, ignoreCase: false }
* ]);
* ```
* \@memberof IgxGridComponent
* @param {?} expression
* @return {?}
*/
groupBy(expression) {
this.endEdit(true);
this._gridAPI.submit_value();
if (expression instanceof Array) {
this._gridAPI.groupBy_multiple(expression);
}
else {
this._gridAPI.groupBy(expression);
}
this.cdr.detectChanges();
this.calculateGridSizes();
}
/**
* Clears all grouping in the grid, if no parameter is passed.
* If a parameter is provided, clears grouping for a particular column or an array of columns.
* ```typescript
* this.grid.clearGrouping(); //clears all grouping
* this.grid.clearGrouping("ID"); //ungroups a single column
* this.grid.clearGrouping(["ID", "Column1", "Column2"]); //ungroups multiple columns
* ```
*
* @param {?=} name
* @return {?}
*/
clearGrouping(name) {
this._gridAPI.clear_groupby(name);
this.calculateGridSizes();
}
/**
* Returns if a group is expanded or not.
* ```typescript
* public groupRow: IGroupByRecord;
* const expandedGroup = this.grid.isExpandedGroup(this.groupRow);
* ```
* \@memberof IgxGridComponent
* @param {?} group
* @return {?}
*/
isExpandedGroup(group) {
/** @type {?} */
const state = this._getStateForGroupRow(group);
return state ? state.expanded : this.groupsExpanded;
}
/**
* Toggles the expansion state of a group.
* ```typescript
* public groupRow: IGroupByRecord;
* const toggleExpGroup = this.grid.toggleGroup(this.groupRow);
* ```
* \@memberof IgxGridComponent
* @param {?} groupRow
* @return {?}
*/
toggleGroup(groupRow) {
this._toggleGroup(groupRow);
}
/**
* @hidden
* @param {?} record
* @return {?}
*/
isGroupByRecord(record) {
// return record.records instance of GroupedRecords fails under Webpack
return record.records && record.records.length;
}
/**
* Toggles the expansion state of all group rows recursively.
* ```typescript
* this.grid.toggleAllGroupRows;
* ```
* \@memberof IgxGridComponent
* @return {?}
*/
toggleAllGroupRows() {
this.groupingExpansionState = [];
this.groupsExpanded = !this.groupsExpanded;
this.cdr.detectChanges();
}
/**
* Returns if the `IgxGridComponent` has groupable columns.
* ```typescript
* const groupableGrid = this.grid.hasGroupableColumns;
* ```
* \@memberof IgxGridComponent
* @return {?}
*/
get hasGroupableColumns() {
return this.columnList.some((col) => col.groupable && !col.columnGroup);
}
/**
* @private
* @param {?} value
* @return {?}
*/
_setGroupColsVisibility(value) {
this.groupingExpressions.forEach((expr) => {
/** @type {?} */
const col = this.getColumnByName(expr.fieldName);
col.hidden = value;
});
}
/**
* Returns if the grid's group by drop area is visible.
* ```typescript
* const dropVisible = this.grid.dropAreaVisible;
* ```
* \@memberof IgxGridComponent
* @return {?}
*/
get dropAreaVisible() {
return (this.draggedColumn && this.draggedColumn.groupable) ||
!this.chipsGoupingExpressions.length;
}
/**
* @hidden
* @protected
* @param {?} groupRow
* @return {?}
*/
_getStateForGroupRow(groupRow) {
return this._gridAPI.groupBy_get_expanded_for_group(groupRow);
}
/**
* @hidden
* @protected
* @param {?} groupRow
* @return {?}
*/
_toggleGroup(groupRow) {
this._gridAPI.groupBy_toggle_group(groupRow);
}
/**
* @hidden
* @protected
* @return {?}
*/
_applyGrouping() {
this._gridAPI.sort_multiple(this._groupingExpressions);
}
/**
* @hidden
* @param {?} fieldName
* @return {?}
*/
isColumnGrouped(fieldName) {
return this.groupingExpressions.find(exp => exp.fieldName === fieldName) ? true : false;
}
/**
* @hidden
* @param {?} rowData
* @param {?} rowIndex
* @return {?}
*/
getContext(rowData, rowIndex) {
return {
$implicit: rowData,
index: rowIndex,
templateID: this.isGroupByRecord(rowData) ? 'groupRow' : this.isSummaryRow(rowData) ? 'summaryRow' : 'dataRow'
};
}
/**
* @hidden
* @return {?}
*/
get template() {
if (this.filteredData && this.filteredData.length === 0) {
return this.emptyGridTemplate ? this.emptyGridTemplate : this.emptyFilteredGridTemplate;
}
if (this.isLoading && (!this.data || this.dataLength === 0)) {
return this.loadingGridTemplate ? this.loadingGridTemplate : this.loadingGridDefaultTemplate;
}
if (this.dataLength === 0) {
return this.emptyGridTemplate ? this.emptyGridTemplate : this.emptyGridDefaultTemplate;
}
}
/**
* @hidden
* @protected
* @return {?}
*/
getGroupByRecords() {
if (this.groupingExpressions && this.groupingExpressions.length) {
/** @type {?} */
const state = {
expressions: this.groupingExpressions,
expansion: this.groupingExpansionState,
defaultExpanded: this.groupsExpanded
};
return DataUtil.group(cloneArray(this.filteredSortedData), state).metadata;
}
else {
return null;
}
}
/**
* @hidden
* @param {?} event
* @return {?}
*/
onChipRemoved(event) {
this.clearGrouping(event.owner.id);
}
/**
* @hidden
* @param {?} event
* @return {?}
*/
chipsOrderChanged(event) {
/** @type {?} */
const newGrouping = [];
for (let i = 0; i < event.chipsArray.length; i++) {
/** @type {?} */
const expr = this.groupingExpressions.filter((item) => {
return item.fieldName === event.chipsArray[i].id;
})[0];
if (!this.getColumnByName(expr.fieldName).groupable) {
// disallow changing order if there are columns with groupable: false
return;
}
newGrouping.push(expr);
}
this.groupingExpansionState = [];
this.chipsGoupingExpressions = newGrouping;
if (event.originalEvent instanceof KeyboardEvent) {
// When reordered using keyboard navigation, we don't have `onMoveEnd` event.
this.groupingExpressions = this.chipsGoupingExpressions;
}
this.markForCheck();
}
/**
* @hidden
* @return {?}
*/
chipsMovingEnded() {
this.groupingExpressions = this.chipsGoupingExpressions;
this.markForCheck();
}
/**
* @hidden
* @param {?} event
* @return {?}
*/
onChipClicked(event) {
/** @type {?} */
const sortingExpr = this.sortingExpressions;
/** @type {?} */
const columnExpr = sortingExpr.find((expr) => expr.fieldName === event.owner.id);
columnExpr.dir = 3 - columnExpr.dir;
this.sort(columnExpr);
this.markForCheck();
}
/**
* @hidden
* @param {?} event
* @return {?}
*/
onChipKeyDown(event) {
if (event.originalEvent.key === ' ' || event.originalEvent.key === 'Spacebar' || event.originalEvent.key === 'Enter') {
/** @type {?} */
const sortingExpr = this.sortingExpressions;
/** @type {?} */
const columnExpr = sortingExpr.find((expr) => expr.fieldName === event.owner.id);
columnExpr.dir = 3 - columnExpr.dir;
this.sort(columnExpr);
this.markForCheck();
}
}
/**
* @hidden
* @protected
* @return {?}
*/
getGroupAreaHeight() {
return this.groupArea ? this.groupArea.nativeElement.offsetHeight : 0;
}
/**
* Gets calculated width of the pinned area.
* ```typescript
* const pinnedWidth = this.grid.getPinnedWidth();
* ```
* \@memberof IgxGridComponent
* @param {?=} takeHidden If we should take into account the hidden columns in the pinned area.
* @return {?}
*/
getPinnedWidth(takeHidden = false) {
/** @type {?} */
let sum = super.getPinnedWidth(takeHidden);
if (this.groupingExpressions.length > 0 && this.headerGroupContainer) {
sum += this.headerGroupContainer.nativeElement.offsetWidth;
}
return sum;
}
/**
* @hidden
* @protected
* @param {?} row
* @param {?} column
* @return {?}
*/
scrollTo(row, column) {
if (this.groupingExpressions && this.groupingExpressions.length
&& typeof (row) !== 'number') {
/** @type {?} */
const groupByRecords = this.getGroupByRecords();
/** @type {?} */
const rowIndex = this.filteredSortedData.indexOf(row);
/** @type {?} */
const groupByRecord = groupByRecords[rowIndex];
if (groupByRecord && !this.isExpandedGroup(groupByRecord)) {
this.toggleGroup(groupByRecord);
}
}
super.scrollTo(row, column);
}
/**
* @hidden
* @return {?}
*/
get dropAreaTemplateResolved() {
if (this.dropAreaTemplate) {
return this.dropAreaTemplate;
}
else {
return this.defaultDropAreaTemplate;
}
}
/**
* @hidden
* @param {?} expression
* @return {?}
*/
getGroupByChipTitle(expression) {
return this.getColumnByName(expression.fieldName).header || expression.fieldName;
}
/**
* @hidden
* @return {?}
*/
ngAfterContentInit() {
if (this.groupTemplate) {
this._groupRowTemplate = this.groupTemplate.template;
}
super.ngAfterContentInit();
if (this.hideGroupedColumns && this.columnList && this.groupingExpressions) {
this._setGroupColsVisibility(this.hideGroupedColumns);
}
}
/**
* @return {?}
*/
ngOnInit() {
super.ngOnInit();
this.onGroupingDone.pipe(takeUntil(this.destroy$)).subscribe((args) => {
this.endEdit(true);
this.summaryService.updateSummaryCache(args);
});
}
/**
* @return {?}
*/
ngDoCheck() {
super.ngDoCheck();
if (this.groupingDiffer) {
/** @type {?} */
const changes = this.groupingDiffer.diff(this.groupingExpressions);
if (changes && this.columnList) {
changes.forEachAddedItem((rec) => {
/** @type {?} */
const col = this.getColumnByName(rec.item.fieldName);
col.hidden = true;
});
changes.forEachRemovedItem((rec) => {
/** @type {?} */
const col = this.getColumnByName(rec.item.fieldName);
col.hidden = false;
});
}
}
}
/**
* @return {?}
*/
getSelectedData() {
if (this.groupingExpressions.length) {
/** @type {?} */
const source = [];
/** @type {?} */
const process = (record) => {
if (record.expression || record.summaries) {
source.push(null);
return;
}
source.push(record);
};
this.verticalScrollContainer.igxForOf.forEach(process);
return this.extractDataFromSelection(source);
}
else {
return super.getSelectedData();
}
}
}
IgxGridComponent.decorators = [
{ type: Component, args: [{
changeDetection: ChangeDetectionStrategy.OnPush,
preserveWhitespaces: false,
providers: [IgxGridNavigationService, IgxGridSummaryService, IgxGridSelectionService, IgxGridCRUDService,
{ provide: GridBaseAPIService, useClass: IgxGridAPIService },
{ provide: IgxGridBaseComponent, useExisting: forwardRef(() => IgxGridComponent) },
IgxFilteringService, IgxColumnResizingService, IgxForOfSyncService
],
selector: 'igx-grid',
template: "<igx-grid-toolbar [style.width.px]=\"outerWidth\" role=\"rowgroup\" *ngIf=\"showToolbar\" [gridID]=\"id\" [displayDensity]=\"displayDensity\" #toolbar>\n</igx-grid-toolbar>\n\n<ng-template #defaultPager let-api>\n <button [disabled]=\"api.isFirstPage\" (click)=\"api.paginate(0)\" igxButton=\"icon\" igxRipple igxRippleCentered=\"true\">\n <igx-icon fontSet=\"material\">first_page</igx-icon>\n </button>\n <button [disabled]=\"api.isFirstPage\" (click)=\"api.previousPage()\" igxButton=\"icon\" igxRipple igxRippleCentered=\"true\">\n <igx-icon fontSet=\"material\">chevron_left</igx-icon>\n </button>\n <span>{{ api.page + 1 }} of {{ api.totalPages }}</span>\n <button [disabled]=\"api.isLastPage\" (click)=\"api.nextPage()\" igxRipple igxRippleCentered=\"true\" igxButton=\"icon\">\n <igx-icon fontSet=\"material\">chevron_right</igx-icon>\n </button>\n <button [disabled]=\"api.isLastPage\" (click)=\"api.paginate(api.totalPages - 1)\" igxButton=\"icon\" igxRipple igxRippleCentered=\"true\">\n <igx-icon fontSet=\"material\">last_page</igx-icon>\n </button>\n <select style=\"margin-left: 1rem;\" (change)=\"api.perPage = $event.target.value\">\n <option [value]=\"val\" [selected]=\"api.perPage == val\" *ngFor=\"let val of [5, 10, 15, 25, 50, 100, 500]\">{{ val }}</option>\n </select>\n</ng-template>\n\n<div [style.width.px]='outerWidth' class=\"igx-grid__grouparea\" *ngIf=\"groupingExpressions.length > 0 || hasGroupableColumns\" #groupArea>\n <igx-chips-area (onReorder)=\"chipsOrderChanged($event)\" (onMoveEnd)=\"chipsMovingEnded()\">\n <ng-container *ngFor=\"let expr of chipsGoupingExpressions; let last = last;\">\n <igx-chip [id]=\"expr.fieldName\" [attr.title]=\"getGroupByChipTitle(expr)\" [removable]=\"getColumnByName(expr.fieldName).groupable\" [draggable]=\"getColumnByName(expr.fieldName).groupable\" [displayDensity]=\"displayDensity\"\n (onKeyDown)=\"onChipKeyDown($event)\" (onRemove)=\"onChipRemoved($event)\" (onClick)=\"getColumnByName(expr.fieldName).groupable ? onChipClicked($event): null\" [disabled]='!getColumnByName(expr.fieldName).groupable'>\n <span>{{ getGroupByChipTitle(expr) }}</span>\n <igx-icon igxSuffix>{{ expr.dir == 1 ? 'arrow_upward' : 'arrow_downward' }}</igx-icon>\n </igx-chip>\n <span class=\"igx-grid__grouparea-connector\">\n <igx-icon [style.visibility]=\"(!last || dropAreaVisible) ? 'visible' : 'hidden'\" >arrow_forward</igx-icon>\n </span>\n </ng-container>\n <div igxGroupAreaDrop [style.visibility]=\"dropAreaVisible ? 'visible' : 'hidden'\" [class]=\"groupAreaHostClass\" [attr.gridId]='this.id'>\n <ng-container *ngTemplateOutlet=\"dropAreaTemplateResolved\"></ng-container>\n </div>\n </igx-chips-area>\n</div>\n\n<div class=\"igx-grid__thead\">\n <div class=\"igx-grid__thead-wrapper\" role=\"rowgroup\" [style.width.px]='calcWidth + 1' #theadRow>\n <div class=\"igx-grid__tr\" role=\"row\" [style.width.px]='calcWidth + 1'>\n <span *ngIf=\"hasMovableColumns && draggedColumn && pinnedColumns.length <= 0\" [igxColumnMovingDrop]=\"parentVirtDir\" [attr.droppable]=\"true\" id=\"left\" class=\"igx-grid__scroll-on-drag-left\" [style.left.px]=\"headerCheckboxWidth\"></span>\n <span *ngIf=\"hasMovableColumns && draggedColumn && pinnedColumns.length > 0\" [igxColumnMovingDrop]=\"parentVirtDir\" [attr.droppable]=\"true\" id=\"left\" class=\"igx-grid__scroll-on-drag-pinned\" [style.left.px]=\"pinnedWidth\"></span>\n <ng-container *ngIf=\"groupingExpressions.length > 0\">\n <div class=\"igx-grid__header-indentation igx-grid__row-indentation--level-{{groupingExpressions.length}}\" #headerGroupContainer>\n <igx-icon *ngIf=\"groupsExpanded\" role=\"button\" class=\"igx-grid__group-expand-btn\" (click)=\"toggleAllGroupRows()\" [ngClass]=\"{\n 'igx-grid__group-expand-btn--push': filteringService.isFilterRowVisible\n }\">unfold_less</igx-icon>\n <igx-icon *ngIf=\"!groupsExpanded\" role=\"button\" class=\"igx-grid__group-expand-btn\" (click)=\"toggleAllGroupRows()\"[ngClass]=\"{\n 'igx-grid__group-expand-btn--push': filteringService.isFilterRowVisible\n }\">unfold_more</igx-icon>\n </div>\n </ng-container>\n <ng-container *ngIf=\"showRowCheckboxes\">\n <div class=\"igx-grid__cbx-selection\" #headerCheckboxContainer [ngClass]=\"{\n 'igx-grid__cbx-selection--push': filteringService.isFilterRowVisible\n }\">\n <igx-checkbox [checked]=\"allRowsSelected\" (change)=\"onHeaderCheckboxClick($event, filteredData)\" disableRipple=\"true\" [aria-label]=\"headerCheckboxAriaLabel\" #headerCheckbox></igx-checkbox>\n </div>\n </ng-container>\n <ng-container *ngIf=\"pinnedColumns.length > 0\">\n <ng-template ngFor let-col [ngForOf]=\"pinnedColumns | igxTopLevel\">\n <igx-grid-header-group [column]=\"col\" [gridID]=\"id\" [style.min-width.px]=\"getHeaderGroupWidth(col)\" [style.flex-basis.px]=\"getHeaderGroupWidth(col)\"></igx-grid-header-group>\n </ng-template>\n </ng-container>\n <ng-template igxGridFor let-col [igxGridForOf]=\"unpinnedColumns | igxTopLevel\" [igxForScrollOrientation]=\"'horizontal'\" [igxForScrollContainer]=\"parentVirtDir\"\n [igxForContainerSize]='unpinnedWidth' [igxForTrackBy]='trackColumnChanges' [igxForSizePropName]='\"calcWidth\"' #headerContainer>\n <igx-grid-header-group [column]=\"col\" [gridID]=\"id\" [style.min-width.px]=\"getHeaderGroupWidth(col)\" [style.flex-basis.px]=\"getHeaderGroupWidth(col)\"></igx-grid-header-group>\n </ng-template>\n </div>\n <igx-grid-filtering-row #filteringRow [style.width.px]='calcWidth' *ngIf=\"filteringService.isFilterRowVisible\" [column]=\"filteringService.filteredColumn\"></igx-grid-filtering-row>\n </div>\n <span *ngIf=\"hasMovableColumns && draggedColumn\" [igxColumnMovingDrop]=\"parentVirtDir\" [attr.droppable]=\"true\" id=\"right\" class=\"igx-grid__scroll-on-drag-right\"></span>\n <div class=\"igx-grid__thead-thumb\" [hidden]='!hasVerticalSroll()' [style.width.px]=\"scrollWidth\"></div>\n</div>\n\n<div igxGridBody class=\"igx-grid__tbody\">\n <div class=\"igx-grid__tbody-content\" role=\"rowgroup\" (onDragStop)=\"selectionService.dragMode = $event\" (onDragScroll)=\"dragScroll($event)\" [igxGridDragSelect]=\"selectionService.dragMode\" [style.height.px]='calcHeight' [style.width.px]='calcWidth + 1' #tbody (scroll)='scrollHandler($event)' (wheel)=\"wheelHandler()\">\n <span *ngIf=\"hasMovableColumns && draggedColumn && pinnedColumns.length <= 0\" [igxColumnMovingDrop]=\"parentVirtDir\" [attr.droppable]=\"true\" id=\"left\" class=\"igx-grid__scroll-on-drag-left\"></span>\n <span *ngIf=\"hasMovableColumns && draggedColumn && pinnedColumns.length > 0\" [igxColumnMovingDrop]=\"parentVirtDir\" [attr.droppable]=\"true\" id=\"left\" class=\"igx-grid__scroll-on-drag-pinned\" [style.left.px]=\"pinnedWidth\"></span>\n <ng-template igxGridFor let-rowData [igxGridForOf]=\"data\n | gridTransaction:id:pipeTrigger\n | gridFiltering:filteringExpressionsTree:id:pipeTrigger\n | gridSort:sortingExpressions:id:pipeTrigger\n | gridPreGroupBy:groupingExpressions:groupingExpansionState:groupsExpanded:id:groupsRecords:pipeTrigger\n | gridPaging:page:perPage:id:pipeTrigger\n | gridPostGroupBy:groupingExpressions:groupingExpansionState:groupsExpanded:id:pipeTrigger\n | gridSummary:hasSummarizedColumns:summaryCalculationMode:summaryPosition:id:pipeTrigger:summaryPipeTrigger\"\n let-rowIndex=\"index\" [igxForScrollOrientation]=\"'vertical'\" [igxForScrollContainer]='verticalScroll'\n [igxForContainerSize]='calcHeight' [igxForItemSize]=\"rowHeight\" #verticalScrollContainer (onChunkPreload)=\"dataLoading($event)\">\n <ng-template #record_template>\n <igx-grid-row [gridID]=\"id\" [index]=\"rowIndex\" [rowData]=\"rowData\" #row>\n </igx-grid-row>\n </ng-template>\n <ng-template #group_template>\n <igx-grid-groupby-row [gridID]=\"id\" [index]=\"rowIndex\" [groupRow]=\"rowData\" #row>\n </igx-grid-groupby-row>\n </ng-template>\n <ng-template #summary_template>\n <igx-grid-summary-row [gridID]=\"id\" [summaries]=\"rowData.summaries\" [indentation]=\"groupingExpressions.length\" [index]=\"rowIndex\" class=\"igx-grid__summaries--body\" #summaryRow>\n </igx-grid-summary-row>\n </ng-template>\n <ng-template [igxTemplateOutlet]='isGroupByRecord(rowData) ? group_template : isSummaryRow(rowData) ? summary_template : record_template'\n [igxTemplateOutletContext]='getContext(rowData, rowIndex)'\n (onCachedViewLoaded)='cachedViewLoaded($event)'>\n </ng-template>\n </ng-template>\n <ng-container *ngTemplateOutlet=\"template\"></ng-container>\n <div class=\"igx-grid__row-editing-outlet\" igxOverlayOutlet #igxRowEditingOverlayOutlet></div>\n </div>\n <span *ngIf=\"hasMovableColumns && draggedColumn\" [igxColumnMovingDrop]=\"parentVirtDir\" [attr.droppable]=\"true\" id=\"right\" class=\"igx-grid__scroll-on-drag-right\"></span>\n <div [hidden]='!hasVerticalSroll()' class=\"igx-grid__tbody-scrollbar\" [style.width.px]=\"scrollWidth\" [style.height.px]='calcHeight'>\n <ng-template igxGridFor [igxGridForOf]='[]' #verticalScrollHolder ></ng-template>\n </div>\n</div>\n\n\n<div class=\"igx-grid__tfoot\" role=\"rowgroup\" [style.height.px]='summariesHeight' #tfoot>\n <igx-grid-summary-row [style.width.px]='calcWidth' [style.height.px]='summariesHeight' *ngIf=\"hasSummarizedColumns && rootSummariesEnabled\" [gridID]=\"id\" [summaries]=\"id | igxGridSummaryDataPipe:summaryService.retriggerRootPipe\" [indentation]=\"groupingExpressions.length\" [index]=\"0\" class=\"igx-grid__summaries\" #summaryRow>\n </igx-grid-summary-row>\n <div class=\"igx-grid__tfoot-thumb\" [hidden]='!hasVerticalSroll()' [style.height.px]='summariesHeight' [style.width.px]=\"scrollWidth\"></div>\n</div>\n\n<div class=\"igx-grid__scroll\" [style.height]=\"'18px'\" #scr [hidden]=\"unpinnedWidth - totalWidth >= 0\">\n <div class=\"igx-grid__scroll-start\" [style.width.px]='pinnedWidth' [hidden]=\"pinnedWidth === 0\"></div>\n <div class=\"igx-grid__scroll-main\" [style.width.px]='unpinnedWidth'>\n <ng-template igxGridFor [igxGridForOf]='[]' #scrollContainer>\n </ng-template>\n </div>\n</div>\n\n<div class=\"igx-paginator igx-grid-paginator\" *ngIf=\"paging && totalRecords\" #paginator>\n <ng-container *ngTemplateOutlet=\"paginationTemplate ? paginationTemplate : defaultPager; context: { $implicit: this }\">\n </ng-container>\n</div>\n\n<ng-template #emptyFilteredGrid>\n <span class=\"igx-grid__tbody-message\">{{emptyFilteredGridMessage}}</span>\n</ng-template>\n\n<ng-template #defaultEmptyGrid>\n <span class=\"igx-grid__tbody-message\">{{emptyGridMessage}}</span>\n</ng-template>\n\n<ng-template #defaultLoadingGrid>\n <div class=\"igx-grid__loading\">\n <igx-circular-bar [indeterminate]=\"true\">\n </igx-circular-bar>\n </div>\n</ng-template>\n\n<ng-template #defaultDropArea>\n <igx-icon fontSet=\"material\" class=\"igx-drop-area__icon\">group_work</igx-icon>\n <span class=\"igx-drop-area__text\">{{dropAreaMessage}}</span>\n</ng-template>\n\n<div *ngIf=\"rowEditable\" igxToggle>\n <div [className]=\"bannerClass\">\n <ng-container *ngTemplateOutlet=\"rowEditContainer; context: { rowChangesCount: rowChangesCount, endEdit: endEdit.bind(this) }\"></ng-container>\n </div>\n</div>\n\n<ng-template #defaultRowEditText>\n You have {{ rowChangesCount }} changes in this row\n</ng-template>\n\n<ng-template #defaultRowEditActions>\n <button igxButton igxRowEditTabStop (click)=\"endEdit(false, $event)\">Cancel</button>\n <button igxButton igxRowEditTabStop (click)=\"endEdit(true, $event)\">Done</button>\n</ng-template>\n\n<ng-template #defaultRowEditTemplate>\n <div class=\"igx-banner__message\">\n <span class=\"igx-banner__text\">\n <ng-container *ngTemplateOutlet=\"rowEditText ? rowEditText : defaultRowEditText; context: { $implicit: rowChangesCount }\"></ng-container>\n </span>\n </div>\n <div class=\"igx-banner__actions\">\n <div class=\"igx-banner__row\">\n <ng-container *ngTemplateOutlet=\"rowEditActions ? rowEditActions : defaultRowEditActions; context: { $implicit: endEdit.bind(this) }\"></ng-container>\n </div>\n </div>\n</ng-template>\n<igx-grid-column-resizer *ngIf=\"colResizingService.showResizer\"></igx-grid-column-resizer>\n<div class=\"igx-grid__outlet\" #igxFilteringOverlayOutlet igxOverlayOutlet></div>\n"
}] }
];
/** @nocollapse */
IgxGridComponent.ctorParameters = () => [
{ type: IgxGridSelectionService },
{ type: IgxGridCRUDService },
{ type: IgxColumnResizingService },
{ type: GridBaseAPIService },
{ type: IgxSelectionAPIService },
{ type: undefined, decorators: [{ type: Inject, args: [IgxGridTransaction,] }] },
{ type: ElementRef },
{ type: NgZone },
{ type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] },
{ type: ChangeDetectorRef },
{ type: ComponentFactoryResolver },
{ type: IterableDiffers },
{ type: ViewContainerRef },
{ type: IgxGridNavigationService },
{ type: IgxFilteringService },
{ type: IgxOverlayService, decorators: [{ type: Inject, args: [IgxOverlayService,] }] },
{ type: IgxGridSummaryService },
{ type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [DisplayDensityToken,] }] }
];
IgxGridComponent.propDecorators = {
id: [{ type: HostBinding, args: ['attr.id',] }, { type: Input }],
data: [{ type: Input }],
groupingExpressions: [{ type: Input }],
groupingExpansionState: [{ type: Input }],
groupsExpanded: [{ type: Input }],
hideGroupedColumns: [{ type: Input }],
dropAreaMessage: [{ type: Input }],
dropAreaTemplate: [{ type: Input }],
onGroupingDone: [{ type: Output }],
onFocusChange: [{ type: Output }],
groupTemplate: [{ type: ContentChild, args: [IgxGroupByRowTemplateDirective, { read: IgxGroupByRowTemplateDirective },] }],
_groupsRowList: [{ type: ViewChildren, args: [IgxGridGroupByRowComponent, { read: IgxGridGroupByRowComponent },] }],
defaultDropAreaTemplate: [{ type: ViewChild, args: ['defaultDropArea', { read: TemplateRef },] }],
groupArea: [{ type: ViewChild, args: ['groupArea',] }]
};
if (false) {
/**
* @type {?}
* @private
*/
IgxGridComponent.prototype._id;
/**
* @hidden
* @type {?}
* @protected
*/
IgxGridComponent.prototype._groupingExpressions;
/**
* @hidden
* @type {?}
* @protected
*/
IgxGridComponent.prototype._groupingExpandState;
/**
* @hidden
* @type {?}
* @protected
*/
IgxGridComponent.prototype._groupRowTemplate;
/**
* @hidden
* @type {?}
* @protected
*/
IgxGridComponent.prototype._groupAreaTemplate;
/**
* @hidden
* @type {?}
* @protected
*/
IgxGridComponent.prototype.groupingDiffer;
/**
* @type {?}
* @private
*/
IgxGridComponent.prototype._data;
/**
* @type {?}
* @private
*/
IgxGridComponent.prototype._hideGroupedColumns;
/**
* @type {?}
* @private
*/
IgxGridComponent.prototype._dropAreaMessage;
/**
* @type {?}
* @private
*/
IgxGridComponent.prototype._gridAPI;
/**
* @type {?}
* @private
*/
IgxGridComponent.prototype._filteredData;
/**
* An \@Input property that determines whether created groups are rendered expanded or collapsed.
* The default rendered state is expanded.
* ```html
* <igx-grid #grid [data]="Data" [groupsExpanded]="false" [autoGenerate]="true"></igx-grid>
* ```
* \@memberof IgxGridComponent
* @type {?}
*/
IgxGridComponent.prototype.groupsExpanded;
/**
* A hierarchical representation of the group by records.
* ```typescript
* let groupRecords = this.grid.groupsRecords;
* ```
* \@memberof IgxGridComponent
* @type {?}
*/
IgxGridComponent.prototype.groupsRecords;
/**
* An \@Input property that sets the template that will be rendered as a GroupBy drop area.
* Note: The grid needs to have at least one groupable column in order the GroupBy area to be displayed.
* ```html
* <igx-grid [dropAreaTemplate]="dropAreaRef">
* <igx-column [groupable]="true" field="ID"></igx-column>
* </igx-grid>
*
* <ng-template #myDropArea>
* <span> Custom drop area! </span>
* </ng-template>
* ```
* ```ts
* \@ViewChild('myDropArea', { read: TemplateRef })
* public dropAreaRef: TemplateRef<any>;
* ```
* \@memberof IgxGridComponent
* @type {?}
*/
IgxGridComponent.prototype.dropAreaTemplate;
/**
* Emitted when a new `IgxColumnComponent` gets grouped/ungrouped, or multiple columns get
* grouped/ungrouped at once by using the Group By API.
* The `onGroupingDone` event would be raised only once if several columns get grouped at once by calling
* the `groupBy()` or `clearGrouping()` API methods and passing an array as an argument.
* The event arguments provide the `expressions`, `groupedColumns` and `ungroupedColumns` properties, which contain
* the `ISortingExpression` and the `IgxColumnComponent` related to the grouping/ungrouping operation.
* Please note that `groupedColumns` and `ungroupedColumns` show only the **newly** changed columns (affected by the **last**
* grouping/ungrouping operation), not all columns which are currently grouped/ungrouped.
* columns.
* ```typescript
* groupingDone(event: IGroupingDoneEventArgs){
* const expressions = event.expressions;
* //the newly grouped columns
* const groupedColumns = event.groupedColumns;
* //the newly ungrouped columns
* const ungroupedColumns = event.ungroupedColumns;
* }
* ```
* ```html
* <igx-grid #grid [data]="localData" (onGroupingDone)="groupingDone($event)" [autoGenerate]="true"></igx-grid>
* ```
* \@memberof IgxGridComponent
* @type {?}
*/
IgxGridComponent.prototype.onGroupingDone;
/** @type {?} */
IgxGridComponent.prototype.onFocusChange;
/**
* @hidden
* @type {?}
* @protected
*/
IgxGridComponent.prototype.groupTemplate;
/**
* @type {?}
* @private
*/
IgxGridComponent.prototype._groupsRowList;
/**
* @hidden
* @type {?}
*/
IgxGridComponent.prototype.defaultDropAreaTemplate;
/**
* @hidden
* @type {?}
*/
IgxGridComponent.prototype.groupArea;
/** @type {?} */
IgxGridComponent.prototype.colResizingService;
/** @type {?} */
IgxGridComponent.prototype.document;
/**
* @type {?}
* @protected
*/
IgxGridComponent.prototype.overlayServi