UNPKG

igniteui-angular

Version:

Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps

1,085 lines • 113 kB
/** * @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