UNPKG

@catull/igniteui-angular

Version:

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

1,227 lines 642 kB
import { __decorate, __metadata, __param } from "tslib"; import { DOCUMENT } from '@angular/common'; import { AfterContentInit, AfterViewInit, ChangeDetectorRef, ComponentFactoryResolver, ContentChildren, ContentChild, ElementRef, EventEmitter, HostBinding, Inject, Input, IterableChangeRecord, IterableDiffers, NgZone, OnDestroy, OnInit, Output, QueryList, TemplateRef, ViewChild, ViewChildren, ViewContainerRef, InjectionToken, Optional, DoCheck, Directive } from '@angular/core'; import ResizeObserver from 'resize-observer-polyfill'; import { Subject, combineLatest, pipe } from 'rxjs'; import { takeUntil, first, filter, throttleTime, map } from 'rxjs/operators'; import { cloneArray, isEdge, isNavigationKey, flatten, mergeObjects, isIE } from '../core/utils'; import { DataType } from '../data-operations/data-util'; import { FilteringLogic } from '../data-operations/filtering-expression.interface'; import { IgxGridForOfDirective } from '../directives/for-of/for_of.directive'; import { IgxTextHighlightDirective } from '../directives/text-highlight/text-highlight.directive'; import { AbsoluteScrollStrategy, HorizontalAlignment, VerticalAlignment, IgxOverlayService, OverlaySettings, PositionSettings, ConnectedPositioningStrategy, ContainerPositionStrategy } from '../services/index'; import { GridBaseAPIService } from './api.service'; import { RowEditPositionStrategy } from './grid.common'; import { IgxGridToolbarComponent } from './toolbar/grid-toolbar.component'; import { IgxRowDirective } from './row.directive'; import { IgxOverlayOutletDirective, IgxToggleDirective } from '../directives/toggle/toggle.directive'; import { FilteringExpressionsTree, FilteringExpressionsTreeType } from '../data-operations/filtering-expressions-tree'; import { TransactionType } from '../services/index'; import { IgxRowEditTemplateDirective, IgxRowEditTabStopDirective, IgxRowEditTextDirective, IgxRowEditActionsDirective } from './grid.rowEdit.directive'; import { IgxGridNavigationService } from './grid-navigation.service'; import { DisplayDensityToken, DisplayDensityBase, DisplayDensity } from '../core/displayDensity'; import { IgxFilteringService } from './filtering/grid-filtering.service'; import { WatchChanges } from './watch-changes'; import { IgxGridHeaderGroupComponent } from './headers/grid-header-group.component'; import { CurrentResourceStrings } from '../core/i18n/resources'; import { IgxGridSummaryService } from './summaries/grid-summary.service'; import { IgxSummaryRowComponent } from './summaries/summary-row.component'; import { IgxGridSelectionService, GridSelectionRange, IgxGridCRUDService, IgxRow, IgxCell, isChromium } from './selection/selection.service'; import { DragScrollDirection } from './selection/drag-select.directive'; import { IgxTemplateOutletDirective } from '../directives/template-outlet/template_outlet.directive'; import { IgxExcelStyleLoadingValuesTemplateDirective } from './filtering/excel-style/excel-style-search.component'; import { IgxExcelStyleSortingTemplateDirective, IgxExcelStylePinningTemplateDirective, IgxExcelStyleHidingTemplateDirective, IgxExcelStyleMovingTemplateDirective } from './filtering/excel-style/grid.excel-style-filtering.component'; import { IgxGridColumnResizerComponent } from './resizing/resizer.component'; import { IgxGridFilteringRowComponent } from './filtering/base/grid-filtering-row.component'; import { CharSeparatedValueData } from '../services/csv/char-separated-value-data'; import { IgxColumnResizingService } from './resizing/resizing.service'; import { DeprecateProperty } from '../core/deprecateDecorators'; import { IgxRowExpandedIndicatorDirective, IgxRowCollapsedIndicatorDirective, IgxHeaderExpandIndicatorDirective, IgxHeaderCollapseIndicatorDirective } from './grid/grid.directives'; import { GridKeydownTargetType, GridSelectionMode, GridSummaryPosition, GridSummaryCalculationMode, FilterMode } from './common/enums'; import { IgxAdvancedFilteringDialogComponent } from './filtering/advanced-filtering/advanced-filtering-dialog.component'; import { IgxDecimalPipeComponent, IgxDatePipeComponent } from './common/pipes'; import { DropPosition } from './moving/moving.service'; import { IgxHeadSelectorDirective, IgxRowSelectorDirective } from './selection/row-selectors'; import { IgxGridToolbarCustomContentDirective } from './toolbar/toolbar.directive'; import { IgxColumnComponent } from './columns/column.component'; import { IgxColumnGroupComponent } from './columns/column-group.component'; import { IgxRowDragGhostDirective, IgxDragIndicatorIconDirective } from './row-drag.directive'; const MINIMUM_COLUMN_WIDTH = 136; const FILTER_ROW_HEIGHT = 50; // By default row editing overlay outlet is inside grid body so that overlay is hidden below grid header when scrolling. // In cases when grid has 1-2 rows there isn't enough space in grid body and row editing overlay should be shown above header. // Default row editing overlay height is higher then row height that is why the case is valid also for row with 2 rows. // More accurate calculation is not possible, cause row editing overlay is still not shown and we don't know its height, // but in the same time we need to set row editing overlay outlet before opening the overlay itself. const MIN_ROW_EDITING_COUNT_THRESHOLD = 2; export const IgxGridTransaction = new InjectionToken('IgxGridTransaction'); let IgxGridBaseDirective = class IgxGridBaseDirective extends DisplayDensityBase { constructor(selectionService, crudService, colResizingService, gridAPI, _transactions, elementRef, zone, document, cdr, resolver, differs, viewRef, navigation, filteringService, overlayService, summaryService, _displayDensityOptions) { super(_displayDensityOptions); this.selectionService = selectionService; this.crudService = crudService; this.colResizingService = colResizingService; this.gridAPI = gridAPI; this._transactions = _transactions; this.elementRef = elementRef; this.zone = zone; this.document = document; this.cdr = cdr; this.resolver = resolver; this.differs = differs; this.viewRef = viewRef; this.navigation = navigation; this.filteringService = filteringService; this.overlayService = overlayService; this.summaryService = summaryService; this._displayDensityOptions = _displayDensityOptions; this._init = true; this._cdrRequests = false; this._cdrRequestRepaint = false; this._resourceStrings = CurrentResourceStrings.GridResStrings; this._emptyGridMessage = null; this._emptyFilteredGridMessage = null; this._isLoading = false; this._locale = null; this._destroyed = false; this.overlayIDs = []; this._advancedFilteringPositionSettings = { verticalDirection: VerticalAlignment.Middle, horizontalDirection: HorizontalAlignment.Center, horizontalStartPoint: HorizontalAlignment.Center, verticalStartPoint: VerticalAlignment.Middle }; this._advancedFilteringOverlaySettings = { closeOnOutsideClick: false, modal: false, positionStrategy: new ConnectedPositioningStrategy(this._advancedFilteringPositionSettings), }; /** * An @Input property that autogenerates the `IgxGridComponent` columns. * The default value is false. * ```html * <igx-grid [data]="Data" [autoGenerate]="true"></igx-grid> * ``` * @memberof IgxGridBaseDirective */ this.autoGenerate = false; /** * Emitted after filtering is performed. * Returns the filtering expressions tree of the column for which filtering was performed. * ```typescript * filteringExprTreeChange(event: IFilteringExpressionsTree){ * const filteringTree = event; * } * ``` * ```html * <igx-grid #grid [data]="localData" [height]="'305px'" [autoGenerate]="true" * (filteringExpressionsTreeChange)="filteringExprTreeChange($event)"></igx-grid> * ``` * @memberof IgxGridBaseDirective */ this.filteringExpressionsTreeChange = new EventEmitter(); /** * Emitted after advanced filtering is performed. * Returns the advanced filtering expressions tree. * ```typescript * advancedFilteringExprTreeChange(event: IFilteringExpressionsTree){ * const filteringTree = event; * } * ``` * ```html * <igx-grid #grid [data]="localData" [height]="'305px'" [autoGenerate]="true" * (advancedFilteringExpressionsTreeChange)="advancedFilteringExprTreeChange($event)"></igx-grid> * ``` * @memberof IgxGridBaseDirective */ this.advancedFilteringExpressionsTreeChange = new EventEmitter(); /** *@hidden */ this.pageChange = new EventEmitter(); /** *@hidden */ this.perPageChange = new EventEmitter(); /** * @hidden * @internal */ this.rowDragging = false; /** * An @Input property that adds styling classes applied to all even `IgxGridRowComponent`s in the grid. * ```html * <igx-grid #grid [data]="Data" [evenRowCSS]="'igx-grid--my-even-class'" [autoGenerate]="true"></igx-grid> * ``` * @memberof IgxGridBaseDirective */ this.evenRowCSS = 'igx-grid__tr--even'; /** * An @Input property that adds styling classes applied to all odd `IgxGridRowComponent`s in the grid. * ```html * <igx-grid #grid [data]="Data" [evenRowCSS]="'igx-grid--my-odd-class'" [autoGenerate]="true"></igx-grid> * ``` * @memberof IgxGridBaseDirective */ this.oddRowCSS = 'igx-grid__tr--odd'; /** * An @Input property that sets the title to be displayed in the built-in column hiding UI. * ```html * <igx-grid [showToolbar]="true" [columnHiding]="true" columnHidingTitle="Column Hiding"></igx-grid> * ``` * @memberof IgxGridBaseDirective */ this.columnHidingTitle = ''; /** * An @Input property that sets the title to be displayed in the UI of the column pinning. * ```html * <igx-grid #grid [data]="localData" [columnPinning]="'true" [columnPinningTitle]="'Column Hiding'" [autoGenerate]="true"></igx-grid> * ``` * @memberof IgxGridBaseDirective */ this.columnPinningTitle = ''; /** * Emitted when `IgxGridCellComponent` is clicked. Returns the `IgxGridCellComponent`. * ```html * <igx-grid #grid (onCellClick)="onCellClick($event)" [data]="localData" [height]="'305px'" [autoGenerate]="true"></igx-grid> * ``` * ```typescript * public onCellClick(e){ * alert("The cell has been clicked!"); * } * ``` * @memberof IgxGridBaseDirective */ this.onCellClick = new EventEmitter(); /** * Emitted when `IgxGridCellComponent` is selected. Returns the `IgxGridCellComponent`. * ```html * <igx-grid #grid (onSelection)="onCellSelect($event)" [data]="localData" [height]="'305px'" [autoGenerate]="true"></igx-grid> * ``` * ```typescript * public onCellSelect(e){ * alert("The cell has been selected!"); * } * ``` * @memberof IgxGridBaseDirective */ this.onSelection = new EventEmitter(); /** * Emitted when `IgxGridRowComponent` is selected. * ```html * <igx-grid #grid (onRowSelectionChange)="onCellClickChange($event)" [data]="localData" [autoGenerate]="true"></igx-grid> * ``` * ```typescript * public onCellClickChange(e){ * alert("The selected row has been changed!"); * } * ``` * @memberof IgxGridBaseDirective */ this.onRowSelectionChange = new EventEmitter(); /** * Emitted when `IgxColumnComponent` is pinned. * The index that the column is inserted at may be changed through the `insertAtIndex` property. * ```typescript * public columnPinning(event) { * if (event.column.field === "Name") { * event.insertAtIndex = 0; * } * } * ``` * @memberof IgxGridBaseDirective */ this.onColumnPinning = new EventEmitter(); /** * An @Output property emitting an event when `IgxGridCellComponent` * editing has been performed in the grid and the values have **not** been submitted (e.g. `Esc` key was pressed). * This event is cancelable. * * args: IGridEditEventArgs = { * cancel: bool, * cellID: { * columnID: int, * rowID: int, * rowIndex: int * } * newValue: object, * oldValue: object, * rowID: int * } * * ```typescript * editCancel(event: IGridEditEventArgs){ * const rowID: IgxColumnComponent = event.rowID; * } * ``` * ```html * <igx-grid #grid3 (onCellEditCancel)="editCancel($event)" [data]="remote | async" [primaryKey]="'ProductID'"> * <igx-column [sortable]="true" [field]="'ProductID'"></igx-column> * <igx-column [editable]="true" [field]="'ProductName'"></igx-column> * <igx-column [sortable]="true" [field]="'UnitsInStock'" [header]="'Units in Stock'"></igx-column> * </igx-grid> * ``` * @memberof IgxGridComponent */ this.onCellEditCancel = new EventEmitter(); /** * An @Output property emitting an event when `IgxGridCellComponent` enters edit mode. * This event is cancelable. * * args: IGridEditEventArgs = { * cancel: bool, * cellID: { * columnID: int, * rowID: int, * rowIndex: int * } * oldValue: object, * rowID: int * } * * ```typescript * editStart(event: IGridEditEventArgs){ * const value: IgxColumnComponent = event.newValue; * } * ``` * ```html * <igx-grid #grid3 (onCellEditEnter)="editStart($event)" [data]="remote | async" (onSortingDone)="process($event)" * [primaryKey]="'ProductID'"> * <igx-column [sortable]="true" [field]="'ProductID'"></igx-column> * <igx-column [editable]="true" [field]="'ProductName'"></igx-column> * <igx-column [sortable]="true" [field]="'UnitsInStock'" [header]="'Units in Stock'"></igx-column> * </igx-grid> * ``` * @memberof IgxGridComponent */ this.onCellEditEnter = new EventEmitter(); /** * An @Output property emitting an event when `IgxGridCellComponent` editing has been performed in the grid. * Event is fired after editing is completed, when the cell is exiting edit mode. * This event is cancelable. * * args: IGridEditEventArgs = { * cancel: bool, * cellID: { * columnID: int, * rowID: int, * rowIndex: int * } * newValue: object, * oldValue: object, * rowID: int * } * * ```typescript * editDone(event: IGridEditEventArgs){ * const value: IgxColumnComponent = event.newValue; * } * ``` * ```html * <igx-grid #grid3 (onCellEdit)="editDone($event)" [data]="remote | async" (onSortingDone)="process($event)" * [primaryKey]="'ProductID'"> * <igx-column [sortable]="true" [field]="'ProductID'"></igx-column> * <igx-column [editable]="true" [field]="'ProductName'"></igx-column> * <igx-column [sortable]="true" [field]="'UnitsInStock'" [header]="'Units in Stock'"></igx-column> * </igx-grid> * ``` * @memberof IgxGridBaseDirective */ this.onCellEdit = new EventEmitter(); /** * An @Output property emitting an event when [rowEditable]="true" a row enters edit mode. * This event is cancelable. * * args: IGridEditEventArgs = { * cancel: bool, * oldValue: <rowObj>, * rowID: int * } * * Bind to the event in markup as follows: * ```html * <igx-grid #grid3 (onRowEditEnter)="editStart($event)" [data]="remote | async" (onSortingDone)="process($event)" * [primaryKey]="'ProductID'" [rowEditable]="true"> * <igx-column [sortable]="true" [field]="'ProductID'"></igx-column> * <igx-column [editable]="true" [field]="'ProductName'"></igx-column> * <igx-column [sortable]="true" [field]="'UnitsInStock'" [header]="'Units in Stock'"></igx-column> * </igx-grid> * ``` * ```typescript * editStart(event: IGridEditEventArgs) { * const editedRowObj = event.oldValue; * const cancelValue = event.cancel; * const rowID = event.rowID; * } * ``` * @memberof IgxGridComponent */ this.onRowEditEnter = new EventEmitter(); /** * An @Output property emitting an event when [rowEditable]="true" & `endEdit(true)` is called. * Emitted when changing rows during edit mode, selecting an un-editable cell in the edited row, * performing paging operation, column resizing, pinning, moving or hitting `Done` * button inside of the rowEditingOverlay, or hitting the `Enter` key while editing a cell. * This event is cancelable. * * args: IGridEditEventArgs = { * cancel: bool, * newValue: <rowObj>, * oldValue: <rowObj>, * rowID: int * } * * Bind to the event in markup as follows: * ```html * <igx-grid #grid3 (onRowEdit)="editDone($event)" [data]="remote | async" (onSortingDone)="process($event)" * [primaryKey]="'ProductID'" [rowEditable]="true"> * <igx-column [sortable]="true" [field]="'ProductID'"></igx-column> * <igx-column [editable]="true" [field]="'ProductName'"></igx-column> * <igx-column [sortable]="true" [field]="'UnitsInStock'" [header]="'Units in Stock'"></igx-column> * </igx-grid> * ``` * * ```typescript * editDone(event: IGridEditEventArgs) { * const originalRowObj = event.oldValue; * const updatedRowObj = event.newValue; * const cancelValue = event.cancel; * const rowID = event.rowID; * } * ``` * @memberof IgxGridBaseDirective */ this.onRowEdit = new EventEmitter(); /** * An @Output property emitting an event when [rowEditable]="true" & `endEdit(false)` is called. * Emitted when changing hitting `Esc` key during cell editing and when click on the `Cancel` button * in the row editing overlay. * This event is cancelable. * * args: IGridEditEventArgs = { * cancel: bool, * newValue: <rowObj>, * oldValue: <rowObj>, * rowID: int * } * * Bind to the event in markup as follows: * ```html * <igx-grid #grid3 (onRowEditCancel)="editCancel($event)" [data]="remote | async" (onSortingDone)="process($event)" * [primaryKey]="'ProductID'" [rowEditable]="true"> * <igx-column [sortable]="true" [field]="'ProductID'"></igx-column> * <igx-column [editable]="true" [field]="'ProductName'"></igx-column> * <igx-column [sortable]="true" [field]="'UnitsInStock'" [header]="'Units in Stock'"></igx-column> * </igx-grid> * ``` * ```typescript * editCancel(emitted: { row: IgxGridRowComponent, newValue: any, oldValue: any }): void { * const originalRowObj = event.oldValue; * const updatedRowObj = event.newValue; * const cancelValue = event.cancel; * const rowID = event.rowID; * } * ``` * @memberof IgxGridBaseDirective */ this.onRowEditCancel = new EventEmitter(); /** * Emitted when a grid column is initialized. Returns the column object. * ```html * <igx-grid #grid [data]="localData" [onColumnInit]="initColumns($event)" [autoGenerate]="true"></igx-grid> * ``` * ```typescript * initColumns(event: IgxColumnComponent) { * const column: IgxColumnComponent = event; * column.filterable = true; * column.sortable = true; * column.editable = true; * } * ``` * @memberof IgxGridBaseDirective */ this.onColumnInit = new EventEmitter(); /** * Emitted when sorting is performed through the UI. Returns the sorting expression. * ```html * <igx-grid #grid [data]="localData" [autoGenerate]="true" (onSortingDone)="sortingDone($event)"></igx-grid> * ``` * ```typescript * sortingDone(event: SortingDirection){ * const sortingDirection = event; * } * ``` * @memberof IgxGridBaseDirective */ this.onSortingDone = new EventEmitter(); /** * Emitted when filtering is performed through the UI. * Returns the filtering expressions tree of the column for which filtering was performed. * ```typescript * filteringDone(event: IFilteringExpressionsTree){ * const filteringTree = event; *} * ``` * ```html * <igx-grid #grid [data]="localData" [height]="'305px'" [autoGenerate]="true" (onFilteringDone)="filteringDone($event)"></igx-grid> * ``` * @memberof IgxGridBaseDirective */ this.onFilteringDone = new EventEmitter(); /** * Emitted when paging is performed. Returns an object consisting of the previous and next pages. * ```typescript * pagingDone(event: IPageEventArgs){ * const paging = event; * } * ``` * ```html * <igx-grid #grid [data]="localData" [height]="'305px'" [autoGenerate]="true" (onPagingDone)="pagingDone($event)"></igx-grid> * ``` * @memberof IgxGridBaseDirective */ this.onPagingDone = new EventEmitter(); /** * Emitted when a `IgxGridRowComponent` is being added to the `IgxGridComponent` through the API. * Returns the data for the new `IgxGridRowComponent` object. * ```typescript * rowAdded(event: IRowDataEventArgs){ * const rowInfo = event; * } * ``` * ```html * <igx-grid #grid [data]="localData" (onRowAdded)="rowAdded($event)" [height]="'305px'" [autoGenerate]="true"></igx-grid> * ``` * @memberof IgxGridBaseDirective */ this.onRowAdded = new EventEmitter(); /** * Emitted when a `IgxGridRowComponent` is deleted through the `IgxGridComponent` API. * Returns an `IRowDataEventArgs` object. * ```typescript * rowDeleted(event: IRowDataEventArgs){ * const rowInfo = event; * } * ``` * ```html * <igx-grid #grid [data]="localData" (onRowDeleted)="rowDeleted($event)" [height]="'305px'" [autoGenerate]="true"></igx-grid> * ``` * @memberof IgxGridBaseDirective */ this.onRowDeleted = new EventEmitter(); /** * Emitted when a new chunk of data is loaded from virtualization. * ```typescript * <igx-grid #grid [data]="localData" [autoGenerate]="true" (onDataPreLoad)='handleDataPreloadEvent()'></igx-grid> * ``` * @memberof IgxGridBaseDirective */ this.onDataPreLoad = new EventEmitter(); /** * Emitted when `IgxColumnComponent` is resized. * Returns the `IgxColumnComponent` object's old and new width. * ```typescript * resizing(event: IColumnResizeEventArgs){ * const grouping = event; * } * ``` * ```html * <igx-grid #grid [data]="localData" (onColumnResized)="resizing($event)" [autoGenerate]="true"></igx-grid> * ``` * @memberof IgxGridBaseDirective */ this.onColumnResized = new EventEmitter(); /** * Emitted when a `IgxGridCellComponent` is right clicked. Returns the `IgxGridCellComponent` object. * ```typescript * contextMenu(event: IGridCellEventArgs){ * const resizing = event; * console.log(resizing); * } * ``` * ```html * <igx-grid #grid [data]="localData" (onContextMenu)="contextMenu($event)" [autoGenerate]="true"></igx-grid> * ``` * @memberof IgxGridBaseDirective */ this.onContextMenu = new EventEmitter(); /** * Emitted when a `IgxGridCellComponent` is double clicked. Returns the `IgxGridCellComponent` object. * ```typescript * dblClick(event: IGridCellEventArgs){ * const dblClick = event; * console.log(dblClick); * } * ``` * ```html * <igx-grid #grid [data]="localData" (onDoubleClick)="dblClick($event)" [autoGenerate]="true"></igx-grid> * ``` * @memberof IgxGridBaseDirective */ this.onDoubleClick = new EventEmitter(); /** * Emitted when `IgxColumnComponent` visibility is changed. Args: { column: any, newValue: boolean } * ```typescript * visibilityChanged(event: IColumnVisibilityChangedEventArgs){ * const visiblity = event; * } * ``` * ```html * <igx-grid [columnHiding]="true" [showToolbar]="true" (onColumnVisibilityChanged)="visibilityChanged($event)"></igx-grid> * ``` * @memberof IgxGridBaseDirective */ this.onColumnVisibilityChanged = new EventEmitter(); /** * Emitted when `IgxColumnComponent` moving starts. Returns the moved `IgxColumnComponent` object. * ```typescript * movingStart(event: IColumnMovingStartEventArgs){ * const movingStarts = event; * } * ``` * ```html * <igx-grid [columnHiding]="true" [showToolbar]="true" (onColumnMovingStart)="movingStart($event)"></igx-grid> * ``` * @memberof IgxGridBaseDirective */ this.onColumnMovingStart = new EventEmitter(); /** * Emitted throughout the `IgxColumnComponent` moving operation. * Returns the source and target `IgxColumnComponent` objects. This event is cancelable. * ```typescript * moving(event: IColumnMovingEventArgs){ * const moving = event; * } * ``` * ```html * <igx-grid [columnHiding]="true" [showToolbar]="true" (onColumnMoving)="moving($event)"></igx-grid> * ``` * @memberof IgxGridBaseDirective */ this.onColumnMoving = new EventEmitter(); /** * Emitted when `IgxColumnComponent` moving ends. * Returns the source and target `IgxColumnComponent` objects. * ```typescript * movingEnds(event: IColumnMovingEndEventArgs){ * const movingEnds = event; * } * ``` * ```html * <igx-grid [columnHiding]="true" [showToolbar]="true" (onColumnMovingEnd)="movingEnds($event)"></igx-grid> * ``` * @memberof IgxGridBaseDirective */ this.onColumnMovingEnd = new EventEmitter(); /** * Emitted when keydown is triggered over element inside grid's body. * This event is fired only if the key combination is supported in the grid. * Return the target type, target object and the original event. This event is cancelable. * ```typescript * customKeydown(args: IGridKeydownEventArgs) { * const keydownEvent = args.event; * } * ``` * ```html * <igx-grid (onGridKeydown)="customKeydown($event)"></igx-grid> * ``` */ this.onGridKeydown = new EventEmitter(); /** * Emitted when start dragging a row. * Return the dragged row. */ this.onRowDragStart = new EventEmitter(); /** * Emitted when dropping a row. * Return the dropped row. */ this.onRowDragEnd = new EventEmitter(); /** * Emitted when a copy operation is executed. * Fired only if copy behavior is enabled through the [`clipboardOptions`]{@link IgxGridBaseDirective#clipboardOptions}. */ this.onGridCopy = new EventEmitter(); /** * @hidden */ this.columnList = new QueryList(); /** * @hidden */ this.tmpOutlets = new QueryList(); /** * The custom template, if any, that should be used when rendering a row expand indicator. */ this.rowExpandedIndicatorTemplate = null; /** * The custom template, if any, that should be used when rendering a row collapse indicator. */ this.rowCollapsedIndicatorTemplate = null; /** * The custom template, if any, that should be used when rendering a header expand indicator. */ this.headerExpandIndicatorTemplate = null; /** * The custom template, if any, that should be used when rendering a header collapse indicator. */ this.headerCollapseIndicatorTemplate = null; /** * @hidden */ this.tabindex = 0; /** * @hidden */ this.hostRole = 'grid'; /** * Emitted before sorting is performed. Returns the sorting expressions. * ```html * <igx-grid #grid [data]="localData" [autoGenerate]="true" (sortingExpressionsChange)="sortingExprChange($event)"></igx-grid> * ``` * ```typescript * sortingExprChange(event: ISortingExpression[]){ * const sortingExpressions = event; * } * ``` * @memberof IgxGridBaseDirective */ this.sortingExpressionsChange = new EventEmitter(); /** * @hidden */ this.columnsWithNoSetWidths = null; /* Toolbar related definitions */ this._showToolbar = false; this._exportExcel = false; this._exportCsv = false; this._toolbarTitle = null; this._exportText = null; this._exportExcelText = null; this._exportCsvText = null; this._rowEditable = false; this._filteredSortedData = null; /** * Provides access to the `IgxToolbarComponent`. * ```typescript * const gridToolbar = this.grid.toolbar; * ``` * @memberof IgxGridBaseDirective */ this.toolbar = null; this.toolbarHtml = null; /** * Controls the copy behavior of the grid. */ this.clipboardOptions = { /** * Enables/disables the copy behavior */ enabled: true, /** * Include the columns headers in the clipboard output. */ copyHeaders: true, /** * Apply the columns formatters (if any) on the data in the clipboard output. */ copyFormatters: true, /** * The separator used for formatting the copy output. Defaults to `\t`. */ separator: '\t' }; /** * Emitted when an export process is initiated by the user. * ```typescript * toolbarExporting(event: IGridToolbarExportEventArgs){ * const toolbarExporting = event; * } * ``` * @memberof IgxGridBaseDirective */ this.onToolbarExporting = new EventEmitter(); /* End of toolbar related definitions */ /** * Emitted when making a range selection either through * drag selection or through keyboard selection. */ this.onRangeSelection = new EventEmitter(); /** * @hidden */ this.calcHeight = 0; /** * @hidden */ this.chipsGoupingExpressions = []; /** * @hidden */ this.disableTransitions = false; /** * @hidden */ this.lastSearchInfo = { searchText: '', caseSensitive: false, exactMatch: false, activeMatchIndex: 0, matchInfoCache: [] }; /** * @hidden */ this.columnWidthSetByUser = false; /** * @hidden */ this.destroy$ = new Subject(); /** * @hidden */ this._perPage = 15; /** * @hidden */ this._page = 0; /** * @hidden */ this._paging = false; /** * @hidden */ this._hideRowSelectors = false; /** * @hidden */ this._rowDrag = false; /** * @hidden */ this._pipeTrigger = 0; /** * @hidden */ this._summaryPipeTrigger = 0; /** * @hidden */ this._columns = []; /** * @hidden */ this._pinnedColumns = []; /** * @hidden */ this._unpinnedColumns = []; /** * @hidden */ this._filteringExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And); /** * @hidden */ this._sortingExpressions = []; /** * @hidden */ this._maxLevelHeaderDepth = null; /** * @hidden */ this._columnHiding = false; /** * @hidden */ this._columnPinning = false; this._allowFiltering = false; this._allowAdvancedFiltering = false; this._filterMode = FilterMode.quickFilter; this.observer = new ResizeObserver(() => { }); this.resizeNotify = new Subject(); this._hiddenColumnsText = ''; this._pinnedColumnsText = ''; this._height = '100%'; this._width = '100%'; this._horizontalForOfs = []; this._multiRowLayoutRowSize = 1; // Caches this._totalWidth = NaN; this._pinnedVisible = []; this._unpinnedVisible = []; this._pinnedWidth = NaN; this._unpinnedWidth = NaN; this._visibleColumns = []; this._columnGroups = false; this._defaultTargetRecordNumber = 10; this._summaryPosition = GridSummaryPosition.bottom; this._summaryCalculationMode = GridSummaryCalculationMode.rootAndChildLevels; this._cellSelectionMode = GridSelectionMode.multiple; this._rowSelectionMode = GridSelectionMode.none; this.rowEditPositioningStrategy = new RowEditPositionStrategy({ horizontalDirection: HorizontalAlignment.Right, verticalDirection: VerticalAlignment.Bottom, horizontalStartPoint: HorizontalAlignment.Left, verticalStartPoint: VerticalAlignment.Bottom, closeAnimation: null }); this.rowEditSettings = { scrollStrategy: new AbsoluteScrollStrategy(), modal: false, closeOnOutsideClick: false, outlet: this.rowOutletDirective, positionStrategy: this.rowEditPositioningStrategy }; this.verticalScrollHandler = (event) => { this.verticalScrollContainer.onScroll(event); if (isEdge()) { this.wheelHandler(false); } this.disableTransitions = true; this.zone.run(() => { this.zone.onStable.pipe(first()).subscribe(() => { this.verticalScrollContainer.onChunkLoad.emit(this.verticalScrollContainer.state); }); if (this.rowEditable) { this.changeRowEditingOverlayStateOnScroll(this.rowInEditMode); } }); this.disableTransitions = false; this.hideOverlays(); }; this.horizontalScrollHandler = (event) => { const scrollLeft = event.target.scrollLeft; if (isEdge()) { this.wheelHandler(true); } this.headerContainer.onHScroll(scrollLeft); this._horizontalForOfs.forEach(vfor => vfor.onHScroll(scrollLeft)); this.cdr.markForCheck(); this.zone.run(() => { this.zone.onStable.pipe(first()).subscribe(() => { this.parentVirtDir.onChunkLoad.emit(this.headerContainer.state); }); }); this.hideOverlays(); }; this.keydownHandler = (event) => { const key = event.key.toLowerCase(); if ((isNavigationKey(key) && event.keyCode !== 32) || key === 'tab' || key === 'pagedown' || key === 'pageup') { event.preventDefault(); if (key === 'pagedown') { this.verticalScrollContainer.scrollNextPage(); this.nativeElement.focus(); } else if (key === 'pageup') { this.verticalScrollContainer.scrollPrevPage(); this.nativeElement.focus(); } } }; /** * @hidden */ this.scrollHandler = (event) => { this.headerContainer.scrollPosition += event.target.scrollLeft; this.verticalScrollContainer.scrollPosition += event.target.scrollTop; event.target.scrollLeft = 0; event.target.scrollTop = 0; }; /** * @hidden */ this.wheelHandler = (isScroll = false) => { if (this.document.activeElement && // tslint:disable-next-line:no-bitwise (this.document.activeElement.compareDocumentPosition(this.tbody.nativeElement) & Node.DOCUMENT_POSITION_CONTAINS || // tslint:disable-next-line:no-bitwise (this.document.activeElement. compareDocumentPosition(this.tfoot.nativeElement) & Node.DOCUMENT_POSITION_CONTAINS && isScroll))) { this.document.activeElement.blur(); } }; /** * @hidden */ this.rowEditingWheelHandler = (event) => { if (event.deltaY > 0) { this.verticalScrollContainer.scrollNext(); } else { this.verticalScrollContainer.scrollPrev(); } }; this.cdr.detach(); } get scrollWidth() { return this._scrollWidth; } /** * An accessor that sets the resource strings. * By default it uses EN resources. */ set resourceStrings(value) { this._resourceStrings = Object.assign({}, this._resourceStrings, value); } /** * An accessor that returns the resource strings. */ get resourceStrings() { return this._resourceStrings; } get filteringLogic() { return this._filteringExpressionsTree.operator; } /** * Sets the filtering logic of the `IgxGridComponent`. * The default is AND. * ```html * <igx-grid [data]="Data" [autoGenerate]="true" [filteringLogic]="filtering"></igx-grid> * ``` * @memberof IgxGridBaseDirective */ set filteringLogic(value) { this._filteringExpressionsTree.operator = value; } /** * Returns the filtering state of `IgxGridComponent`. * ```typescript * let filteringExpressionsTree = this.grid.filteringExpressionsTree; * ``` * @memberof IgxGridBaseDirective */ get filteringExpressionsTree() { return this._filteringExpressionsTree; } /** * Sets the filtering state of the `IgxGridComponent`. * ```typescript * const logic = new FilteringExpressionsTree(FilteringLogic.And, "ID"); * logic.filteringOperands = [ * { * condition: IgxNumberFilteringOperand.instance().condition('greaterThan'), * fieldName: 'ID', * searchVal: 1 * } * ]; * this.grid.filteringExpressionsTree = (logic); * ``` * Two-way data binding. * ```html * <igx-grid #grid [data]="Data" [autoGenerate]="true" [(filteringExpressionsTree)]="model.filteringExpressions"></igx-grid> * ``` * @memberof IgxGridBaseDirective */ set filteringExpressionsTree(value) { if (value && value instanceof FilteringExpressionsTree) { const val = value; for (let index = 0; index < val.filteringOperands.length; index++) { if (!(val.filteringOperands[index] instanceof FilteringExpressionsTree)) { const newExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And, val.filteringOperands[index].fieldName); newExpressionsTree.filteringOperands.push(val.filteringOperands[index]); val.filteringOperands[index] = newExpressionsTree; } } // clone the filtering expression tree in order to trigger the filtering pipe const filteringExpressionTreeClone = new FilteringExpressionsTree(value.operator, value.fieldName); filteringExpressionTreeClone.type = FilteringExpressionsTreeType.Regular; filteringExpressionTreeClone.filteringOperands = value.filteringOperands; this._filteringExpressionsTree = filteringExpressionTreeClone; this.filteringExpressionsTreeChange.emit(this._filteringExpressionsTree); if (this.filteringService.isFilteringExpressionsTreeEmpty() && !this.advancedFilteringExpressionsTree) { this.filteredData = null; } this.filteringService.refreshExpressions(); this.selectionService.clearHeaderCBState(); this.summaryService.clearSummaryCache(); this.notifyChanges(); } } /** * Returns the advanced filtering state of `IgxGridComponent`. * ```typescript * let advancedFilteringExpressionsTree = this.grid.advancedFilteringExpressionsTree; * ``` * @memberof IgxGridBaseDirective */ get advancedFilteringExpressionsTree() { return this._advancedFilteringExpressionsTree; } /** * Sets the advanced filtering state of the `IgxGridComponent`. * ```typescript * const logic = new FilteringExpressionsTree(FilteringLogic.And); * logic.filteringOperands = [ * { * condition: IgxNumberFilteringOperand.instance().condition('greaterThan'), * fieldName: 'ID', * searchVal: 1 * }, * { * condition: IgxStringFilteringOperand.instance().condition('contains'), * fieldName: 'CompanyName', * searchVal: 'a' * } * ]; * this.grid.advancedFilteringExpressionsTree = logic; * ``` * @memberof IgxGridBaseDirective */ set advancedFilteringExpressionsTree(value) { if (value && value instanceof FilteringExpressionsTree) { // clone the filtering expression tree in order to trigger the filtering pipe const filteringExpressionTreeClone = new FilteringExpressionsTree(value.operator, value.fieldName); filteringExpressionTreeClone.type = FilteringExpressionsTreeType.Advanced; filteringExpressionTreeClone.filteringOperands = value.filteringOperands; this._advancedFilteringExpressionsTree = filteringExpressionTreeClone; } else { this._advancedFilteringExpressionsTree = null; } this.advancedFilteringExpressionsTreeChange.emit(this._advancedFilteringExpressionsTree); if (this.filteringService.isFilteringExpressionsTreeEmpty() && !this.advancedFilteringExpressionsTree) { this.filteredData = null; } this.selectionService.clearHeaderCBState(); this.summaryService.clearSummaryCache(); this.markForCheck(); // Wait for the change detection to update filtered data through the pipes and then emit the event. requestAnimationFrame(() => this.onFilteringDone.emit(this._advancedFilteringExpressionsTree)); } /** * Returns the locale of the grid. * If not set, returns browser's language. */ get locale() { if (this._locale) { return this._locale; } else { return 'en'; } } /** * Sets the locale of the grid. */ set locale(value) { this._locale = value; } /** * Returns whether the paging feature is enabled/disabled. * The default state is disabled (false). * ``` * const paging = this.grid.paging; * ``` * @memberof IgxGridBaseDirective */ get paging() { return this._paging; } /** * Enables/Disables the paging feature. * ```html * <igx-grid #grid [data]="Data" [autoGenerate]="true" [paging]="true"></igx-grid> * ``` * @memberof IgxGridBaseDirective */ set paging(value) { this._paging = value; this._pipeTrigger++; this.notifyChanges(true); } /** * Returns the current page index. * ```html * let gridPage = this.grid.page; * ``` * @memberof IgxGridBaseDirective */ get page() { return this._page; } /** * Sets the current page index. * ```html * <igx-grid #grid [data]="Data" [paging]="true" [page]="5" [autoGenerate]="true"></igx-grid> *``` * Two-way data binding. * ```html * <igx-grid #grid [data]="Data" [paging]="true" [(page)]="model.page" [autoGenerate]="true"></igx-grid> * ``` * @memberof IgxGridBaseDirective */ set page(val) { if (val === this._page || val < 0 || val > this.totalPages - 1) { return; } this.selectionService.clear(true); this.onPagingDone.emit({ previous: this._page, current: val }); this._page = val; this.pageChange.emit(this._page); this.notifyChanges(); } /** * Returns the number of visible items per page of the `IgxGridComponent`. * The default is 15. * ```html * let itemsPerPage = this.grid.perPage; * ``` * @memberof IgxGridBaseDirective */ get perPage() { return this._perPage; } /** * Sets the number of visible items per page of the `IgxGridComponent`. * ```html * <igx-grid #grid [data]="Data" [paging]="true" [perPage]="5" [autoGenerate]="true"></igx-grid> * ``` * * Two-way data binding. * ```html * <igx-grid #grid [data]="Data" [paging]="true" [(perPage)]="model.perPage" [autoGenerate]="true"></igx-grid> * ``` * @memberof IgxGridBaseDirective */ set perPage(val) { if (val < 0) { return; } this.selectionService.clear(true); this._perPage = val; this.perPageChange.emit(this._perPage); this.page = 0; this.endEdit(true); this.notifyChanges(); } /** * Returns whether the column hiding UI for the `IgxGridComponent` is enabled. * By default it is disabled (false). * ```typescript * let gridColHiding = this.grid.columnHiding; * ``` * @memberof IgxGridBaseDirective */ get columnHiding() { return this._columnHiding; } /** * Sets whether the column hiding UI for the `IgxGridComponent` is enabled. * In order for the UI to work, you need to enable the toolbar as shown in the example below. * ```html * <igx-grid [data]="Data" [autoGenerate]="true" [showToolbar]="true" [columnHiding]="true"></igx-grid> * ``` * @memberof IgxGridBaseDirective */ set columnHiding(value) { if (this._columnHiding !== value) { this._columnHiding = value; if (!this._init) { this.notifyChanges(true); } } } get rowSelectable()