File

projects/i-components/src/lib/components/xam-grid/xam-grid.component.ts

Description

Angular Component for the Xam Grid Control

Extends

BaseComponent

Implements

OnInit AfterContentInit AfterViewChecked AfterViewInit DoCheck OnDestroy

Metadata

selector wm-xam-grid
styleUrls ./xam-grid.component.scss
templateUrl ./xam-grid.component.html

Index

Properties
Methods
Inputs
Outputs
HostBindings
HostListeners
Accessors

Constructor

constructor(injector: Injector, cdRef: ChangeDetectorRef, differsFactory: IterableDiffers, resolver: ComponentFactoryResolver, ref: ElementRef, document, iconService: IgxIconService)

Creates an instance of XamGridComponent.

Parameters :
Name Type Optional
injector Injector No
cdRef ChangeDetectorRef No
differsFactory IterableDiffers No
resolver ComponentFactoryResolver No
ref ElementRef<HTMLElement> No
document No
iconService IgxIconService No

Inputs

addNewRowInheritance
Type : any

Input from the extended component to fill the addNewRow in the internal xamGrid

autoGenerateColumns
Type : boolean

Sets whether the columns of all ColumnLayout objects of this XamGrid should be generated.

borderBrush
Type : any

Gets the border color of the control.

borderThickness
Type : string

Gets the border styling of the grid.

cellStyleEnabled
Type : boolean
Default value : false

Flag which indicates if the cell styling is enabled

columnLayoutInheritance
Type : any

Input from the extended component to fill the ColumnLayout in the internal xamGrid

columnWidth
Type : ColumnWidth

Gets/sets the ColumnWidth type for the columns of the grid. Runs only on initialization

data
Type : any

Gets/set data.

editingInheritance
Type : EditingSettingsComponent

Input from the extended component to fill the addNewRow in the internal xamGrid

filterCellTooltip
Type : string

Custom input of xam grid component to add tooltip message to each filter column. Note: Every FilterRowCellControl is going to have the same tooltip, if an specific tooltip should be set to an specific FilterRowCellControl please add new functionality.

footerVisibility
Type : boolean

Controls whether to show the column footers if any.

gridColumnsInheritance
Type : any

Input from the extended component to fill the grid columns in the internal xamGrid

headerStyle
Type : any

set headerStyle.

headersVisibility
Type : any

Sets the visibility of the Xam grid columns headers.

isAlternateRowsEnabled
Type : boolean

Gets/sets the isAlternateRowsEnabled, if enabled even rows will display in a different color.

itemsSource
Type : any

Two-way bindable property for the data source of the Xam grid.

model
Type : XamGridModel

Object with XamGridComponent properties and events.

name
Type : string
Inherited from BaseComponent
Defined in BaseComponent:446

Sets the name model property for the control when the name is an input

selectedRow
Type : any

Gets/sets the current selected row in the Xam grid.

selectionSettings
Type : SelectionSettings

Gets/sets the selection settings for the XamGrid.

sortingSettingInheritance
Type : SortingSettingsComponent

Sorting settings from the extended component.

virtualHeight
Type : any

Sets the grid height to limit how many rows are rendered accepts null value, which will render all rows in the DOM with no scrollbar

controlTemplate
Type : any
Inherited from BaseComponent
Defined in BaseComponent:1197

Sets the controlTemplate Input property for changing the model's TemplateProperty

cursor
Inherited from BaseComponent
Defined in BaseComponent:1451

Property used to save the cursor value

dataContext
Type : any
Inherited from BaseComponent
Defined in BaseComponent:952

Gets/sets the dataContext Input property for changing the model's DataContextProperty

dataGridRowHeight
Type : number
Default value : 22
Inherited from BaseComponent
Defined in BaseComponent:507

Represents the row height of both the DataGrid and XamGrid components it affects the css and also an internal function that virtualized data, so do not change directly on css, use this variable instead.

foreground
Type : any
Inherited from BaseComponent
Defined in BaseComponent:1223

Sets the value of the Foreground property

height
Inherited from BaseComponent
Defined in BaseComponent:1394

Sets the height

horizontalAlignment
Inherited from BaseComponent
Defined in BaseComponent:1096

Sets the horizontal alignment.

horizontalContentAlignment
Inherited from BaseComponent
Defined in BaseComponent:1125

Sets the horizontal content alignment.

hostHozSelfAlign
Type : boolean
Default value : false
Inherited from BaseComponent
Defined in BaseComponent:380

Applies horizontal selfalign class. Flags indicates when the control should handle its own horizontal alignment and ignore container alignment.

isEnabled
Inherited from BaseComponent
Defined in BaseComponent:1008

Gets/sets the isEnabled property for the BaseComponent

isTabStop
Type : boolean
Inherited from BaseComponent
Defined in BaseComponent:760

Sets/gets IsTabStop property of the BaseComponent

margin
Type : string
Inherited from BaseComponent
Defined in BaseComponent:782

Sets Margin property of the BaseComponent.

maxHeight
Type : any
Inherited from BaseComponent
Defined in BaseComponent:1325

Sets maxHeight

maxWidth
Type : any
Inherited from BaseComponent
Defined in BaseComponent:1283

Sets maxWidth

minHeight
Type : any
Inherited from BaseComponent
Defined in BaseComponent:1304

Sets minHeight

minWidth
Type : any
Inherited from BaseComponent
Defined in BaseComponent:1262

Sets min Width

opacity
Inherited from BaseComponent
Defined in BaseComponent:1336

Sets Opacity value property of the component

spellCheck
Type : boolean
Default value : false
Inherited from BaseComponent
Defined in BaseComponent:186

Flag to determinate if the component should do the spell check or not. Default value is false.

style
Inherited from BaseComponent
Defined in BaseComponent:1434

Sets the style

tabIndex
Type : number
Inherited from BaseComponent
Defined in BaseComponent:733

Sets the property TabIndex of the control model.

tag
Type : any
Inherited from BaseComponent
Defined in BaseComponent:1171

Object used in the Tag property of the Button

useCss
Type : boolean
Default value : false
Inherited from BaseComponent
Defined in BaseComponent:177

Determines if the component uses CSS height/width values, instead of inputs

verticalAlignment
Inherited from BaseComponent
Defined in BaseComponent:1038

Sets the vertical alignment.

verticalContentAlignment
Inherited from BaseComponent
Defined in BaseComponent:1067

Sets the vertical content alignment.

visibility
Type : any
Inherited from BaseComponent
Defined in BaseComponent:980

Gets/sets the visibility property for the BaseComponent

width
Inherited from BaseComponent
Defined in BaseComponent:1365

Sets the width

zindex
Type : number
Inherited from BaseComponent
Defined in BaseComponent:1498

Property used to set the canvas zindex value.

Note: Consider moving this @Input to canvas.direcive.ts, refactoring the directive so all inputs are declared in the directive, and all @HostBindings are declared here in baseComponent, the directive would be responsible for updating the models, while baseComponent will be responsible for binding the values: zIndex, Top, Left...

Outputs

activeCellChanged
Type : EventEmitter<any>

Active cell event emitter

afterCellControlAttached
Type : EventEmitter<any>

Event emitted after the 'new' cells are created

cellClicked
Type : EventEmitter<any>

CellClicked eventEmitter.

cellControlAttached
Type : EventEmitter<any>

Event emitted when 'new' cells are entering the view

cellDoubleClicked
Type : EventEmitter<any>

Double-click eventEmitter.

cellEdited
Type : EventEmitter<any>

Cell edited event emitter

cellEditing
Type : EventEmitter<any>

Cell editing event emitter

cellEnteredEditMode
Type : EventEmitter<any>

CellEnteredEditMode

cellEnteringEditMode
Type : EventEmitter<any>

Cell enter edit mode

cellExitedEditMode
Type : EventEmitter<any>

Cell exit edit mode

cellExitingEditMode
Type : EventEmitter<any>

Cell exiting edit mode eventEmitter

cellSelectionChange
Type : EventEmitter<IGridCellEventArgs>

cellSelectionChanged eventEmitter.

columnFiltered
Type : EventEmitter<any>

Column filtering eventEmitter

columnFixed
Type : EventEmitter<any>

Column fixed eventEmitter.

columnFixedStateChanged
Type : EventEmitter<any>

column fixed state changed eventEmitter

columnResized
Type : EventEmitter<any>

Column resized eventEmitter.

columnResizing
Type : EventEmitter<any>

Column resizing eventEmitter

columnSelectionChanged
Type : EventEmitter<IColumnSelectionEventArgs>

columnSelectionChange event emitter.

columnSorted
Type : EventEmitter<any>

Event emitted when a column has done applying a sorting

columnSorting
Type : EventEmitter<any>

Column sorting eventEmitter.

initializeRow
Type : EventEmitter<any>

Event emitted when the row is initialized

itemsSourceChange
Type : EventEmitter<any>

Event emitter for two-way binding of the itemsSource property.

keyDown
Type : EventEmitter<any>

KeyDown eventEmitter.

loaded
Type : EventEmitter<any>
Inherited from BaseComponent
Defined in BaseComponent:856

Event emitted when the grid is done loading in the DOM

pageIndexChanged
Type : EventEmitter<PageChangedEventArgs>

Page changed event emitter

pageIndexChanging
Type : EventEmitter<CancellablePageChangingEventArgs>

Page changing event emitter

rendered
Type : EventEmitter<any>

XamGrid rendered eventEmitter.

rowAdded
Type : EventEmitter<any>

Row added event emitter

rowDeleted
Type : EventEmitter<any>

Row deleted event emitter

rowEnteredEditMode
Type : EventEmitter<any>

Row entered edit mode

rowExitedEditMode
Type : EventEmitter<any>

Row exit edit mode

selectedRowChange
Type : EventEmitter<any>

Event emitter for two-way binding of the selectedRow property.

selectedRowsCollectionChanged
Type : EventEmitter<literal type>

rowSelectionChange eventEmitter.

unloaded
Type : EventEmitter<any>

Event emitted when the grid is unloading the component

bindingValidationError
Type : EventEmitter<any>
Inherited from BaseComponent
Defined in BaseComponent:114

output to emit the new value of the bindingValidationError event

layoutUpdated
Type : EventEmitter<any>
Inherited from BaseComponent
Defined in BaseComponent:140

Output to emit when then component's layout is updated.

mouseEnter
Type : EventEmitter<literal type>
Inherited from BaseComponent
Defined in BaseComponent:157

Event Emitter. EventEmitter normally called in the mouseEnterHandler.

mouseLeave
Type : EventEmitter<literal type>
Inherited from BaseComponent
Defined in BaseComponent:167

Event Emitter Called in the mouseLeave handler

mouseLeftButtonUp
Type : EventEmitter<literal type>
Inherited from BaseComponent
Defined in BaseComponent:147

MouseLeftButtonUp event Emitter.

sizeChanged
Type : EventEmitter<any>
Inherited from BaseComponent
Defined in BaseComponent:132

Output to emit when then component size is changed.

HostBindings

class
Type : string
Default value : null
Inherited from BaseComponent
Defined in BaseComponent:407

Applies custom CSS classes

class.defaultFontStyles
Type : boolean
Default value : false
Inherited from BaseComponent
Defined in BaseComponent:398

Applies default font styles class, used to allow specificity for each control css

class.focusable
Type : boolean
Default value : false
Inherited from BaseComponent
Defined in BaseComponent:388

Display if the component is focusable or not

class.hasDefinedCursor
Type : boolean
Default value : false
Inherited from BaseComponent
Defined in BaseComponent:415

Applies Defined Cursor class

class.horizontal-center
Type : boolean
Default value : false
Inherited from BaseComponent
Defined in BaseComponent:308

Applies horizontal alignment left class

class.horizontal-left
Type : boolean
Default value : false
Inherited from BaseComponent
Defined in BaseComponent:298

Applies horizontal alignment left class

class.horizontal-right
Type : boolean
Default value : false
Inherited from BaseComponent
Defined in BaseComponent:368

Applies horizontal alignment right class

class.horizontal-stretch
Type : boolean
Default value : false
Inherited from BaseComponent
Defined in BaseComponent:358

Applies horizontal alignment stretch class

class.vertical-bottom
Type : boolean
Default value : false
Inherited from BaseComponent
Defined in BaseComponent:328

Applies vertical alignment bottom class

class.vertical-center
Type : boolean
Default value : false
Inherited from BaseComponent
Defined in BaseComponent:338

Applies vertical alignment center class

class.vertical-stretch
Type : boolean
Default value : false
Inherited from BaseComponent
Defined in BaseComponent:318

Applies horizontal alignment stretch class

class.vertical-top
Type : boolean
Default value : false
Inherited from BaseComponent
Defined in BaseComponent:348

Applies vertical alignment top class

style.display
Type : any
Default value : null
Inherited from BaseComponent
Defined in BaseComponent:243

Property use it to apply the host binding for the visibility

style.font-family
Type : any
Default value : null
Inherited from BaseComponent
Defined in BaseComponent:261

Property use it to apply the host binding for the font-family

style.font-size
Type : any
Default value : null
Inherited from BaseComponent
Defined in BaseComponent:270

Property use it to apply the host binding for the font-size

style.font-style
Type : any
Default value : null
Inherited from BaseComponent
Defined in BaseComponent:279

Property use it to apply the host binding for the font-style

style.font-weight
Type : any
Default value : null
Inherited from BaseComponent
Defined in BaseComponent:288

Property use it to apply the host binding for the font-weight

style.height
Type : string
Default value : null
Inherited from BaseComponent
Defined in BaseComponent:218

Property use it to apply the host binding for the height

style.max-height.px
Type : number
Inherited from BaseComponent
Defined in BaseComponent:234

Property used to apply the host binding for max-height

style.max-width.px
Type : number
Inherited from BaseComponent
Defined in BaseComponent:210

Property used to apply the host binding for max-width

style.min-height.px
Type : number
Inherited from BaseComponent
Defined in BaseComponent:226

Property used to apply the host binding for min-height

style.min-width.px
Type : number
Inherited from BaseComponent
Defined in BaseComponent:202

Property used to apply the host binding for min-width

style.opacity
Type : any
Default value : null
Inherited from BaseComponent
Defined in BaseComponent:252

Property use it to apply the host binding for the opacity

style.width
Type : string
Default value : null
Inherited from BaseComponent
Defined in BaseComponent:194

Property use it to apply the host binding for the width

style.z-index
Type : string
Default value : null
Inherited from BaseComponent
Defined in BaseComponent:424

Sets the z-index style.

HostListeners

document:mousedown
Arguments : '$event.target'
document:mousedown(target: any)

TriggerExitEditMode when a click is called outside a xam grid row and a row and is in edition

Parameters :
Name Optional
target No
keydown
Arguments : '$event'
keydown(event: KeyboardEvent)

Listener for tab keydown event Needs to be done in host listener to trigger even in not editable cells

Parameters :
Name Optional
event No

Methods

activeNodeHandler
activeNodeHandler(event: IActiveNodeChangeEventArgs)

Active cell handler

Parameters :
Name Type Optional
event IActiveNodeChangeEventArgs No
Returns : void
Private addColumnFromExpression
addColumnFromExpression(expression: any)

Helper method to add a column to a column collection. Used to handle filtering/sorting/grouping.

Parameters :
Name Type Optional
expression any No
Returns : void
addValidationHelper
addValidationHelper(element: any, msg: string)

Attach a validation helper to the given element.

Parameters :
Name Type Optional
element any No
msg string No
Returns : void
Private adjustPagerSettings
adjustPagerSettings()

Adjust the pager settings and initialize required fields

Returns : void
applyColumnFooterStyles
applyColumnFooterStyles()

Apply footer styles to DOM elements.

Returns : void
applyDataUpdate
applyDataUpdate(isRendering)

Reassign current grid data. This is required to see changes reflected.

Parameters :
Name Optional Default value
isRendering No false
Returns : void
arrowLeftHandler
arrowLeftHandler(event: KeyboardEvent)

Handler for arrowLeft keydown event Gets the cursor position and move to the last cell

Parameters :
Name Type Optional
event KeyboardEvent No
Returns : void
arrowRightHandler
arrowRightHandler(event: KeyboardEvent)

Handler for arrowRight keydown event Gets the cursor position and move to the next cell

Parameters :
Name Type Optional
event KeyboardEvent No
Returns : void
arrowsHandler
arrowsHandler(event: KeyboardEvent)

Handler to know which handler has to use

Parameters :
Name Type Optional
event KeyboardEvent No
Returns : boolean
beginAddRow
beginAddRow(index?: number)

Starts the row adding UI for the XamGrid.

Parameters :
Name Type Optional
index number Yes
Returns : void
buildFooterStylePlan
buildFooterStylePlan()

Build a footer style plan for the current grid.

Returns : StylePlan

{StylePlan}

Protected calculateAndSetNonSpecialColumnsWidth
calculateAndSetNonSpecialColumnsWidth()

Calculates and sets the columns width used for numeric and star values.

Returns : void
Private calculateCellControlValue
calculateCellControlValue(cellComponent: CellType, event: any, result: literal type)

Calculates the value of the cell control

Parameters :
Name Type Optional
cellComponent CellType No
event any No
result literal type No
Returns : void
Protected calculateNumericColumnsWidth
calculateNumericColumnsWidth(columnModels: XamGridColumnModel[])

Calculates column width for numeric columns.

Parameters :
Name Type Optional
columnModels XamGridColumnModel[] No
Returns : void
Protected calculatePercentPerStar
calculatePercentPerStar(starValues: literal type)

Calculates width percent that should be given to each star unit.

Parameters :
Name Type Optional
starValues literal type No
Returns : void
Protected calculateStarColumnsWidth
calculateStarColumnsWidth(columnModels: XamGridColumnModel[])

Calculates column width for star columns.

Parameters :
Name Type Optional
columnModels XamGridColumnModel[] No
Returns : void
Protected calculateStarColumnsWidthLoop
calculateStarColumnsWidthLoop(starValues: literal type)

Calculates column width for star columns. If some star column gets assigned a fixed width, it recalculates usedPixelSize and starTotalSpace and returns false, to indicate that width should be recalculated for all remaining star columns.

Parameters :
Name Type Optional
starValues literal type No
Returns : boolean

{boolean} true if width for all star columns was calculated, false otherwise.

calcVirtualHeight
calcVirtualHeight()

Defines whether to use virtualization or not

Returns : string | null
cellChanged
cellChanged()

Flag to know when a style change from the model

Returns : void
cellClickHandler
cellClickHandler(event: IGridCellEventArgs)

Click Handler event.

Parameters :
Name Type Optional
event IGridCellEventArgs No
Returns : void
cellContext
cellContext(context)

Returns current column data context.

Parameters :
Name Optional
context No
Returns : any

{void}

Private cellControlEvents
cellControlEvents(cell: XamGridCell)

This function is called when a cell is created and it fires two events that can be used to attach a control to the cell.

Parameters :
Name Type Optional Description
cell XamGridCell No
  • XamGridCell - The cell that the control is being attached to.
Returns : void
cellEditedHandler
cellEditedHandler(event: IGridEditDoneEventArgs)

Cell edited handler

Parameters :
Name Type Optional
event IGridEditDoneEventArgs No
Returns : void
cellEditHandler
cellEditHandler(event: IGridEditEventArgs)

Cell editing handler

Parameters :
Name Type Optional
event IGridEditEventArgs No
Returns : void
cellEnterEditMode
cellEnterEditMode(cellType: CellType, isAsync)

Triggers the cell edit mode if column is editable and not read-only

Parameters :
Name Type Optional Default value Description
cellType CellType No

cell to enter edit mode

isAsync No false
Returns : void
cellSelectionHandler
cellSelectionHandler(event: IGridCellEventArgs)

Cell selection event handler.

Parameters :
Name Type Optional
event IGridCellEventArgs No
Returns : void
changePage
changePage()

Changes the page base on the newItemsPerPage value

Returns : void
Private checkDecimalLimits
checkDecimalLimits(result: literal type)

Converts the given value to number and check if it is within allowed limits for decimal type.

NOTE: number limits are much lower than decimal limits, so a true check for decimal limits is not possible with primitive JS number type.

Parameters :
Name Type Optional
result literal type No
Returns : void

{void}

Private checkIntLimits
checkIntLimits(result: literal type)

Converts the given value to number and check if it is within allowed limits for int type.

Parameters :
Name Type Optional
result literal type No
Returns : void

{void}

Private checkNullableIntLimits
checkNullableIntLimits(result: literal type)

Converts the given value to null if it is an empty string, otherwise it converts the value to number and check if it is within allowed limits for int type.

Parameters :
Name Type Optional
result literal type No
Returns : void

{void}

cleanActiveFromIgxGrid
cleanActiveFromIgxGrid()

Clean the active cell of the xam-grid component

Returns : void
clearResolvedCellControl
clearResolvedCellControl()

Method in charge of reset the cell control content herarchy resolutions when required Used in rows scrolling to avoid wrong references in reused controls

Returns : void
clickListener
clickListener(target: any)
Decorators :
@HostListener('document:mousedown', ['$event.target'])

TriggerExitEditMode when a click is called outside a xam grid row and a row and is in edition

Parameters :
Name Type Optional
target any No
Returns : void
columnSelectionHandler
columnSelectionHandler(event: any)

Column selection handler.

Parameters :
Name Type Optional
event any No
Returns : void
Private columnSortingEventParameters
columnSortingEventParameters(e: any)

The function is called when the user clicks on a column header sorting arrow. It gets the column name from the event and then sets the sorting expression to that column.

Parameters :
Name Type Optional Description
e any No
  • any - the sorting event object
Returns : void
Public createCell
createCell(cell: CellType, row?: XamGridRow)

Creates the cell component from the infragistics cell component

Parameters :
Name Type Optional
cell CellType No
row XamGridRow Yes
Returns : XamGridCell
Private createEventParams
createEventParams()

Helper method for creating event params.

Returns : any
Private createRow
createRow(row: RowType)

Create or returns a cached row model from a rowType. Could be a data row or a addNew row.

Parameters :
Name Type Optional
row RowType No
Returns : any
Private createRowFromData
createRowFromData(data: any, index: number)

Create row from data

Parameters :
Name Type Optional
data any No
index number No
Returns : any
dataChangedHandler
dataChangedHandler(event: any)

Handler triggered after the data has changed Emitted after a data operation, rebinding, pagination, etc

Parameters :
Name Type Optional
event any No
Returns : void
dataHandler
dataHandler()

Returns data

Returns : any[]
Private deselectGridRows
deselectGridRows(sender: any, newEventArgs: SelectionCollectionChangedEventArgs)

Deselects the rows from the main grid and column layouts grids.

Parameters :
Name Type Optional
sender any No
newEventArgs SelectionCollectionChangedEventArgs<SelectedRowsCollection> No
Returns : void
doubleClickHandler
doubleClickHandler(event: IGridCellEventArgs)

Double-click event handler.

Parameters :
Name Type Optional
event IGridCellEventArgs No
Returns : void
endRowEdit
endRowEdit(commit, event?: Event)

Ends row editing and triggers the event pipeline.

Parameters :
Name Type Optional Default value
commit No true
event Event Yes
Returns : void
enterEditHandler
enterEditHandler(event: IGridEditEventArgs)

Cell entering edit mode handler

Parameters :
Name Type Optional
event IGridEditEventArgs No
Returns : void
evaluateAutoColumns
evaluateAutoColumns()

Evaluate for which auto columns is neccesary to apply autosize.

Returns : void
evaluateColumnDataErrors
evaluateColumnDataErrors(data: any)

Validates if there are columns with errors

Parameters :
Name Type Optional
data any No
Returns : string
evaluateColumns
evaluateColumns()

Evaluate columns to apply width

Returns : void
executeInitializeRowSequence
executeInitializeRowSequence()

"For each row in the model, fire the InitializeRow event, then for each cell in the row, fire the CellControlAttached event."

memberof XamGridComponent

Returns : void
exitEditHandler
exitEditHandler(event: IGridEditDoneEventArgs)

Cell exiting edit mode handler

Parameters :
Name Type Optional
event IGridEditDoneEventArgs No
Returns : void
Private exitEditOnRowChanged
exitEditOnRowChanged(newRowIndex: number)

Exits edit mode on row changed

Parameters :
Name Type Optional
newRowIndex number No
Returns : void
filteringHandler
filteringHandler(event: IFilteringExpressionsTree)

Filtering handler

Parameters :
Name Type Optional
event IFilteringExpressionsTree No
Returns : void
findElement
findElement(element: any)

If the element has children, return the first child that doesn't have the class 'validationCornerError'.

Parameters :
Name Type Optional Description
element any No
  • any - the element that you want to find the child of
Returns : Element | null

the child element that is not a validationCornerError.

forceRevalidation
forceRevalidation()

Calling this function produces the necessary event to execute the validations of the cell being edited. When used, the cellEditHandler function will be called

Returns : void
Protected generateColumnModels
generateColumnModels()

Generates XamColumn instances and the corresponding column models for them.

Returns : void
Protected generateDataFields
generateDataFields(data: any[])

Try to infer the 'shape' of the objects in the passed data array and to generate the columns based on that.

Parameters :
Name Type Optional
data any[] No
Returns : string[]

{string[]}

Private getAddedRow
getAddedRow(event: IGridEditEventArgs)

Returns the row created from the data

Parameters :
Name Type Optional
event IGridEditEventArgs No
Returns : void
getAddRow
getAddRow()

Get the addNewRow position in the grid

Returns : any

{*}

getAllColumns
getAllColumns(columns?: ColumnBaseCollection | GroupColumnsCollection)

Get all columns

Parameters :
Name Type Optional
columns ColumnBaseCollection | GroupColumnsCollection Yes
getCellByRowColumn
getCellByRowColumn(rowIndex: number, column: string)

Get a cell throuht it row and column.

Parameters :
Name Type Optional
rowIndex number No
column string No
Returns : any
Private getCellControlIfExists
getCellControlIfExists(cell: () => void, cellModel: any)

Gets cell control if it exists.

Parameters :
Name Type Optional
cell function No
cellModel any No
Returns : any
Private getCellElementByEvent
getCellElementByEvent(event: IGridEditDoneEventArgs)

Gets the cell associated with the given event.

Parameters :
Name Type Optional
event IGridEditDoneEventArgs No
Returns : any

{*}

Protected getColumnCalcPixelWidth
getColumnCalcPixelWidth(col: IgxColumnComponent)

Gets the column current used pixel width

Parameters :
Name Type Optional
col IgxColumnComponent No
Returns : any
getColumnGroup
getColumnGroup(col: XamGridColumnModel)

Returns columns from a column group

Parameters :
Name Type Optional
col XamGridColumnModel No
Private getColumnKey
getColumnKey(key: string)

Gets the column key

Parameters :
Name Type Optional
key string No
Returns : any
Private getColumnModelByKey
getColumnModelByKey(key: string, searchInGroups)

Returns a column model by key, if found.

Parameters :
Name Type Optional Default value
key string No
searchInGroups No false
Returns : XamGridColumnModel | undefined

{(XamGridColumnModel | undefined)}

getColumns
getColumns()

Returns columns from model.

Returns : any

{*}

getFilterable
getFilterable(col: XamGridColumnModel)

Returns true if the column IsFilterable and AllowFiltering is true for the grid model. Otherwise, return false.

Parameters :
Name Type Optional Description
col XamGridColumnModel No
  • XamGridColumnModel - The column model that is evaluated.
Returns : any

boolean.

getFilteringCells
getFilteringCells()

Gets filtering cell DOM elements

Returns : any

NodeList

Protected getGridRemainSpaceInfo
getGridRemainSpaceInfo()

Gets the remaining available space

Returns : {}
getGridSelectionMode
getGridSelectionMode(selection: string)

Gets GridSelectionMode depending of the selection value

Parameters :
Name Type Optional
selection string No
Returns : GridSelectionMode

GridSelectionMode

getModelToUse
getModelToUse(control: any, element: any)

Returns model for content use

Parameters :
Name Type Optional
control any No
element any No
Returns : any
getNativeElement
getNativeElement(cell: CellType)

Returns the DOM element of the cell

Parameters :
Name Type Optional
cell CellType No
Returns : any

{*}

Public getPaginationComponent
getPaginationComponent()

Gets the PagerSettingsComponent reference.

Returns : any
Public getRowFromFilteredDataByKey
getRowFromFilteredDataByKey(rowSelector: any)

Get row from filtered data by key

Parameters :
Name Type Optional
rowSelector any No
Returns : XamGridRow
Public getRowFromModelByKey
getRowFromModelByKey(rowSelector: any, component: XamGridComponent)

Gets row from model by key

Parameters :
Name Type Optional
rowSelector any No
component XamGridComponent No
Returns : XamGridRow
Protected getRowIndex
getRowIndex(row: XamGridRow)

Get row index

Parameters :
Name Type Optional
row XamGridRow No
Returns : number
Protected getRowIndexFromFilteredData
getRowIndexFromFilteredData(row: XamGridRow)

Get row index from filtered data

Parameters :
Name Type Optional
row XamGridRow No
Returns : number
getStrategy
getStrategy(col: XamGridColumnModel)

If the column has a SortComparer, return it. Otherwise, return null.

Parameters :
Name Type Optional Description
col XamGridColumnModel No
  • XamGridColumnModel - The column model that is being sorted.
Returns : any

The comparer function that will be used to sort the column.

gridDataHandler
gridDataHandler()

Handler used to fill grid data when is required

Returns : void
gridScrollHandler
gridScrollHandler(event: IGridScrollEventArgs)

Handler triggered on scroll event Be aware this event is called several times per scroll

Parameters :
Name Type Optional
event IGridScrollEventArgs No
Returns : void
hasSummary
hasSummary(column: any)

Determine if the column has sumamry

Parameters :
Name Type Optional
column any No
Returns : boolean

boolean

hasValidationErrors
hasValidationErrors(row: XamGridRow)

Validates if the row currently has any validation errors

Parameters :
Name Type Optional
row XamGridRow No
Returns : boolean
internalColumnLayoutRowSelectionHandler
internalColumnLayoutRowSelectionHandler(sender: any, e: SelectionCollectionChangedEventArgs)

Internal row selection event handler for column layout.

Parameters :
Name Type Optional
sender any No
e SelectionCollectionChangedEventArgs<SelectedRowsCollection> No
Returns : void
Protected invalidateInternalDataWrapper
invalidateInternalDataWrapper()

Clears the internal data wrapper. On the next rebind of the grid data from the dataHandler method the internal wrapper will be populated.

Returns : void
InvalidateSelectionAndActivation
InvalidateSelectionAndActivation(isSelectingCell)

Validates the selectedRows and update the collection if it's necessary while is handling collection changes

Parameters :
Name Optional Default value Description
isSelectingCell No false
  • boolean - flag to tell if its selecting a cell while is handling collection changes
Returns : void
Public isCellInEditMode
isCellInEditMode()

Returns true if the cell is in EditMode

Returns : boolean
Public isCellOrRowInEditMode
isCellOrRowInEditMode()

Returns true if the cell or row is in EditMode

Returns : boolean
isEditable
isEditable(column: XamGridColumnModel)

Determinate if the column is a editable column

Parameters :
Name Type Optional
column XamGridColumnModel No
Returns : boolean

boolean

isNewRow
isNewRow(row: RowType)

Validate if the row is an add new Row type.

Parameters :
Name Type Optional Description
row RowType No

New row.

Returns : boolean

{boolean} true if the row is an add new row Type.

keydownHandler
keydownHandler(e: IGridKeydownEventArgs)

Keydown event handler.

Parameters :
Name Type Optional
e IGridKeydownEventArgs No
Returns : void
lostFocusTextPerPage
lostFocusTextPerPage()

Lost focus handler for page size change control textarea

Returns : void
modelChangeHandler
modelChangeHandler(name?: string, args?: any)
Inherited from BaseComponent
Defined in BaseComponent:2602

Detects if there are changes on the model.

Parameters :
Name Type Optional
name string Yes
args any Yes
Returns : void
navigateToCell
navigateToCell(cellType: CellType)

Navigates and focus the content of a cell.

Parameters :
Name Type Optional
cellType CellType No
Returns : void
Public ngAfterContentChecked
ngAfterContentChecked()
Inherited from BaseComponent
Defined in BaseComponent:2435

Usable for the grid to know when the style has changed and need to call the AlignmentPipe

Returns : void
ngAfterContentInit
ngAfterContentInit()
Inherited from BaseComponent
Defined in BaseComponent:1726

Angular lifecycle hook. Generates column models if needed and adds then to the 'silverlight' model.

Returns : void
ngAfterViewChecked
ngAfterViewChecked()
Inherited from BaseComponent
Defined in BaseComponent:1814

Angular lifecycle hook.

Returns : void
ngAfterViewInit
ngAfterViewInit()
Inherited from BaseComponent
Defined in BaseComponent:1797

Angular lifecycle hook.

Returns : void
Public ngDoCheck
ngDoCheck()
Inherited from BaseComponent
Defined in BaseComponent:2449

Angular lifecycle hook. Use to apply the style over the cells and rows In charge of triggering the first and any other re-evaluation of the columns width calculation

Returns : void
ngOnDestroy
ngOnDestroy()
Inherited from BaseComponent
Defined in BaseComponent:2027

Angular lifecycle hook. Removes all the event listeners for the disabled overlay.

Returns : void
ngOnInit
ngOnInit()
Inherited from BaseComponent
Defined in BaseComponent:2483

Initialize model object.

Returns : void
paginationHandler
paginationHandler(event: IPageEventArgs)

Pagination handler for the control

Parameters :
Name Type Optional
event IPageEventArgs No
Returns : void
pagingHandler
pagingHandler()

Paging handler

Returns : boolean

true if handler paging is applied

pinningHandler
pinningHandler(event: IPinColumnEventArgs)

Column pinning handler

Parameters :
Name Type Optional
event IPinColumnEventArgs No
Returns : void
populateModel
populateModel(dataItem: any, index: number)

Returns a new model for the details XamGrid.

Parameters :
Name Type Optional
dataItem any No
index number No
Returns : any
processActiveCell
processActiveCell(isOnCellActiveEditingEnabled: boolean, isReadOnly: boolean)

Set the Active Cell in editMode if the conditions are met

Parameters :
Name Type Optional
isOnCellActiveEditingEnabled boolean No
isReadOnly boolean No
Returns : void
Private processAllowToolTips
processAllowToolTips(cell: CellType, model: XamGridColumnModel)

Auxiliary function that defines the cell's tooltip by changing the cell's element title property

Parameters :
Name Type Optional
cell CellType No
model XamGridColumnModel No
Returns : void
Private processAllowToolTipsByColumn
processAllowToolTipsByColumn(column: IgxColumnComponent)

Defines whether to show or not the cell tooltip by changing the title property

Parameters :
Name Type Optional
column IgxColumnComponent No
Returns : void
Private processAllowToolTipsByRow
processAllowToolTipsByRow()

Process AllowToolTip property for all visible rows

Returns : void
processAutosize
processAutosize(columns: IgxColumnComponent[])

Asyncronously apply autosize to the given columns.

Parameters :
Name Type Optional
columns IgxColumnComponent[] No
Returns : void
Private processColumnLayoutForRowSelection
processColumnLayoutForRowSelection(oldRows: XamGridRow[])

Process column layout when a row is selected

Parameters :
Name Type Optional
oldRows XamGridRow[] No
Returns : void
processDefaultHeaderStyle
processDefaultHeaderStyle()

Process undefined headerstyle for new columns

Returns : void
processEditableColumn
processEditableColumn(column: XamGridColumnModel)

Determinate if the column is a editable column when the grid is in edit mode

Parameters :
Name Type Optional
column XamGridColumnModel No
Returns : boolean

{boolean}

processElementComponent
processElementComponent(component: any, control: any)

Returns component model with tooltip handler

Parameters :
Name Type Optional
component any No
control any No
Returns : any
Private processFilterCellTooltip
processFilterCellTooltip()

Process filtering columns to add a filter tooltip

Returns : void
processFooterStyle
processFooterStyle(stylePlan: StylePlan, element: Element, footerStyle: RuntimeStyleInfo)

Process the given footer style into the style plan.

Parameters :
Name Type Optional
stylePlan StylePlan No
element Element No
footerStyle RuntimeStyleInfo No
Returns : void
processGridSelections
processGridSelections(name: string)

When SelectedItem is changed verify Grid Selections.

Parameters :
Name Type Optional
name string No
Returns : void
processHeaderStyle
processHeaderStyle(name: string)

Apply the style changes for each column.

Parameters :
Name Type Optional
name string No
Returns : void
processInnerSpans
processInnerSpans(stylePlan: StylePlan, element: Element, setter: Setter)

Add inner span elements into style plan, instead of the given element.

Parameters :
Name Type Optional
stylePlan StylePlan No
element Element No
setter Setter No
Returns : void
processItemSource
processItemSource(name: string)

When itemSource is changed igxGrid reassign the data.

Parameters :
Name Type Optional
name string No
Returns : void
processItemsSourceChange
processItemsSourceChange(name: string, args: DependencyPropertyChangedEventArgs)

Unregister and clear collectionHandler when ItemsSource changes.

Parameters :
Name Type Optional
name string No
args DependencyPropertyChangedEventArgs No
Returns : void
Private processPreviousSelectedRows
processPreviousSelectedRows(sender: any, newEventArgs: SelectionCollectionChangedEventArgs)

Process previous selected rows when a row is selected in a column layout.

Parameters :
Name Type Optional
sender any No
newEventArgs SelectionCollectionChangedEventArgs<SelectedRowsCollection> No
Returns : void
Private processRowCells
processRowCells(row: any)

Create dn select a new XamGridRow

Parameters :
Name Type Optional
row any No
Returns : void
Private processTabCode
processTabCode(event: KeyboardEvent)

Processes the Keyboard event when the code is for the Tab key

Parameters :
Name Type Optional
event KeyboardEvent No
Returns : void
processTriggerExitEditMode
processTriggerExitEditMode(name: string, commit: any)

Triggers the endEdit for the grid to allow changes to be handled

Parameters :
Name Type Optional
name string No
commit any No
Returns : void
Protected registerCellControl
registerCellControl(row: any)

Register the available cells on the model.

Parameters :
Name Type Optional
row any No
Returns : void
registerHandlerForObservablesCollection
registerHandlerForObservablesCollection()

Register a handler for current observableCollection

Returns : void
removeAllErrorMessages
removeAllErrorMessages()

Removes error messages from all cells.

Returns : void
removeErrorMessageOnCell
removeErrorMessageOnCell(event: IGridEditDoneEventArgs)

Removes the error message from the cell asociated with event, if there is any.

Parameters :
Name Type Optional
event IGridEditDoneEventArgs No
Returns : void
Private removeItemSourceHandler
removeItemSourceHandler()

Remove the attached subscription

Returns : void
Protected removeModel
removeModel(models: XamGridColumnModel[], model: XamGridColumnModel)

Removes model from the models array.

Parameters :
Name Type Optional
models XamGridColumnModel[] No
model XamGridColumnModel No
Returns : void
removeValidationHelper
removeValidationHelper(element: any)

Removes the validation helper from an element, if it exists.

Parameters :
Name Type Optional
element any No
Returns : void
renderedHandler
renderedHandler()

Event emitted when the underlying igx-grid is considered 'ready' in the DOM.

Returns : void
renderFooters
renderFooters()

Renders and rebinds the context for the footers of the Xam grid.

Returns : void
resetRows
resetRows()

Reset the rows

Returns : void
resetScrollPosition
resetScrollPosition()

Reset the scroll position: vertical scroll resets to top and horizontal scroll resets to left.

Returns : void
resizeHandler
resizeHandler(event: any)

Column resize event handler.

Parameters :
Name Type Optional
event any No
Returns : void
resolveCellDataContext
resolveCellDataContext(cellModel: any)

Returns cell DataContext

Parameters :
Name Type Optional
cellModel any No
Returns : any
Private resolveUnboundColumnDataContext
resolveUnboundColumnDataContext(cellModel: any)

Creates a new UnboundColumnDataContext when the resolver is not defined otherwise just change the existing DataContext value.

Parameters :
Name Type Optional
cellModel any No
rowAddedHandler
rowAddedHandler(event: IGridEditEventArgs)

Row added handler

Parameters :
Name Type Optional
event IGridEditEventArgs No
Returns : void
Private RowCollectionHandler
RowCollectionHandler(isRendering)

Triggers a collection changed for each row

Parameters :
Name Optional Default value
isRendering No false
Returns : void
rowDefined
rowDefined()

Returns if row is defined

Returns : boolean

{boolean}

rowDeletedHandler
rowDeletedHandler(event: IRowDataEventArgs)

Row deleted handler

Parameters :
Name Type Optional
event IRowDataEventArgs No
Returns : void
rowEditHandler
rowEditHandler(event: any)

RowEdit handler catches if state error is true and cancel enter edition

Parameters :
Name Type Optional
event any No
Returns : void
rowEnterEditHandler
rowEnterEditHandler(event: IGridEditDoneEventArgs)

Row exiting edit mode handler

Parameters :
Name Type Optional
event IGridEditDoneEventArgs No
Returns : void
rowExitEditHandler
rowExitEditHandler(event: IGridEditDoneEventArgs)

Row exiting edit mode handler

Parameters :
Name Type Optional
event IGridEditDoneEventArgs No
Returns : void
rowSelectionHandler
rowSelectionHandler(event: any)

Row selection event handler.

Parameters :
Name Type Optional
event any No
Returns : void
scrollCellIntoViewHandler
scrollCellIntoViewHandler(cell: XamGridCell)

Handler for the ScrollIntoView method

Parameters :
Name Type Optional
cell XamGridCell No
Returns : void
Private selectInputTextIfTextColumnDefault
selectInputTextIfTextColumnDefault(cell: XamGridCell, cellQuery: string)

If the cell is a text column, select the text in the input

Parameters :
Name Type Optional Description
cell XamGridCell No
  • XamGridCell - the cell that is being edited
cellQuery string No
  • string - the query selector for the cell
Returns : void
Protected setColumnProperties
setColumnProperties(collection: any)

Set column properties based on the data grid model setting objects. Called only once, during rendering.

Parameters :
Name Type Optional
collection any No
Returns : void
Protected setColumnsToMinimumWidth
setColumnsToMinimumWidth(starColumnModels: XamGridColumnModel[])

Sets widths to MinimumWidth (or '0' if MinimumWidth is not available) for all given columns.

Parameters :
Name Type Optional
starColumnModels XamGridColumnModel[] No
Returns : void
Protected setColumnsWidth
setColumnsWidth(isRendering)

Called once after rendering of the XamGrid. Setups the width property for the column models based on the grid ColumnWidth property. It is a no-op for Auto, InitialAuto and Star width values.

Parameters :
Name Optional Default value
isRendering No false
Returns : void
Protected setColumnWidthSpecialCase
setColumnWidthSpecialCase(col: any, columnWidth: ColumnWidth)

Sets the igx column size for special scenarios using autosize

Parameters :
Name Type Optional
col any No
columnWidth ColumnWidth No
Returns : boolean
Private setParentRow
setParentRow(model: XamGridModel, rowInternalIndex: any)

Sets the parent row property of nested rows

Parameters :
Name Type Optional Description
model XamGridModel No
  • Model that contains the nested rows
rowInternalIndex any No
  • The parent row internal index data
Returns : void
setReCalcColumnsValues
setReCalcColumnsValues(hasStarValues: boolean, failedSpecialCases: boolean)

Sets if the current columns should recalculated.

Parameters :
Name Type Optional
hasStarValues boolean No
failedSpecialCases boolean No
Returns : void
Protected setsColumnsToNumericValues
setsColumnsToNumericValues()

Sets the columns width to numeric values when resizing from UI. All columns should be resized to a numeric value.

Returns : void
Protected setupAvailableRows
setupAvailableRows()

For each available row at rendering it will register its cells.

Returns : void
Protected setupCellTracker
setupCellTracker()

Creates the tracking needed for the even emitter when a new cell has entered the view.

Returns : void
Protected setupColumnMovingSettings
setupColumnMovingSettings()

Applies grid column moving settings from template directive if defined.

Returns : void

{void}

Protected setupColumnResizing
setupColumnResizing()

Applies column resizing settings from template directive if defined.

Returns : void

{void}

Protected setupColumnTracking
setupColumnTracking()

Setup the handling of dynamic adding/removing of columns in XamGrid and keeping both models in sync.

Returns : void
Protected setupDisabledOverlay
setupDisabledOverlay()

Workaround for the IsEnabled property. The listeners here are registered in the capture phase.

Returns : void
Protected setupEditingSettings
setupEditingSettings()

Applies grid editing settings from template directive if defined.

Returns : void

{void}

Protected setupFilteringExpressions
setupFilteringExpressions()

Synchronize the grid filteringExpressions with the model FilteringSettings.

Returns : void

{void}

Protected setupFilteringSettings
setupFilteringSettings()

Applies grid filtering settings from template directive if defined.

Returns : void

{void}

Protected setupGridSettings
setupGridSettings()

Applies Xam grid settings defined in the context of the xam grid as template bindings

Returns : void
Protected setupPaginationSettings
setupPaginationSettings()

Applies grid pagination settings from template directive if defined.

Returns : void

{void}

Protected setupRowSelectorsSettings
setupRowSelectorsSettings()

Enables row selectors settings from template directive if defined.

Returns : void
Protected setupSelectionSettings
setupSelectionSettings()

Applies grid selection settings from template directive if defined.

Returns : void

{void}

Protected setupSortedColumns
setupSortedColumns()

Synchronize the grid sortingExpressions with the model SortingSettings.

Returns : void

{void}

Protected setupSortingSettings
setupSortingSettings()

Synchronize the grid SortingSettings with the model SortingSettings.

Returns : void

{void}

Protected setupSummarySettings
setupSummarySettings()

Applies grid summary settings from template directive if defined.

Returns : void

{void}

Private shouldInvalidateActiveCell
shouldInvalidateActiveCell(itemsSource1: any)

"If the itemsSource is null or empty, or the active cell's row index is greater than the number of items in the itemsSource, or the active cell's row data is not in the itemsSource, then return true."

Parameters :
Name Type Optional Description
itemsSource1 any No
  • The data source for the grid.
Returns : boolean

The return value is a boolean.

Private shouldReCalcColumnsWidth
shouldReCalcColumnsWidth()

Indicates if the columns width calculation mechanism should be trigger again

Returns : boolean
showErrorMessageOnCell
showErrorMessageOnCell(msg: string, event: IGridEditDoneEventArgs)

Display an error message on the cell asociated with event.

Parameters :
Name Type Optional
msg string No
event IGridEditDoneEventArgs No
Returns : void
sortingDoneHandler
sortingDoneHandler(event: ISortingExpression | ISortingExpression[], singleColumn)

Sorting Done handler, it is called when the sorting is done in the igx-grid The code syncs the sorting expressions with the XamGrid.model.SortingSettings.SortedColumns Also call the columnSorted event.

Parameters :
Name Type Optional Default value
event ISortingExpression | ISortingExpression[] No
singleColumn No true
Returns : void
sortingHandler
sortingHandler(e: any)

Called whenever sorting action is done Avoids the sorting 'None' state

Parameters :
Name Type Optional
e any No
Returns : void
stopClickOutsideCell
stopClickOutsideCell()

If AllowEditing is on Cell type and there is a error message on the active cell, prevent clicks on components in edit mode on table data

Returns : boolean

{boolean}

Protected syncFilteringExpressions
syncFilteringExpressions()

Sets the grid filteringExpressions based on the info of the model.

Returns : void

{void}

synchronizeRowCell
synchronizeRowCell()

Synchronize row

Returns : void
Protected syncSortedColumns
syncSortedColumns()

Sets the grid sortingExpressions based on the model information.

Returns : void

{void}

tabKeyListener
tabKeyListener(event: KeyboardEvent)
Decorators :
@HostListener('keydown', ['$event'])

Listener for tab keydown event Needs to be done in host listener to trigger even in not editable cells

Parameters :
Name Type Optional
event KeyboardEvent No
Returns : void
Private tabKeyNavigation
tabKeyNavigation(isShift: boolean)

Manages the tab key navigation for the grid cells

Parameters :
Name Type Optional Description
isShift boolean No

if the shift key is being pressed

Returns : void
totalPagingRecordsHandler
totalPagingRecordsHandler()

Returns number of total items.

Returns : number

{number}

updateRowsWithFilterResults
updateRowsWithFilterResults()
Returns : void
validateDataErrorInfo
validateDataErrorInfo(data: any, columnName: string, event: IGridEditDoneEventArgs)

Validates if data implements IDataErrorInfo and checks for errors.

Parameters :
Name Type Optional
data any No
columnName string No
event IGridEditDoneEventArgs No
Returns : void
Public validateLimits
validateLimits(type: XamGridColumnType, result: literal type)

Validate if a new value is within allowed limits for the given type.

Parameters :
Name Type Optional
type XamGridColumnType No
result literal type No
Returns : void

{void}

verifyGridSelections
verifyGridSelections()

Verify grid row selection

Returns : void
Protected alignmentHandler
alignmentHandler()
Inherited from BaseComponent
Defined in BaseComponent:2346

Calculate the values for the grid size behavior from the alignments

Returns : void
Protected assignPendingPropertyValues
assignPendingPropertyValues()
Inherited from BaseComponent
Defined in BaseComponent:2057

Apply pending assignments to properties with property values

Returns : void
calculateActualSize
calculateActualSize(name?: string)
Inherited from BaseComponent
Defined in BaseComponent:1674

If the name is equal to 'calculateActualSize', then call the handlerCalcActualSize function and pass in false to avoid the timer in the function.

memberof BaseComponent

Parameters :
Name Type Optional Description
name string Yes
  • The name of the event. memberof BaseComponent
Returns : void
Protected checkAndRegisterCompatibilityBinding
checkAndRegisterCompatibilityBinding(property: DependencyProperty, bindingObjectCandidate: any)
Inherited from BaseComponent
Defined in BaseComponent:2023

Verifies if the given object (bindingObjectCandidate) is a binding object. If so the binding will be registered.

Parameters :
Name Type Optional
property DependencyProperty No
bindingObjectCandidate any No
Returns : boolean

{boolean} true if the value is a binding info object and if the binding was registered, false if not

Protected checkForStaticResource
checkForStaticResource(property: string, value: any)
Inherited from BaseComponent
Defined in BaseComponent:2043

Checks if the given value is a static resource reference or not, if a reference then the value is queue for later assignment.

Parameters :
Name Type Optional Description
property string No

the name of the property to check for

value any No

the property value

Returns : boolean

true if the value is a static resource reference, otherwise false

checkStaticItemInModelCollection
checkStaticItemInModelCollection(collection: any, itemToCheck: any)
Inherited from BaseComponent
Defined in BaseComponent:1889

Checks if the element exists previously in the items collection

Parameters :
Name Type Optional Description
collection any No

The control items collection

itemToCheck any No

The static element to be reviewed

Returns : number

number Returns -1 if the item is not present in the items collection otherwise the index value

createElementInRoot
createElementInRoot(injector: Injector, componentToCreate: any)
Inherited from BaseComponent
Defined in BaseComponent:2698

Create a given component on the HTML body.

Parameters :
Name Type Optional
injector Injector No
componentToCreate any No
Returns : ComponentRef<any>
cursorStyle
cursorStyle()
Inherited from BaseComponent
Defined in BaseComponent:1549

Returns the correct CSS cursor style and sets the definedCursor flag if necessary

Returns : string

{string}

detectChanges
detectChanges()
Inherited from BaseComponent
Defined in BaseComponent:813

Performs a single detect Changes over the component

Returns : void
detectChangesAction
detectChangesAction()
Inherited from BaseComponent
Defined in BaseComponent:1686

Handle subscription to the notifyDetectChanges action Refresh the component whenever a model modification was performed

Returns : void
getForeground
getForeground()
Inherited from BaseComponent
Defined in BaseComponent:1966

Calculates the Foreground color to be applied

Returns : string

string

getImageString
getImageString(value: any)
Inherited from BaseComponent
Defined in BaseComponent:2221

Returns string path to the image.

Parameters :
Name Type Optional
value any No
Returns : any
getTargetValue
getTargetValue(e: Event)
Inherited from BaseComponent
Defined in BaseComponent:2239

Returns the value from a $event

Parameters :
Name Type Optional
e Event No
Returns : string
Protected handlerCalcActualSize
handlerCalcActualSize(async: boolean)
Inherited from BaseComponent
Defined in BaseComponent:2391

Handler that calculates ActualHeight & ActualWidth based on its inner content.

Parameters :
Name Type Optional
async boolean No
Returns : void
heightCalc
heightCalc()
Inherited from BaseComponent
Defined in BaseComponent:1939

Applies the height CSS value

Returns : any
heightDefaultStyle
heightDefaultStyle()
Inherited from BaseComponent
Defined in BaseComponent:1914

Calculates the auto height value

Returns : string

{string}

Protected hostHorizontalAlignmentCall
hostHorizontalAlignmentCall()
Inherited from BaseComponent
Defined in BaseComponent:2374

Assign all the horizontal bindings for the control

Returns : void
Protected hostVerticalAlignmentCall
hostVerticalAlignmentCall()
Inherited from BaseComponent
Defined in BaseComponent:2357

Assign all the vertical bindings for the control

Returns : void
imageToPath
imageToPath(value: any)
Inherited from BaseComponent
Defined in BaseComponent:2202

Returns the path of the given image.

Parameters :
Name Type Optional
value any No
Returns : any
loadStaticItems
loadStaticItems(staticItems: any, itemsCollection: any)
Inherited from BaseComponent
Defined in BaseComponent:1634
Parameters :
Name Type Optional Description
staticItems any No

The static elements to be added

itemsCollection any No

The control items collection

Returns : void

void

Private markForCheckComp
markForCheckComp()
Inherited from BaseComponent
Defined in BaseComponent:2451

Marks current component

Returns : void
mouseEnterHandler
mouseEnterHandler(event: any)
Inherited from BaseComponent
Defined in BaseComponent:1982

Event Handler for when the mouse enter the Image component.

Parameters :
Name Type Optional Description
event any No
  • event from the DOM event
Returns : void
mouseLeaveHandler
mouseLeaveHandler(event: any)
Inherited from BaseComponent
Defined in BaseComponent:2001

Event Handler for when the mouse enter the Image component.

Parameters :
Name Type Optional Description
event any No
  • event from the DOM event
Returns : void
Public ngOnChanges
ngOnChanges()
Inherited from BaseComponent
Defined in BaseComponent:824

Angular Lifecycle Hooks

Returns : void
preventItemsDuplication
preventItemsDuplication(itemsToRender: any, items: any, contentChildTemplate: any, afterContentInitCalled: boolean, injector: Injector)
Inherited from BaseComponent
Defined in BaseComponent:2170

Validates if coming models are the same, and prevents to be recreated on Ribbon DOM. (Needs to be checked, in some statics scenarios RibbonTab, RibbonGroup duplicates items)

Parameters :
Name Type Optional
itemsToRender any No
items any No
contentChildTemplate any No
afterContentInitCalled boolean No
injector Injector No
Returns : any[]
processAlignments
processAlignments(name: string)
Inherited from BaseComponent
Defined in BaseComponent:1704

Method to check if the component should assign a alignment property

Parameters :
Name Type Optional
name string No
Returns : void

{void}

processCursor
processCursor(name: string)
Inherited from BaseComponent
Defined in BaseComponent:1850

Method to set the cursor style of the component

Parameters :
Name Type Optional
name string No
Returns : void
processCustomCssClasses
processCustomCssClasses(name: string)
Inherited from BaseComponent
Defined in BaseComponent:1723

Method to set custom CSS Clases

Parameters :
Name Type Optional
name string No
Returns : void

{void}

processFocusable
processFocusable(name: string)
Inherited from BaseComponent
Defined in BaseComponent:1816

Method to check and set the height of the grid

Parameters :
Name Type Optional
name string No
Returns : void
Private processFontFamily
processFontFamily(name: string)
Inherited from BaseComponent
Defined in BaseComponent:2784

Process the FontFamily property

Parameters :
Name Type Optional
name string No
Returns : any
processFonts
processFonts(name: string)
Inherited from BaseComponent
Defined in BaseComponent:1778

Method to apply the font styles for the component.

Parameters :
Name Type Optional
name string No
Returns : void
Private processFontSize
processFontSize(name: string)
Inherited from BaseComponent
Defined in BaseComponent:2798

Process the FontSize property

Parameters :
Name Type Optional
name string No
Returns : any
Private processFontStyle
processFontStyle(name: string)
Inherited from BaseComponent
Defined in BaseComponent:2815

Process the FontStyle property

Parameters :
Name Type Optional
name string No
Returns : any
Private processFontWeight
processFontWeight(name: string)
Inherited from BaseComponent
Defined in BaseComponent:2832

Process the FontWeight property

Parameters :
Name Type Optional
name string No
Returns : any
processHeights
processHeights(name: string)
Inherited from BaseComponent
Defined in BaseComponent:1797

Method to check and set the height of the grid

Parameters :
Name Type Optional
name string No
Returns : void
processIsEnabled
processIsEnabled(name: string)
Inherited from BaseComponent
Defined in BaseComponent:1764

Process changes to IsEnabled property.

Parameters :
Name Type Optional
name string No
Returns : void
processOpacity
processOpacity(name: string)
Inherited from BaseComponent
Defined in BaseComponent:1751

Method to apply the opacity for the component.

Parameters :
Name Type Optional
name string No
Returns : void
processVisibility
processVisibility(name: string)
Inherited from BaseComponent
Defined in BaseComponent:1737

Method to check if the component should be show or hide.

Parameters :
Name Type Optional
name string No
Returns : void
processWidths
processWidths(name: string)
Inherited from BaseComponent
Defined in BaseComponent:1829

Method to check and set the width of the grid

Parameters :
Name Type Optional
name string No
Returns : void
Private processZIndex
processZIndex(name: string)
Inherited from BaseComponent
Defined in BaseComponent:1872

Method to process the ZIndex when set through the model

Parameters :
Name Type Optional
name string No
Returns : void
Private recreateInvalidBindings
recreateInvalidBindings()
Inherited from BaseComponent
Defined in BaseComponent:2756

Execution of removeModelProxyHandlers in a previous instance of the component (that used the same model) could have set some bindings in an invalid state, this will check if some of them has to be recreated

Returns : void
Private registerContextMenuActions
registerContextMenuActions(ctxMenu: ContextMenuManager)
Inherited from BaseComponent
Defined in BaseComponent:2533

Enable the contextMenu actions to be displayed when the user perform an action Creates dinamically a new instance of XamContextMenu to be displayed in the screen

Parameters :
Name Type Optional
ctxMenu ContextMenuManager No
Returns : void
Protected registerDomEventListenerOnElement
registerDomEventListenerOnElement(eventName: string, handler: any)
Inherited from BaseComponent
Defined in BaseComponent:2316

Registers a DOM handler on the current element

Parameters :
Name Type Optional
eventName string No
handler any No
Returns : void
Protected registerHandler
registerHandler(event: SubscriptionEvent<void>, arrowHandler: (s: any,a: any) => void)
Inherited from BaseComponent
Defined in BaseComponent:2298

Register arrow handler into the given SubscriptionEvent with unregister handling when component destroy.

Parameters :
Name Type Optional
event SubscriptionEvent<void> No
arrowHandler function No
Returns : void
Protected registerMouseEvents
registerMouseEvents()
Inherited from BaseComponent
Defined in BaseComponent:2272

Registers mouse events if required

Returns : void
Protected registerObservers
registerObservers(emitter: EventEmitter, model: FrameworkElement, event: SubscriptionEvent<void>)
Inherited from BaseComponent
Defined in BaseComponent:2252

Register observers from the given EventEmitter into the given SubscriptionEvent.

Parameters :
Name Type Optional
emitter EventEmitter<any> No
model FrameworkElement No
event SubscriptionEvent<void> No
Returns : void
Private registerToolTip
registerToolTip(element: ElementRef, tooltip: ToolTipModel)
Inherited from BaseComponent
Defined in BaseComponent:2607

Registers a tooltip to a component

Parameters :
Name Type Optional
element ElementRef<any> No
tooltip ToolTipModel No
Returns : void
Private removeModelProxyHandlers
removeModelProxyHandlers()
Inherited from BaseComponent
Defined in BaseComponent:2738

Clean up the handlers when the component is destroyed

Returns : void
Private setComponentForDirectives
setComponentForDirectives()
Inherited from BaseComponent
Defined in BaseComponent:2512

Sets an internal reference through the element ref to access the component in a directive

Returns : void
Protected setPendingPropertyValue
setPendingPropertyValue(property: string, value: any)
Inherited from BaseComponent
Defined in BaseComponent:2336

Stores the pending property values for instance attach properties. Which will be applied when the model is available

Parameters :
Name Type Optional
property string No
value any No
Returns : void
setupDependencyComponents
setupDependencyComponents(model: FrameworkElement)
Inherited from BaseComponent
Defined in BaseComponent:1612

Adds the references to the dependency components

Parameters :
Name Type Optional
model FrameworkElement No
Returns : void
setupModel
setupModel(model: FrameworkElement)
Inherited from BaseComponent
Defined in BaseComponent:1559

Syncs the modelProxy with model

Parameters :
Name Type Optional
model FrameworkElement No
Returns : void

void

Private syncToolTip
syncToolTip(tooltip: ToolTipModel)
Inherited from BaseComponent
Defined in BaseComponent:2587

Updates the tooltip associated to a component

Parameters :
Name Type Optional
tooltip ToolTipModel No
Returns : void
Private syncValidationError
syncValidationError(name?: string)
Inherited from BaseComponent
Defined in BaseComponent:2766

Syncs validation information with component properties

Parameters :
Name Type Optional
name string Yes
Returns : void
Private tabSelectionSubscription
tabSelectionSubscription()
Inherited from BaseComponent
Defined in BaseComponent:2471

Subscribe to the tabhandler event if Required When the component is inside a tab control it should trigger the load event every time the tab is selected

Returns : void
trackByFn
trackByFn(index: any, item: any)
Inherited from BaseComponent
Defined in BaseComponent:1904

Function used by Angular to track elements in the ngFor directive. We use the GUID property to compare elements.

Parameters :
Name Type Optional Description
index any No
  • index of the array
item any No
  • item of the array
Returns : any

{*} -return the model or object itself

Private unregisterToolTip
unregisterToolTip(element: ElementRef)
Inherited from BaseComponent
Defined in BaseComponent:2719

Unregisters a tooltip to a component

Parameters :
Name Type Optional
element ElementRef<any> No
Returns : void
Private updateSizePropertiesForActualSizeChange
updateSizePropertiesForActualSizeChange(element: Element)
Inherited from BaseComponent
Defined in BaseComponent:2421

Updates the size properties of the component based on the initial size change

Parameters :
Name Type Optional Description
element Element No

HTML element

Returns : void
validatesLoadingFlag
validatesLoadingFlag()
Inherited from BaseComponent
Defined in BaseComponent:1519

Validates loading flag for components outside current tab index TabIndexService should be only tabItem provider, and when currentTabId is different from selectedTab IsFirstTimeLoad is set to false because tabService is going to be one in charge to trigger only one time when tab changes.

Returns : void
widthCalc
widthCalc()
Inherited from BaseComponent
Defined in BaseComponent:1953

Applies the width CSS value

Returns : any
widthDefaultStyle
widthDefaultStyle()
Inherited from BaseComponent
Defined in BaseComponent:1926

Calculates the auto width value

Returns : string

{string}

Properties

activeCellChanged
Type : EventEmitter<any>
Default value : new EventEmitter<any>()
Decorators :
@Output()

Active cell event emitter

Private additionalStyles
Type : HTMLStyleElement

The html additional styles elements

addNewRow
Type : AddNewRowSettingsComponent
Decorators :
@ContentChild(AddNewRowSettingsComponent)

Add new row settings if present

addNewRowInheritance
Type : any
Decorators :
@Input()

Input from the extended component to fill the addNewRow in the internal xamGrid

addRowKey
Type : RowType

The addRowKey property

Protected adjustPaginator
Default value : () => {...}

Manipulate the default bottom pager of the grid component to emulate all the values from the PageLocation enumeration.

Parameters :
Name
value
afterCellControlAttached
Type : EventEmitter<any>
Default value : new EventEmitter<any>()
Decorators :
@Output()

Event emitted after the 'new' cells are created

allColumns
Type : ColumnBaseCollection

The all columns collection

allowChangeItemsPerPage
Default value : false

Flags to manage when the button for update the items per page

Protected autosizedColumns
Default value : new Set<IgxColumnComponent>()

Stores the columns which have been autosized during a horizontal scroll event.

Private cachedGridWidth
Type : number
Default value : 0

Cached latest grid width used to determine if the columns should be calculated again

callProcessActiveCellFlag
Default value : false

Flag to determine if we need to call the processActiveCell method

cellClicked
Type : EventEmitter<any>
Default value : new EventEmitter<any>()
Decorators :
@Output()

CellClicked eventEmitter.

cellControlAttached
Type : EventEmitter<any>
Default value : new EventEmitter<any>()
Decorators :
@Output()

Event emitted when 'new' cells are entering the view

cellDoubleClicked
Type : EventEmitter<any>
Default value : new EventEmitter<any>()
Decorators :
@Output()

Double-click eventEmitter.

cellEdited
Type : EventEmitter<any>
Default value : new EventEmitter<any>()
Decorators :
@Output()

Cell edited event emitter

cellEditing
Type : EventEmitter<any>
Default value : new EventEmitter<any>()
Decorators :
@Output()

Cell editing event emitter

cellEnteredEditMode
Type : EventEmitter<any>
Default value : new EventEmitter<any>()
Decorators :
@Output()

CellEnteredEditMode

cellEnteringEditMode
Type : EventEmitter<any>
Default value : new EventEmitter<any>()
Decorators :
@Output()

Cell enter edit mode

cellExitedEditMode
Type : EventEmitter<any>
Default value : new EventEmitter<any>()
Decorators :
@Output()

Cell exit edit mode

cellExitingEditMode
Type : EventEmitter<any>
Default value : new EventEmitter<any>()
Decorators :
@Output()

Cell exiting edit mode eventEmitter

cellSelectionChange
Type : EventEmitter<IGridCellEventArgs>
Default value : new EventEmitter<IGridCellEventArgs>()
Decorators :
@Output()

cellSelectionChanged eventEmitter.

cellStyleEnabled
Default value : false
Decorators :
@Input()

Flag which indicates if the cell styling is enabled

Protected cellsWithValidationMsg
Default value : new Set<any>()

Cells which have a validation message attached.

collectionHandler
Type : any

Handler for the subscriptionEvent

columnContentTemplate
Type : QueryList<any>
Decorators :
@ContentChildren('columnContentTemplate')

Query list of customColumn content.

columnFiltered
Type : EventEmitter<any>
Default value : new EventEmitter<any>()
Decorators :
@Output()

Column filtering eventEmitter

columnFixed
Type : EventEmitter<any>
Default value : new EventEmitter<any>()
Decorators :
@Output()

Column fixed eventEmitter.

columnFixedStateChanged
Type : EventEmitter<any>
Default value : new EventEmitter<any>()
Decorators :
@Output()

column fixed state changed eventEmitter

Public columnLayout
Type : XamColumnLayoutComponent
Decorators :
@ContentChild(XamColumnLayoutComponent)

Column layout component if present

columnLayoutInheritance
Type : any
Decorators :
@Input()

Input from the extended component to fill the ColumnLayout in the internal xamGrid

Protected columnLayoutModels
Type : SimpleDictionary<any | XamGridModel>

Columns layout models dictionay

Protected columnMoving
Type : ColumnMovingSettingsComponent
Decorators :
@ContentChild(ColumnMovingSettingsComponent)

Column moving settings component if present

columnResized
Type : EventEmitter<any>
Default value : new EventEmitter<any>()
Decorators :
@Output()

Column resized eventEmitter.

columnResizing
Type : EventEmitter<any>
Default value : new EventEmitter<any>()
Decorators :
@Output()

Column resizing eventEmitter

columnSelectionChanged
Type : EventEmitter<IColumnSelectionEventArgs>
Default value : new EventEmitter<IColumnSelectionEventArgs>()
Decorators :
@Output()

columnSelectionChange event emitter.

columnSorted
Type : EventEmitter<any>
Default value : new EventEmitter<any>()
Decorators :
@Output()

Event emitted when a column has done applying a sorting

columnSorting
Type : EventEmitter<any>
Default value : new EventEmitter<any>()
Decorators :
@Output()

Column sorting eventEmitter.

defaultBorderColor
Type : string
Default value : '#A3AEB9'

Default XamGrid border color

Private differ
Type : IterableDiffer<XamGridColumnComponent>

The iterable differ for the XamGridColumnComponents

Protected disabledEventsHandler
Default value : () => {...}

Disables default browser behavior for events, and stops propagation through the DOM tree.

Parameters :
Name
event
Public editing
Type : EditingSettingsComponent
Decorators :
@ContentChild(EditingSettingsComponent)

Editing settings component if present

editingInheritance
Type : EditingSettingsComponent
Decorators :
@Input()

Input from the extended component to fill the addNewRow in the internal xamGrid

Protected eventManager
Type : XamDataGridEventManager

Event manager to change the order of certain events

filterCellTooltip
Type : string
Decorators :
@Input()

Custom input of xam grid component to add tooltip message to each filter column. Note: Every FilterRowCellControl is going to have the same tooltip, if an specific tooltip should be set to an specific FilterRowCellControl please add new functionality.

Private filteredExpressionsHandler
Type : any

Handler for the subscriptionEvent of the filteredExpressions

Protected filtering
Type : FilteringSettingsComponent
Decorators :
@ContentChild(FilteringSettingsComponent)

Filtering settings component if present

filteringExpressions
Type : IFilteringExpression[] | FilteringExpressionsTree
Default value : []

Filtering settings for the grid

Private footerStylePlan
Type : StylePlan

Plan to apply columns footer style.

Private forcedColumnsWidthCalc
Default value : false

Forces the calculation of the columns width

gridColumnLayout
Type : XamGridComponent
Decorators :
@ViewChild('gridColumnLayout')

reference to the internal xamGrid used to replicate the columnLayout feature

Public gridColumnLayouts
Type : QueryList<XamGridComponent>
Decorators :
@ViewChildren('gridColumnLayout')

The internal grid for columnLayout section.

gridColumns
Type : QueryList<XamGridColumnComponent>
Default value : new QueryList<XamGridColumnComponent>()
Decorators :
@ContentChildren(XamGridColumnComponent, {read: XamGridColumnComponent, descendants: true})

Query list with XamGridColumnComponent.

gridColumnsInheritance
Type : any
Decorators :
@Input()

Input from the extended component to fill the grid columns in the internal xamGrid

Public gridComponent
Type : XamGridComponent
Decorators :
@ViewChild(XamGridComponent)

Reference to the component itself in case the control is inherit.

Public gridRef
Type : IgxGridComponent
Decorators :
@ViewChild('grid', {read: IgxGridComponent})

The underlying Angular igx-grid instance.

initializeRow
Type : EventEmitter<any>
Default value : new EventEmitter<any>()
Decorators :
@Output()

Event emitted when the row is initialized

Protected internalData
Type : Array<any>

Array with data.

Protected internalDataWrapper
Type : []
Default value : []

Component's collection wrapper that includes a primary key definition that allows the grid to be edited

internalXamGrid
Type : XamGridComponent
Decorators :
@ViewChild(XamGridComponent)

reference to the internal grid component when the instance is a inherited grid

Private isActiveCellChanged
Default value : false

Flag to determine if the active cell changed in the enterEditHandler

isCellChanged
Type : number
Default value : 0

Value which indicates if a change has occurred in a cell

Private isColumnsWidthSet
Default value : false

Flag to check when the grid has calculated the first column width

isEvaluatingAutoColumns
Default value : false

Flag to indicate when autosize is being calculated for auto columns.

isHandlingCollectionChanges
Default value : false

Flag to indicate when RowCollectionHandler is executing.

isScrollingHorizontal
Default value : false

Flag to avoid consecutive horizontal scroll events triggered.

isScrollingVertical
Type : any

Flag timer to avoid consecutive vertical scroll events triggered

isTabKeyNavigating
Default value : false

Flags that allow navigating throw cells in edit mode event when there are validation errors

itemsSourceChange
Type : EventEmitter<any>
Default value : new EventEmitter<any>()
Decorators :
@Output()

Event emitter for two-way binding of the itemsSource property.

keyDown
Type : EventEmitter<any>
Default value : new EventEmitter<any>()
Decorators :
@Output()

KeyDown eventEmitter.

lastSortingExpression
Type : ISortingExpression[]

Keeps a reference to last sorting expression to avoid 'None' state

loaded
Type : EventEmitter<any>
Default value : new EventEmitter<any>()
Decorators :
@Output()
Inherited from BaseComponent
Defined in BaseComponent:856

Event emitted when the grid is done loading in the DOM

Public model
Type : XamGridModel
Decorators :
@Input()

Object with XamGridComponent properties and events.

Protected modelProxy
Default value : ModelProxy.create<XamGridModel>()
Inherited from BaseComponent
Defined in BaseComponent:1475

The model proxy of XamGridModel

newItemsPerPage
Type : string

New value for items per page.

nextColumnWithErrors
Type : null
Default value : null

Stores the name of the following column with errors

pageIndexChanged
Type : EventEmitter<PageChangedEventArgs>
Default value : new EventEmitter<PageChangedEventArgs>()
Decorators :
@Output()

Page changed event emitter

pageIndexChanging
Type : EventEmitter<CancellablePageChangingEventArgs>
Default value : new EventEmitter<CancellablePageChangingEventArgs>()
Decorators :
@Output()

Page changing event emitter

Protected pagination
Type : PagerSettingsComponent
Decorators :
@ContentChild(PagerSettingsComponent)

Pagination settings component if present

refreshRowsFilteredTimer
Type : any

Flag timer to avoid consecutive update of rows filtered

refreshRowsTimer
Type : any

Semaphore timer to avoid consecutive refresh of Rows structure

rendered
Type : EventEmitter<any>
Default value : new EventEmitter<any>()
Decorators :
@Output()

XamGrid rendered eventEmitter.

renderedCalled
Default value : false

Flag which indicates if the rendered have been called.

Private requiredSpecialValuesSizeReCalc
Default value : false

Forces the calculation of the columns width for special values

Protected resizing
Type : ColumnResizingSettingsComponent
Decorators :
@ContentChild(ColumnResizingSettingsComponent)

Column resizing settings component if present

resolvedCellControlContent
Type : XamGridCellControl[]
Default value : []

Registry of XamGridCellControl which have resolved the content This registry is used to reset the herarchy with the cell template control when scrolling or updated to avoid reference from the control the wrong template

rowAdded
Type : EventEmitter<any>
Default value : new EventEmitter<any>()
Decorators :
@Output()

Row added event emitter

rowDeleted
Type : EventEmitter<any>
Default value : new EventEmitter<any>()
Decorators :
@Output()

Row deleted event emitter

rowEnteredEditMode
Type : EventEmitter<any>
Default value : new EventEmitter<any>()
Decorators :
@Output()

Row entered edit mode

rowExitedEditMode
Type : EventEmitter<any>
Default value : new EventEmitter<any>()
Decorators :
@Output()

Row exit edit mode

Protected rowLimitNoVirtualization
Type : number
Default value : 2000

Value to limit how many rows are rendered in the DOM when no virtualization is applied This value affects the performance of the grid

Protected rowSelectors
Type : RowSelectorSettingsComponent
Decorators :
@ContentChild(RowSelectorSettingsComponent)

Row selectors settings component if present

selectedRowChange
Type : EventEmitter<any>
Default value : new EventEmitter<any>()
Decorators :
@Output()

Event emitter for two-way binding of the selectedRow property.

selectedRowsCollectionChanged
Type : EventEmitter<literal type>
Default value : new EventEmitter<{ sender: XamGridModel; e: SelectionCollectionChangedEventArgs<any>; }>()
Decorators :
@Output()

rowSelectionChange eventEmitter.

selectedRowsCollectionHandler
Type : any

Selected rows collection handler

Protected selection
Type : SelectionSettingsComponent
Decorators :
@ContentChild(SelectionSettingsComponent)

Selection settings component if present

sortedColumnsHandler
Type : any

Handler for the subscriptionEvent of the SortedColumns

sorting
Type : SortingSettingsComponent
Decorators :
@ContentChild(SortingSettingsComponent)

Sorting settings component if present

sortingExpressions
Type : ISortingExpression[]
Default value : []

Sorting settings for the grid

sortingSettingInheritance
Type : SortingSettingsComponent
Decorators :
@Input()

Sorting settings from the extended component.

styleChanged
Default value : false

Flag used to indicate when a row or cell change their style.

Protected summary
Type : SummarySettingsComponent
Decorators :
@ContentChild(SummarySettingsComponent)

Summary settings component if present

toast
Type : IgxToastComponent
Default value : null
Decorators :
@ViewChild(IgxToastComponent)

reference to the internal xamGrid used to replicate the columnLayout feature

Private toleranceGridColumnWidth
Type : number
Default value : 18

Tolerance of grid columns width mechanism

unloaded
Type : EventEmitter<any>
Default value : new EventEmitter<any>()
Decorators :
@Output()

Event emitted when the grid is unloading the component

validationErrorFlag
Default value : false

Checks if an error state.

xamTextFilters
Default value : XamGridCustomFilterOperands.instance()

Additional string filter conditions for the Xam grid.

actualSizeCalled
Default value : false
Inherited from BaseComponent
Defined in BaseComponent:481

Flag to know if the Angular event was called

afterContentInitCalled
Default value : false
Inherited from BaseComponent
Defined in BaseComponent:465

Flag to know if the Angular event was called

afterViewCheckedCalled
Default value : false
Inherited from BaseComponent
Defined in BaseComponent:473

Flag to know if the Angular event was called

afterViewInitCalled
Default value : false
Inherited from BaseComponent
Defined in BaseComponent:457

Flag to know if the Angular event was called

Private bindingValidationCallback
Type : function
Inherited from BaseComponent
Defined in BaseComponent:618

Callback for binding validation

bindingValidationError
Type : EventEmitter<any>
Default value : new EventEmitter()
Decorators :
@Output()
Inherited from BaseComponent
Defined in BaseComponent:114

output to emit the new value of the bindingValidationError event

Private cdRefInjection
Type : ChangeDetectorRef
Inherited from BaseComponent
Defined in BaseComponent:659

Change Detector Reference for the component

Private changeDetectionTimer
Type : any
Inherited from BaseComponent
Defined in BaseComponent:668

A timer to debounce changedetection actions

Protected changeDetectorNotifier
Type : ChangeDectionNotifierService
Inherited from BaseComponent
Defined in BaseComponent:576

Change Detection Notifier Service instace.

Private contextMenuUnlistener
Type : function
Inherited from BaseComponent
Defined in BaseComponent:676

Context Menu event unlisten action.

Private ctxMenuInstance
Type : any
Inherited from BaseComponent
Defined in BaseComponent:630

Reference to the ctxMenuInstance

customCssClasses
Type : string
Default value : null
Decorators :
@HostBinding('class')
Inherited from BaseComponent
Defined in BaseComponent:407

Applies custom CSS classes

Private customTooltipInstance
Type : any
Default value : null
Inherited from BaseComponent
Defined in BaseComponent:641

Reference to the custom tooltip instance this is used to render a popup with custom elements used when the content value is not a string

dataGridRowHeight
Type : number
Default value : 22
Decorators :
@Input()
Inherited from BaseComponent
Defined in BaseComponent:507

Represents the row height of both the DataGrid and XamGrid components it affects the css and also an internal function that virtualized data, so do not change directly on css, use this variable instead.

Protected domHandlerUnListeners
Type : Array<void>
Inherited from BaseComponent
Defined in BaseComponent:567

A collection (possible undefined) of DOM unlistener functions . That is, functions to de register handlers

fireLoadedSubscription
Type : Subscription
Default value : null
Inherited from BaseComponent
Defined in BaseComponent:449

Flag to control load event for components inside tab control

focusable
Default value : false
Decorators :
@HostBinding('class.focusable')
Inherited from BaseComponent
Defined in BaseComponent:388

Display if the component is focusable or not

Protected handlersToUnregister
Type : Array<>
Default value : []
Inherited from BaseComponent
Defined in BaseComponent:558

handlers to unregister when the component is destroyed

hasDefinedCursor
Default value : false
Decorators :
@HostBinding('class.hasDefinedCursor')
Inherited from BaseComponent
Defined in BaseComponent:415

Applies Defined Cursor class

hostFontFamily
Type : any
Default value : null
Decorators :
@HostBinding('style.font-family')
Inherited from BaseComponent
Defined in BaseComponent:261

Property use it to apply the host binding for the font-family

hostFontSize
Type : any
Default value : null
Decorators :
@HostBinding('style.font-size')
Inherited from BaseComponent
Defined in BaseComponent:270

Property use it to apply the host binding for the font-size

hostFontStyle
Type : any
Default value : null
Decorators :
@HostBinding('style.font-style')
Inherited from BaseComponent
Defined in BaseComponent:279

Property use it to apply the host binding for the font-style

hostFontStyles
Default value : false
Decorators :
@HostBinding('class.defaultFontStyles')
Inherited from BaseComponent
Defined in BaseComponent:398

Applies default font styles class, used to allow specificity for each control css

hostFontWeight
Type : any
Default value : null
Decorators :
@HostBinding('style.font-weight')
Inherited from BaseComponent
Defined in BaseComponent:288

Property use it to apply the host binding for the font-weight

hostHeight
Type : string
Default value : null
Decorators :
@HostBinding('style.height')
Inherited from BaseComponent
Defined in BaseComponent:218

Property use it to apply the host binding for the height

hostHozCenter
Default value : false
Decorators :
@HostBinding('class.horizontal-center')
Inherited from BaseComponent
Defined in BaseComponent:308

Applies horizontal alignment left class

hostHozLeft
Default value : false
Decorators :
@HostBinding('class.horizontal-left')
Inherited from BaseComponent
Defined in BaseComponent:298

Applies horizontal alignment left class

hostHozRight
Default value : false
Decorators :
@HostBinding('class.horizontal-right')
Inherited from BaseComponent
Defined in BaseComponent:368

Applies horizontal alignment right class

hostHozSelfAlign
Default value : false
Decorators :
@HostBinding('class.horizontal-selfalign')
@Input()
Inherited from BaseComponent
Defined in BaseComponent:380

Applies horizontal selfalign class. Flags indicates when the control should handle its own horizontal alignment and ignore container alignment.

hostHozStretch
Default value : false
Decorators :
@HostBinding('class.horizontal-stretch')
Inherited from BaseComponent
Defined in BaseComponent:358

Applies horizontal alignment stretch class

hostMaxHeight
Type : number
Decorators :
@HostBinding('style.max-height.px')
Inherited from BaseComponent
Defined in BaseComponent:234

Property used to apply the host binding for max-height

hostMaxWidth
Type : number
Decorators :
@HostBinding('style.max-width.px')
Inherited from BaseComponent
Defined in BaseComponent:210

Property used to apply the host binding for max-width

hostMinHeight
Type : number
Decorators :
@HostBinding('style.min-height.px')
Inherited from BaseComponent
Defined in BaseComponent:226

Property used to apply the host binding for min-height

hostMinWidth
Type : number
Decorators :
@HostBinding('style.min-width.px')
Inherited from BaseComponent
Defined in BaseComponent:202

Property used to apply the host binding for min-width

hostOpacity
Type : any
Default value : null
Decorators :
@HostBinding('style.opacity')
Inherited from BaseComponent
Defined in BaseComponent:252

Property use it to apply the host binding for the opacity

hostVerBottom
Default value : false
Decorators :
@HostBinding('class.vertical-bottom')
Inherited from BaseComponent
Defined in BaseComponent:328

Applies vertical alignment bottom class

hostVerCenter
Default value : false
Decorators :
@HostBinding('class.vertical-center')
Inherited from BaseComponent
Defined in BaseComponent:338

Applies vertical alignment center class

hostVerStretch
Default value : false
Decorators :
@HostBinding('class.vertical-stretch')
Inherited from BaseComponent
Defined in BaseComponent:318

Applies horizontal alignment stretch class

hostVerTop
Default value : false
Decorators :
@HostBinding('class.vertical-top')
Inherited from BaseComponent
Defined in BaseComponent:348

Applies vertical alignment top class

hostVisibility
Type : any
Default value : null
Decorators :
@HostBinding('style.display')
Inherited from BaseComponent
Defined in BaseComponent:243

Property use it to apply the host binding for the visibility

hostWidth
Type : string
Default value : null
Decorators :
@HostBinding('style.width')
Inherited from BaseComponent
Defined in BaseComponent:194

Property use it to apply the host binding for the width

hostZIndex
Type : string
Default value : null
Decorators :
@HostBinding('style.z-index')
Inherited from BaseComponent
Defined in BaseComponent:424

Sets the z-index style.

isInitialized
Type : any
Default value : undefined
Inherited from BaseComponent
Defined in BaseComponent:523

Flag to know if the component is ready to render

isInternalInherit
Default value : false
Inherited from BaseComponent
Defined in BaseComponent:515

Flag which indicates that the component is an internal use for inheritance

layoutUpdated
Type : EventEmitter<any>
Default value : new EventEmitter()
Decorators :
@Output()
Inherited from BaseComponent
Defined in BaseComponent:140

Output to emit when then component's layout is updated.

Protected modelChangeRef
Type : function
Inherited from BaseComponent
Defined in BaseComponent:601

Contains the reference of the function added for handle the model's change

mouseEnter
Type : EventEmitter<literal type>
Default value : new EventEmitter()
Decorators :
@Output()
Inherited from BaseComponent
Defined in BaseComponent:157

Event Emitter. EventEmitter normally called in the mouseEnterHandler.

mouseLeave
Type : EventEmitter<literal type>
Default value : new EventEmitter()
Decorators :
@Output()
Inherited from BaseComponent
Defined in BaseComponent:167

Event Emitter Called in the mouseLeave handler

Private mouseLeaveTooltipUnlistener
Type : function
Default value : null
Inherited from BaseComponent
Defined in BaseComponent:684

Mouse over event for tooltip unlisten action.

mouseLeftButtonUp
Type : EventEmitter<literal type>
Default value : new EventEmitter<any>()
Decorators :
@Output()
Inherited from BaseComponent
Defined in BaseComponent:147

MouseLeftButtonUp event Emitter.

Private mouseMoveTooltipUnlistener
Type : function
Default value : null
Inherited from BaseComponent
Defined in BaseComponent:701

Mouse move event for tooltip unlisten action. This should have a short lifespan, as much as it takes for the tooltip to be shown

Private mouseOverTooltipUnlistener
Type : function
Default value : null
Inherited from BaseComponent
Defined in BaseComponent:692

Mouse over event for tooltip unlisten action.

Protected ngZone
Type : NgZone
Inherited from BaseComponent
Defined in BaseComponent:585

Angular´s NgZone accessor

Protected pendingDependencyPropertyValue
Type : Array<>
Default value : []
Inherited from BaseComponent
Defined in BaseComponent:549

A collection of pending dependency properties values to assign to the model

Protected pendingSetValues
Type : Array<>
Default value : []
Inherited from BaseComponent
Defined in BaseComponent:540

A collection of pending values to assign to the model

Protected renderer2
Type : Renderer2
Inherited from BaseComponent
Defined in BaseComponent:594

Angular´s Renderer2

sizeChanged
Type : EventEmitter<any>
Default value : new EventEmitter()
Decorators :
@Output()
Inherited from BaseComponent
Defined in BaseComponent:132

Output to emit when then component size is changed.

Private sizeChangedPendingTimeout
Type : any
Inherited from BaseComponent
Defined in BaseComponent:610

Timeout id for triggering the sizechanged event

spellCheck
Default value : false
Decorators :
@Input()
Inherited from BaseComponent
Defined in BaseComponent:186

Flag to determinate if the component should do the spell check or not. Default value is false.

staticContent
Type : any
Default value : null
Inherited from BaseComponent
Defined in BaseComponent:432

cache the static content of the control to validate if the current data is not equals.

tabSubscription
Type : Subscription
Default value : null
Inherited from BaseComponent
Defined in BaseComponent:440

TabSelection event subscription

Private tooltipMousePosition
Type : DOMRect
Default value : null
Inherited from BaseComponent
Defined in BaseComponent:710

To track the position of the mouse while the tooltip is being displayed

Private toolTipTimeout
Type : any
Default value : null
Inherited from BaseComponent
Defined in BaseComponent:650

To control the timer to show the tooltip

useCss
Default value : false
Decorators :
@Input()
Inherited from BaseComponent
Defined in BaseComponent:177

Determines if the component uses CSS height/width values, instead of inputs

validationError
Default value : false
Inherited from BaseComponent
Defined in BaseComponent:488

Property to set the validationError class in the component

validationErrorMessage
Type : string
Default value : ''
Inherited from BaseComponent
Defined in BaseComponent:496

Property for specifying validation error message

Accessors

xamGridContext
getxamGridContext()

returns the correct context to call the xam grid methods

childXamGrid
getchildXamGrid()

returns the internal grid component when the inherited grid is different of the columnLayout grid

Returns : XamGridComponent
footerVisibility
getfooterVisibility()

Controls whether to show the column footers if any.

Returns : boolean
setfooterVisibility(value: boolean)
Parameters :
Name Type Optional
value boolean No
Returns : void
editingComponent
geteditingComponent()

Returns the editing instance of the grid from the xam grid or the extended component

autoGenerateColumns
getautoGenerateColumns()

Gets whether the columns of all ColumnLayout objects of this XamGrid should be generated.

Returns : boolean
setautoGenerateColumns(value: boolean)

Sets whether the columns of all ColumnLayout objects of this XamGrid should be generated.

Parameters :
Name Type Optional
value boolean No
Returns : void
collection
getcollection()

The collection of items bound to this grid

Returns : any
name
setname(value: string)

Sets the name model property for the control when the name is an input

Parameters :
Name Type Optional
value string No
Returns : void
selectionSettings
getselectionSettings()

Gets/sets the selection settings for the XamGrid.

Returns : SelectionSettings
setselectionSettings(value: SelectionSettings)
Parameters :
Name Type Optional
value SelectionSettings No
Returns : void
data
getdata()

Gets/set data.

Returns : any
setdata(value: any)
Parameters :
Name Type Optional
value any No
Returns : void
itemsSource
getitemsSource()

Two-way bindable property for the data source of the Xam grid.

Returns : any
setitemsSource(source: any)
Parameters :
Name Type Optional
source any No
Returns : void
headerStyle
getheaderStyle()

Get headerStyle.

setheaderStyle(value)

set headerStyle.

Parameters :
Name Optional
value No
Returns : void
selectedRow
getselectedRow()

Gets/sets the current selected row in the Xam grid.

setselectedRow(row)
Parameters :
Name Optional
row No
Returns : void
virtualHeight
getvirtualHeight()

Sets the grid height to limit how many rows are rendered accepts null value, which will render all rows in the DOM with no scrollbar

setvirtualHeight(value)
Parameters :
Name Optional
value No
Returns : void
borderThickness
getborderThickness()

Gets the border styling of the grid.

setborderThickness(value: string)

Sets the border styling of the grid.

Parameters :
Name Type Optional
value string No
Returns : void
borderBrush
getborderBrush()

Gets the border color of the control.

setborderBrush(value: any)

Sets the border color of the control.

Parameters :
Name Type Optional
value any No
Returns : void
borderStyle
getborderStyle()

Applies the 'solid' style based on the model BorderThickness value.

headersVisibility
getheadersVisibility()

Gets the visibility of the Xam grid columns headers.

Returns : any
setheadersVisibility(value: any)

Sets the visibility of the Xam grid columns headers.

Parameters :
Name Type Optional
value any No
Returns : void
columnWidth
getcolumnWidth()

Gets/sets the ColumnWidth type for the columns of the grid. Runs only on initialization

Returns : ColumnWidth
setcolumnWidth(value: ColumnWidth)
Parameters :
Name Type Optional
value ColumnWidth No
Returns : void
isAlternateRowsEnabled
getisAlternateRowsEnabled()

Gets/sets the isAlternateRowsEnabled, if enabled even rows will display in a different color.

Returns : boolean
setisAlternateRowsEnabled(value: boolean)
Parameters :
Name Type Optional
value boolean No
Returns : void
hasColumnLayout
gethasColumnLayout()

Returns whether the xam grid has a column layout component

shouldAddNewRow
getshouldAddNewRow()

Returns whether the xam grid has a to add the AddNewRow

disableAddNewRow
getdisableAddNewRow()

Returns whether Add new row button should be disabled

Returns : boolean
addNewRowInstance
getaddNewRowInstance()

Returns the AddNewRow Instance from the current or inherited component

sortingComponent
getsortingComponent()

Returns the SortingSettingsComponent instance.

columnLayoutItems
getcolumnLayoutItems()

Returns the columnLayout collection

gridColumnsItems
getgridColumnsItems()

Returns the columns collection

columnsToRender
getcolumnsToRender()

Returns columns to be rendered.

Returns : any
Columns
getColumns()

Returns columns from the model.

Rows
getRows()

Returns the rows from the model.

grid
getgrid()

Returns the IgxGridComponent reference.

Returns : IgxGridComponent
inEditMode
getinEditMode()

Returns whether the grid is currently in edit mode.

visibleColumns
getvisibleColumns()

Returns the currently visible columns.

Returns : IgxColumnComponent[]
isFilteredSortedData
getisFilteredSortedData()

Returns if the grid has any filterable or sortable column

Returns : boolean
filteringExpressionsTree
getfilteringExpressionsTree()

Get the filteringExpressions as IFilteringExpressionsTree

setfilteringExpressionsTree(value: IFilteringExpressionsTree)

Get the filteringExpressions as IFilteringExpressionsTree

Parameters :
Name Type Optional
value IFilteringExpressionsTree No
Returns : void
filteringSettingsEnabled
getfilteringSettingsEnabled()

Returns true if the FilteringSettings.AllowFiltering is enabled, otherwise false.

Returns : boolean
isGridVisible
getisGridVisible()

Validates is the grid is already rendered on screen

Returns : boolean
wmFilterApplied
getwmFilterApplied()

Explicit mark to be added to the grid to indicate the type of filtering being applied, so custom code can do css rules customizations, possible values are: none|excelStyleFilter|quickFilter

Returns : string
selectRowOnClick
getselectRowOnClick()

Select true if CellClickAction is SelectRow

Returns : boolean
import { DOCUMENT } from '@angular/common';
import {
  AfterContentInit,
  AfterViewChecked,
  AfterViewInit,
  ChangeDetectorRef,
  Component,
  ComponentFactoryResolver,
  ContentChild,
  ContentChildren,
  DoCheck,
  ElementRef,
  EventEmitter,
  HostListener,
  Inject,
  Injector,
  Input,
  IterableDiffer,
  IterableDiffers,
  OnDestroy,
  OnInit,
  Output,
  QueryList,
  ViewChild,
  ViewChildren,
} from '@angular/core';
import {
  AddNewRow,
  AllowToolTips,
  AngularComponentId,
  BeginEditingCellEventArgs,
  CancellablePageChangingEventArgs,
  CellBase,
  CellClickedEventArgs,
  CellControlAttachedEventArgs,
  CellExitedEditingEventArgs,
  CellSelectionAction,
  CollectionChangeAction,
  CollectionChangeInfo,
  ColumnBaseCollection,
  ColumnWidth,
  ColumnWidthType,
  ComponentId,
  DependencyPropertyChangedEventArgs,
  DoesNotEndWithOperand,
  DoesNotStartWithOperand,
  EditingCellEventArgs,
  EditingRowEventArgs,
  ExitEditingCellEventArgs,
  FixedState,
  GroupColumnsCollection,
  InitializeRowEventArgs,
  IRecordFilter,
  iuAny,
  iuCount,
  iuFirstOrDefault,
  iuWhere,
  ModelProxy,
  MouseEditingAction,
  out,
  PageChangedEventArgs,
  PagingLocation,
  ReflectionHelper,
  RuntimeStyleInfo,
  SelectedRowsCollection,
  SelectionCollectionChangedEventArgs,
  SelectionSettings,
  Setter,
  SimpleDictionary,
  SimpleList,
  smColorToCssColor,
  smTryParseFloat,
  SolidColorBrush,
  SortDirection,
  ThicknessModel,
  UnboundColumnDataContext,
  VirtualCollection,
  XamGridCell,
  XamGridCellControl,
  XamGridCheckboxColumnModel,
  XamGridColumnModel,
  XamGridColumnType,
  XamGridEditingType,
  XamGridGroupColumnModel,
  XamGridModel,
  XamGridRow,
  XamGridTemplateColumnModel,
  XamGridTextColumnModel,
  XamGridUnboundColumnModel,
  XamSelectionMode,
} from '@mobilize/wms-framework';
import {
  CellType,
  ColumnPinningPosition,
  DefaultSortingStrategy,
  FilteringExpressionsTree,
  GridSelectionMode,
  IActiveNodeChangeEventArgs,
  IColumnSelectionEventArgs,
  IFilteringExpression,
  IFilteringExpressionsTree,
  IForOfState,
  IGridCellEventArgs,
  IGridEditDoneEventArgs,
  IGridEditEventArgs,
  IGridKeydownEventArgs,
  IGridScrollEventArgs,
  IgxColumnComponent,
  IgxGridComponent,
  IgxIconService,
  IgxStringFilteringOperand,
  IgxToastComponent,
  IPageEventArgs,
  IPinColumnEventArgs,
  IRowDataEventArgs,
  ISortingExpression,
  RowType,
  SortingDirection,
} from 'igniteui-angular';
import { isEqual } from 'lodash';
import { v4 as uuidv4 } from 'uuid';
import { NotifyCollectionChangedHandler } from '../../utils';
import { XamDataGridEventManager } from '../../utils/event-manager';
import { Utils } from '../../utils/utilities';
import { ValidationHelper } from '../../utils/validation-helper';
import { BaseComponent } from '../base/base.component';
import { XamGridColumnComponent } from '../xam-grid-column/xam-grid-column.component';
import { AddNewRowSettingsComponent } from '../xam-grid-settings/xam-grid-add-row.component';
import { ColumnMovingSettingsComponent } from '../xam-grid-settings/xam-grid-column-moving.component';
import { ColumnResizingSettingsComponent } from '../xam-grid-settings/xam-grid-column-resizing.component';
import { EditingSettingsComponent } from '../xam-grid-settings/xam-grid-editing.component';
import { FilteringSettingsComponent } from '../xam-grid-settings/xam-grid-filtering.component';
import { PagerSettingsComponent } from '../xam-grid-settings/xam-grid-paging.component';
import { RowSelectorSettingsComponent } from '../xam-grid-settings/xam-grid-row-selector.component';
import { SelectionSettingsComponent } from '../xam-grid-settings/xam-grid-selection.component';
import { SortingSettingsComponent } from '../xam-grid-settings/xam-grid-sorting.component';
import { SummarySettingsComponent } from '../xam-grid-settings/xam-grid-summary.component';
import { XamColumnLayoutComponent } from './XamColumnLayout.component';
import { CloneStrategy } from './clone-strategy';
import {
  iconDoesNotEndWith,
  iconDoesNotStartWith,
} from './operatorsIconsString';
import { StylePlan } from './style-plan';

/**
 * The collection of events the xam grid will handle in order to emulate
 * the disabled state.
 */
const DISABLED_EVENTS = [
  'pointerdown',
  'mousedown',
  'pointerenter',
  'mouseenter',
  'pointerup',
  'mouseup',
  'focusin',
  'click',
  'dblclick',
  'contextmenu',
  'keydown',
];

/**
 * Angular Component for the Xam Grid Control
 *
 * @export
 * @class XamGridComponent
 * @extends {BaseComponent}
 * @implements {OnInit}
 * @implements {AfterContentInit}
 * @implements {OnDestroy}
 */
@Component({
  selector: 'wm-xam-grid',
  templateUrl: './xam-grid.component.html',
  styleUrls: ['./xam-grid.component.scss'],
})
@ComponentId([AngularComponentId.xamGrid])
export class XamGridComponent
  extends BaseComponent
  implements
    OnInit,
    AfterContentInit,
    AfterViewChecked,
    AfterViewInit,
    DoCheck,
    OnDestroy
{
  /**
   * Default XamGrid border color
   *
   * @memberof XamGridComponent
   */
  defaultBorderColor = '#A3AEB9';

  /**
   * Checks if an error state.
   *
   * @memberof XamGridComponent
   */
  validationErrorFlag = false;

  /**
   * Stores the name of the following column with errors
   *
   * @memberof XamGridComponent
   */
  nextColumnWithErrors = null;

  /**
   * reference to the internal grid component when the instance is a inherited grid
   *
   * @type {XamGridComponent}
   * @memberof XamGridComponent
   */
  @ViewChild(XamGridComponent) internalXamGrid: XamGridComponent;

  /**
   * reference to the internal xamGrid used to replicate the columnLayout feature
   *
   * @type {XamGridComponent}
   * @memberof XamGridComponent
   */
  @ViewChild('gridColumnLayout') gridColumnLayout: XamGridComponent;

  /**
   * reference to the internal xamGrid used to replicate the columnLayout feature
   *
   * @type {XamGridComponent}
   * @memberof XamGridComponent
   */
  @ViewChild(IgxToastComponent) toast: IgxToastComponent = null;

  /**
   * Flag used to indicate when a row or cell change their style.
   *
   * @type {boolean}
   * @memberof XamGridComponent
   */
  styleChanged = false;

  /**
   * Flag which indicates if the rendered have been called.
   *
   * @memberof XamGridComponent
   */
  renderedCalled = false;

  /**
   * The addRowKey property
   *
   * @type {RowType}
   * @memberof XamGridComponent
   */
  addRowKey: RowType;

  /**
   * Registry of XamGridCellControl which have resolved the content
   * This registry is used to reset the herarchy with the cell template control
   * when scrolling or updated to avoid reference from the control the wrong template
   *
   * @type {XamGridCellControl[]}
   * @memberof XamGridComponent
   */
  resolvedCellControlContent: XamGridCellControl[] = [];

  /**
   * New value for items per page.
   *
   * @type {number}
   * @memberof XamGridComponent
   */
  newItemsPerPage: string;

  /**
   * Flags to manage when the button for update the items per page
   *
   * @type {boolean}
   * @memberof XamGridComponent
   */
  allowChangeItemsPerPage = false;

  /**
   * Keeps a reference to last sorting expression to avoid 'None' state
   *
   * @type {ISortingExpression[]}
   * @memberof XamGridComponent
   */
  lastSortingExpression: ISortingExpression[];

  /**
   * returns the correct context to call the xam grid methods
   *
   * @readonly
   * @memberof XamGridComponent
   */
  get xamGridContext() {
    return this.childXamGrid ?? this;
  }

  /**
   * returns the internal grid component when the inherited grid is different of the columnLayout grid
   *
   * @readonly
   * @type {XamGridComponent}
   * @memberof XamGridComponent
   */
  get childXamGrid(): XamGridComponent {
    return this.internalXamGrid !== this.gridColumnLayout
      ? this.internalXamGrid
      : null;
  }

  /**
   * Flag which indicates if the cell styling is enabled
   *
   * @memberof XamGridComponent
   */
  @Input() cellStyleEnabled = false;

  /**
   * Controls whether to show the column footers if any.
   *
   * @type {boolean}
   * @memberof XamGridComponent
   */
  @Input() get footerVisibility(): boolean {
    return this.modelProxy.FooterVisibility;
  }

  set footerVisibility(value: boolean) {
    this.modelProxy.FooterVisibility = value;
  }

  /**
   * Custom input of xam grid component to add tooltip message to each filter column.
   * Note: Every FilterRowCellControl is going to have the same tooltip, if an specific
   * tooltip should be set to an specific FilterRowCellControl please add new functionality.
   */
  @Input() filterCellTooltip: string;

  /**
   * Input from the extended component to fill the ColumnLayout in the internal xamGrid
   *
   * @type {*}
   * @memberof XamGridComponent
   */
  @Input() columnLayoutInheritance: any;

  /**
   * Input from the extended component to fill the addNewRow in the internal xamGrid
   *
   * @type {*}
   * @memberof XamGridComponent
   */
  @Input() addNewRowInheritance: any;

  /**
   * Input from the extended component to fill the addNewRow in the internal xamGrid
   *
   * @type {*}
   * @memberof XamGridComponent
   */
  @Input() editingInheritance: EditingSettingsComponent;

  /**
   * Returns the editing instance of the grid from the xam grid or the extended component
   *
   * @readonly
   * @type {EditingSettingsComponent}
   * @memberof XamGridComponent
   */
  get editingComponent(): EditingSettingsComponent {
    return this.editingInheritance ?? this.editing;
  }

  /**
   * Sorting settings from the extended component.
   *
   * @type {SortingSettingsComponent}
   * @memberof XamGridComponent
   */
  @Input() sortingSettingInheritance: SortingSettingsComponent;

  /**
   * Input from the extended component to fill the grid columns in the internal xamGrid
   *
   * @type {*}
   * @memberof XamGridComponent
   */
  @Input() gridColumnsInheritance: any;

  /**
   * Sets whether the columns of all ColumnLayout objects of this XamGrid should be generated.
   *
   * @type {boolean}
   * @memberof XamGridComponent
   */
  @Input() set autoGenerateColumns(value: boolean) {
    this.modelProxy.AutoGenerateColumns = value;
  }

  /**
   * Gets whether the columns of all ColumnLayout objects of this XamGrid should be generated.
   *
   * @type {boolean}
   * @memberof XamGridComponent
   */
  get autoGenerateColumns(): boolean {
    return this.model.AutoGenerateColumns;
  }

  /**
   * The collection of items bound to this grid
   *
   * @readonly
   * @type {*}
   * @memberof XamGridComponent
   */
  get collection(): any {
    return this.data?.internalArray || this.model.ItemsSource || this.data;
  }

  /**
   * Sets the name model property for the control when the name is an input
   *
   * @memberof XamGridComponent
   */
  @Input() set name(value: string) {
    this.modelProxy.Name = value;
  }

  /**
   * Object with XamGridComponent properties and events.
   *
   * @type {DataGrid}
   * @memberof XamGridComponent
   */
  @Input()
  public model: XamGridModel;

  /**
   * CellClicked eventEmitter.
   *
   * @type {EventEmitter<IGridCellEventArgs>}
   * @memberof XamGridComponent
   */
  @Output()
  cellClicked: EventEmitter<any> = new EventEmitter<any>();

  /**
   * cellSelectionChanged eventEmitter.
   *
   * @type {EventEmitter<IGridCellEventArgs>}
   * @memberof XamGridComponent
   */
  @Output()
  cellSelectionChange: EventEmitter<IGridCellEventArgs> = new EventEmitter<IGridCellEventArgs>();

  /**
   * rowSelectionChange eventEmitter.
   *
   * @type {EventEmitter<IRowSelectionEventArgs>}
   * @memberof XamGridComponent
   */
  @Output()
  selectedRowsCollectionChanged: EventEmitter<{
    sender: XamGridModel;
    e: SelectionCollectionChangedEventArgs<any>;
  }> = new EventEmitter<{
    sender: XamGridModel;
    e: SelectionCollectionChangedEventArgs<any>;
  }>();

  /**
   * columnSelectionChange event emitter.
   *
   * @type {EventEmitter<IColumnSelectionEventArgs>}
   * @memberof XamGridComponent
   */
  @Output()
  columnSelectionChanged: EventEmitter<IColumnSelectionEventArgs> = new EventEmitter<IColumnSelectionEventArgs>();

  /**
   * KeyDown eventEmitter.
   *
   * @type {EventEmitter<IRowSelectionEventArgs>}
   * @memberof XamGridComponent
   */
  @Output()
  keyDown: EventEmitter<any> = new EventEmitter<any>();

  /**
   * Double-click eventEmitter.
   *
   * @type {EventEmitter<any>}
   * @memberof XamGridComponent
   */
  @Output()
  cellDoubleClicked: EventEmitter<any> = new EventEmitter<any>();

  /**
   * XamGrid rendered eventEmitter.
   *
   * @type {EventEmitter<IGridCellEventArgs>}
   * @memberof XamGridComponent
   */
  @Output()
  rendered: EventEmitter<any> = new EventEmitter<any>();

  /**
   * Column resized eventEmitter.
   *
   * @type {EventEmitter<IRowSelectionEventArgs>}
   * @memberof XamGridComponent
   */
  @Output()
  columnResized: EventEmitter<any> = new EventEmitter<any>();

  /**
   * Column resizing eventEmitter
   *
   * @type {EventEmitter<any>}
   * @memberof XamGridComponent
   */
  @Output()
  columnResizing: EventEmitter<any> = new EventEmitter<any>();

  /**
   * column fixed state changed eventEmitter
   *
   * @type {EventEmitter<any>}
   * @memberof XamGridComponent
   */
  @Output()
  columnFixedStateChanged: EventEmitter<any> = new EventEmitter<any>();

  /**
   * Event emitted when a column has done applying a sorting
   *
   * @type {EventEmitter<any>}
   * @memberof XamGridComponent
   */
  @Output()
  columnSorted: EventEmitter<any> = new EventEmitter<any>();

  /**
   * Column sorting eventEmitter.
   *
   * @type {EventEmitter<any>}
   * @memberof XamGridComponent
   */
  @Output()
  columnSorting: EventEmitter<any> = new EventEmitter<any>();

  /**
   * Column filtering eventEmitter
   *
   * @type {EventEmitter<any>}
   * @memberof XamGridComponent
   */
  @Output()
  columnFiltered: EventEmitter<any> = new EventEmitter<any>();

  /**
   * Column fixed eventEmitter.
   *
   * @type {EventEmitter<any>}
   * @memberof XamGridComponent
   */
  @Output()
  columnFixed: EventEmitter<any> = new EventEmitter<any>();

  /**
   * Cell enter edit mode
   *
   * @type {EventEmitter<any>}
   * @memberof XamGridComponent
   */
  @Output()
  cellEnteringEditMode: EventEmitter<any> = new EventEmitter<any>();

  /**
   * CellEnteredEditMode
   *
   * @type {EventEmitter<any>}
   * @memberof XamGridComponent
   */
  @Output()
  cellEnteredEditMode: EventEmitter<any> = new EventEmitter<any>();

  /**
   * Cell exiting edit mode eventEmitter
   *
   * @type {EventEmitter<any>}
   * @memberof XamGridComponent
   */
  @Output()
  cellExitingEditMode: EventEmitter<any> = new EventEmitter<any>();

  /**
   * Cell exit edit mode
   *
   * @type {EventEmitter<any>}
   * @memberof XamGridComponent
   */
  @Output()
  cellExitedEditMode: EventEmitter<any> = new EventEmitter<any>();

  /**
   * Row exit edit mode
   *
   * @type {EventEmitter<any>}
   * @memberof XamGridComponent
   */
  @Output()
  rowExitedEditMode: EventEmitter<any> = new EventEmitter<any>();

  /**
   * Row entered edit mode
   *
   * @type {EventEmitter<any>}
   * @memberof XamGridComponent
   */
  @Output()
  rowEnteredEditMode: EventEmitter<any> = new EventEmitter<any>();

  /**
   * Cell editing event emitter
   *
   * @type {EventEmitter<any>}
   * @memberof XamGridComponent
   */
  @Output()
  cellEditing: EventEmitter<any> = new EventEmitter<any>();

  /**
   * Cell edited event emitter
   *
   * @type {EventEmitter<any>}
   * @memberof XamGridComponent
   */
  @Output()
  cellEdited: EventEmitter<any> = new EventEmitter<any>();

  /**
   * Active cell event emitter
   *
   * @type {EventEmitter<any>}
   * @memberof XamGridComponent
   */
  @Output()
  activeCellChanged: EventEmitter<any> = new EventEmitter<any>();

  /**
   * Row added event emitter
   *
   * @type {EventEmitter<any>}
   * @memberof XamGridComponent
   */
  @Output()
  rowAdded: EventEmitter<any> = new EventEmitter<any>();

  /**
   * Row deleted event emitter
   *
   * @type {EventEmitter<any>}
   * @memberof XamGridComponent
   */
  @Output()
  rowDeleted: EventEmitter<any> = new EventEmitter<any>();

  /**
   * Page changing event emitter
   *
   * @type {EventEmitter<CancellablePageChangingEventArgs>}
   * @memberof XamGridComponent
   */
  @Output()
  pageIndexChanging: EventEmitter<CancellablePageChangingEventArgs> = new EventEmitter<CancellablePageChangingEventArgs>();

  /**
   * Page changed event emitter
   *
   * @type {EventEmitter<PageChangedEventArgs>}
   * @memberof XamGridComponent
   */
  @Output()
  pageIndexChanged: EventEmitter<PageChangedEventArgs> = new EventEmitter<PageChangedEventArgs>();

  /**
   * Query list with XamGridColumnComponent.
   *
   * @type {QueryList<XamGridColumnComponent>}
   * @memberof XamGridComponent
   */
  @ContentChildren(XamGridColumnComponent, {
    read: XamGridColumnComponent,
    descendants: true,
  })
  gridColumns: QueryList<XamGridColumnComponent> = new QueryList<XamGridColumnComponent>();

  /**
   * Query list of customColumn content.
   *
   * @type {QueryList<any>}
   * @memberof XamGridComponent
   */
  @ContentChildren('columnContentTemplate')
  columnContentTemplate: QueryList<any>;
  /**
   * Gets/sets the selection settings for the XamGrid.
   *
   * @type {SelectionSettings}
   * @memberof XamGridComponent
   */
  @Input()
  get selectionSettings(): SelectionSettings {
    return this.modelProxy.SelectionSettings;
  }

  set selectionSettings(value: SelectionSettings) {
    this.modelProxy.SelectionSettings = value;
  }

  /**
   * Gets/set data.
   *
   * @type {*}
   * @memberof XamGridComponent
   */
  @Input()
  get data(): any {
    return this.itemsSource;
  }

  set data(value: any) {
    this.itemsSource = value;
  }

  /**
   * Two-way bindable property for the data source of the Xam grid.
   *
   * @type {*}
   * @memberof XamGridComponent
   */
  @Input()
  get itemsSource(): any {
    return this.modelProxy.ItemsSource;
  }

  set itemsSource(source: any) {
    if (
      !this.checkAndRegisterCompatibilityBinding(
        XamGridModel.ItemsSourceProperty,
        source
      )
    ) {
      this.modelProxy.ItemsSource = source;
      this.registerHandlerForObservablesCollection();
    }
  }

  /**
   * Event emitter for two-way binding of the `itemsSource` property.
   *
   * @type {EventEmitter<any>}
   * @memberof XamGridComponent
   */
  @Output()
  itemsSourceChange: EventEmitter<any> = new EventEmitter<any>();

  /**
   * Get headerStyle.
   *
   * @readonly
   * @memberof XamGridComponent
   */
  get headerStyle() {
    return this.model.HeaderStyle;
  }

  /**
   * set headerStyle.
   *
   * @memberof XamGridComponent
   */
  @Input()
  set headerStyle(value) {
    /* istanbul ignore else */
    if (
      !this.checkAndRegisterCompatibilityBinding(
        XamGridModel.HeaderStyleProperty,
        value
      )
    ) {
      this.modelProxy.HeaderStyle = value;
    }
  }

  /**
   * Gets/sets the current selected row in the Xam grid.
   *
   * @memberof XamGridComponent
   */
  @Input()
  get selectedRow() {
    return this.modelProxy.SelectedRow;
  }

  set selectedRow(row) {
    /* istanbul ignore else */
    if (
      !this.checkAndRegisterCompatibilityBinding(
        XamGridModel.SelectedRowProperty,
        row
      )
    ) {
      this.modelProxy.SelectedRow = row;
    }
  }

  /**
   * Event emitter for two-way binding of the `selectedRow` property.
   *
   * @type {EventEmitter<any>}
   * @memberof XamGridComponent
   */
  @Output()
  selectedRowChange: EventEmitter<any> = new EventEmitter<any>();

  /**
   * Event emitted when the grid is done loading in the DOM
   *
   * @type {EventEmitter<any>}
   * @memberof XamGridComponent
   */
  @Output()
  loaded: EventEmitter<any> = new EventEmitter<any>();

  /**
   * Event emitted when the grid is unloading the component
   *
   * @type {EventEmitter<any>}
   * @memberof XamGridComponent
   */
  @Output()
  unloaded: EventEmitter<any> = new EventEmitter<any>();

  /**
   * Event emitted when 'new' cells are entering the view
   *
   * @type {EventEmitter<any>}
   * @memberof XamGridComponent
   */
  @Output()
  cellControlAttached: EventEmitter<any> = new EventEmitter<any>();

  /**
   * Event emitted after the 'new' cells are created
   *
   * @type {EventEmitter<any>}
   * @memberof XamGridComponent
   */
  @Output()
  afterCellControlAttached: EventEmitter<any> = new EventEmitter<any>();

  /**
   * Event emitted when the row is initialized
   *
   * @type {EventEmitter<any>}
   * @memberof XamGridComponent
   */
  @Output()
  initializeRow: EventEmitter<any> = new EventEmitter<any>();

  /**
   * Sets the grid height to limit how many rows are rendered
   * accepts null value, which will render all rows in the DOM with no scrollbar
   *
   * @type {string|null}
   * @memberof XamGridComponent
   */
  @Input()
  get virtualHeight() {
    return this.model.virtualHeight;
  }

  set virtualHeight(value) {
    this.model.virtualHeight = value;
  }

  /**
   * Gets the border styling of the grid.
   *
   * @memberof XamGridComponent
   */
  @Input()
  get borderThickness() {
    /* istanbul ignore next */
    const top = this.model.BorderThickness?.Top;
    /* istanbul ignore next */
    const bottom = this.model.BorderThickness?.Bottom;
    /* istanbul ignore next */
    const left = this.model.BorderThickness?.Left;
    /* istanbul ignore next */
    const right = this.model.BorderThickness?.Right;
    if (top !== 0 || bottom !== 0 || left !== 0 || right !== 0) {
      return `${top}px ${right}px ${bottom}px ${left}px`;
    } else {
      return '1px';
    }
  }

  /**
   * Sets the border styling of the grid.
   *
   * @memberof XamGridComponent
   */
  set borderThickness(value: string) {
    this.modelProxy.BorderThickness = ThicknessModel.parse(value);
  }

  /**
   * Gets the border color of the control.
   *
   * @memberof XamGridComponent
   */
  @Input()
  get borderBrush() {
    /* istanbul ignore else */
    if (
      this.model.BorderBrush != null &&
      this.model.BorderBrush instanceof SolidColorBrush
    ) {
      return smColorToCssColor(this.model.BorderBrush.Color);
    }
    return this.defaultBorderColor;
  }

  /**
   * Sets the border color of the control.
   *
   * @memberof XamGridComponent
   */
  set borderBrush(value: any) {
    this.modelProxy.BorderBrush = Utils.createSolidBrush(value);
  }

  /**
   * Applies the 'solid' style based on the model BorderThickness
   * value.
   *
   * @readonly
   * @memberof XamGridComponent
   */
  get borderStyle() {
    return this.model.BorderThickness ? 'solid' : null;
  }

  /**
   * Sets the visibility of the Xam grid columns headers.
   *
   * @memberof XamGridComponent
   */
  @Input()
  set headersVisibility(value: any) {
    this.modelProxy.HeaderVisibility = value;
    if (value === 'hidden') {
      if (!this.additionalStyles.sheet.cssRules.length) {
        this.additionalStyles.sheet.insertRule(
          'div.igx-grid__thead { display: none !important; }',
          0
        );
      }
      this.additionalStyles.sheet.disabled = false;
    } else {
      this.additionalStyles.sheet.disabled = true;
    }
  }

  /**
   * Gets the visibility of the Xam grid columns headers.
   *
   * @memberof XamGridComponent
   */
  get headersVisibility(): any {
    return this.modelProxy.HeaderVisibility;
  }

  /**
   * Gets/sets the ColumnWidth type for the columns of the grid.
   * Runs only on initialization
   *
   * @type {ColumnWidth}
   * @memberof XamGridComponent
   */
  @Input()
  get columnWidth(): ColumnWidth {
    return this.modelProxy.ColumnWidth;
  }

  set columnWidth(value: ColumnWidth) {
    /* istanbul ignore else */
    if (value) {
      this.modelProxy.ColumnWidth = ColumnWidth.parse(value);
    }
  }

  /**
   * Gets/sets the isAlternateRowsEnabled, if enabled even rows
   * will display in a different color.
   *
   * @type {boolean}
   * @memberof XamGridComponent
   */
  @Input()
  get isAlternateRowsEnabled(): boolean {
    return this.modelProxy.IsAlternateRowsEnabled;
  }

  set isAlternateRowsEnabled(value: boolean) {
    this.modelProxy.IsAlternateRowsEnabled = value;
  }

  /**
   * Returns whether the xam grid has a column layout component
   *
   * @readonly
   * @memberof XamGridComponent
   */
  get hasColumnLayout() {
    return !!this.columnLayout || !!this.columnLayoutInheritance;
  }

  /**
   * Returns whether the xam grid has a to add the AddNewRow
   *
   * @readonly
   * @memberof XamGridComponent
   */
  get shouldAddNewRow() {
    return !!this.addNewRow || !!this.addNewRowInheritance;
  }

  /**
   *  Returns whether Add new row button should be disabled
   *
   * @readonly
   * @memberof XamGridComponent
   */
  get disableAddNewRow(): boolean {
    return !!this.addNewRowInheritance?.disableAddNewRow;
  }

  /**
   * Returns the AddNewRow Instance from the current or inherited component
   *
   * @readonly
   * @memberof XamGridComponent
   */
  get addNewRowInstance(): AddNewRowSettingsComponent | any {
    return this.addNewRow ?? this.addNewRowInheritance;
  }

  /**
   * Returns the SortingSettingsComponent instance.
   *
   * @readonly
   * @type {SortingSettingsComponent}
   * @memberof XamGridComponent
   */
  get sortingComponent(): SortingSettingsComponent {
    return this.sorting ?? this.sortingSettingInheritance;
  }

  /**
   * Returns the columnLayout collection
   *
   * @readonly
   * @memberof XamGridComponent
   */
  get columnLayoutItems(): XamColumnLayoutComponent | any {
    return this.columnLayout ?? this.columnLayoutInheritance;
  }

  /**
   * Returns the columns collection
   *
   * @readonly
   * @memberof XamGridComponent
   */
  get gridColumnsItems() {
    return this.gridColumns.length > 0 || !this.gridColumnsInheritance
      ? this.gridColumns
      : this.gridColumnsInheritance;
  }

  /**
   * Returns columns to be rendered.
   *
   * @readonly
   * @memberof XamGridComponent
   */
  get columnsToRender(): any {
    return this.model.Columns;
  }

  /**
   * Returns columns from the model.
   *
   * @readonly
   * @memberof XamGridComponent
   */
  // eslint-disable-next-line
  get Columns(): ColumnBaseCollection {
    return this.modelProxy.getColumns();
  }

  /**
   * Returns the rows from the model.
   *
   * @readonly
   * @memberof XamGridComponent
   */
  // eslint-disable-next-line
  get Rows() {
    return this.model.Rows;
  }

  /**
   * The underlying Angular `igx-grid` instance.
   *
   * @public
   * @type {IgxGridComponent}
   * @memberof XamGridComponent
   */
  @ViewChild('grid', { read: IgxGridComponent })
  public gridRef: IgxGridComponent;

  /**
   * Reference to the component itself in case the control is inherit.
   *
   * @public
   * @type {XamGridComponent}
   * @memberof XamGridComponent
   */
  @ViewChild(XamGridComponent)
  public gridComponent: XamGridComponent;

  /**
   * Returns the IgxGridComponent reference.
   *
   * @type {IgxGridComponent}
   * @memberof XamGridComponent
   */
  get grid(): IgxGridComponent {
    return this.gridRef ?? this.gridComponent?.gridRef;
  }

  /**
   * Returns whether the grid is currently in edit mode.
   *
   * @readonly
   * @memberof XamGridComponent
   */
  get inEditMode() {
    const service = this.grid.crudService as any;
    return service.cellInEditMode || service.rowInEditMode;
  }

  /**
   * Returns the currently visible columns.
   *
   * @readonly
   * @type {IgxColumnComponent[]}
   * @memberof XamGridComponent
   */
  get visibleColumns(): IgxColumnComponent[] {
    if (!this.grid?.columns) {
      return [];
    }
    return this.grid.columns.filter((col) => col.headerCell != null);
  }

  /**
   * Returns if the grid has any filterable or sortable column
   *
   * @readonly
   * @type {boolean}
   * @memberof XamGridComponent
   */
  get isFilteredSortedData(): boolean {
    return this.grid.hasFilterableColumns || this.grid.hasSortableColumns;
  }

  /**
   * The internal grid for columnLayout section.
   *
   * @public
   * @type {XamGridComponent}
   * @memberof XamGridComponent
   */
  @ViewChildren('gridColumnLayout')
  public gridColumnLayouts: QueryList<XamGridComponent>;

  /**
   * Column layout component if present
   *
   * @public
   * @type {XamColumnLayoutComponent}
   * @memberof XamGridComponent
   */
  @ContentChild(XamColumnLayoutComponent)
  public columnLayout: XamColumnLayoutComponent;

  /**
   * Event manager to change the order of certain events
   *
   * @protected
   * @memberof XamGridComponent
   */
  protected eventManager: XamDataGridEventManager;

  /**
   * Selection settings component if present
   *
   * @protected
   * @type {SelectionSettingsComponent}
   * @memberof XamGridComponent
   */
  @ContentChild(SelectionSettingsComponent)
  protected selection: SelectionSettingsComponent;

  /**
   * Column moving settings component if present
   *
   * @protected
   * @type {ColumnMovingSettingsComponent}
   * @memberof XamGridComponent
   */
  @ContentChild(ColumnMovingSettingsComponent)
  protected columnMoving: ColumnMovingSettingsComponent;

  /**
   * Add new row settings if present
   *
   * @protected
   * @type {AddNewRowSettingsComponent}
   * @memberof XamGridComponent
   */
  @ContentChild(AddNewRowSettingsComponent)
  addNewRow: AddNewRowSettingsComponent;

  /**
   * Editing settings component if present
   *
   * @protected
   * @type {EditingSettingsComponent}
   * @memberof XamGridComponent
   */
  @ContentChild(EditingSettingsComponent)
  public editing: EditingSettingsComponent;

  /**
   * Filtering settings component if present
   *
   * @protected
   * @type {FilteringSettingsComponent}
   * @memberof XamGridComponent
   */
  @ContentChild(FilteringSettingsComponent)
  protected filtering: FilteringSettingsComponent;

  /**
   * Sorting settings component if present
   *
   * @protected
   * @type {SortingSettingsComponent}
   * @memberof XamGridComponent
   */
  @ContentChild(SortingSettingsComponent)
  sorting: SortingSettingsComponent;

  /**
   * Summary settings component if present
   *
   * @protected
   * @type {SummarySettingsComponent}
   * @memberof XamGridComponent
   */
  @ContentChild(SummarySettingsComponent)
  protected summary: SummarySettingsComponent;

  /**
   * Pagination settings component if present
   *
   * @protected
   * @type {PagerSettingsComponent}
   * @memberof XamGridComponent
   */
  @ContentChild(PagerSettingsComponent)
  protected pagination: PagerSettingsComponent;

  /**
   * Column resizing settings component if present
   *
   * @protected
   * @type {ColumnResizingSettingsComponent}
   * @memberof XamGridComponent
   */
  @ContentChild(ColumnResizingSettingsComponent)
  protected resizing: ColumnResizingSettingsComponent;

  /**
   * Row selectors settings component if present
   *
   * @protected
   * @type {RowSelectorSettingsComponent}
   * @memberof XamGridComponent
   */
  @ContentChild(RowSelectorSettingsComponent)
  protected rowSelectors: RowSelectorSettingsComponent;

  /**
   * Handler for the subscriptionEvent of the SortedColumns
   *
   * @type {*}
   * @memberof XamGridComponent
   */
  sortedColumnsHandler: any;

  /**
   * Handler for the subscriptionEvent
   *
   * @type {*}
   * @memberof XamGridComponent
   */
  collectionHandler: any;

  /**
   * Selected rows collection handler
   *
   * @type {*}
   * @memberof XamGridComponent
   */
  selectedRowsCollectionHandler: any;

  /**
   * Semaphore timer to avoid consecutive refresh of Rows structure
   *
   * @type {*}
   * @memberof XamGridComponent
   */
  refreshRowsTimer: any;

  /**
   * Flag to determine if we need to call the processActiveCell method
   *
   * @type {*}
   * @memberof XamGridComponent
   */
  callProcessActiveCellFlag = false;

  /**
   * Flag timer to avoid consecutive vertical scroll events triggered
   *
   * @type {*}
   * @memberof XamGridComponent
   */
  isScrollingVertical: any;

  /**
   * Flag to avoid consecutive horizontal scroll events triggered.
   *
   * @type {any}
   * @memberof XamGridComponent
   */
  isScrollingHorizontal = false;

  /**
   * Flag to indicate when autosize is being calculated for auto columns.
   *
   * @memberof XamGridComponent
   */
  isEvaluatingAutoColumns = false;

  /**
   * Flags that allow navigating throw cells in edit mode event when there are validation errors
   *
   * @memberof XamGridComponent
   */
  isTabKeyNavigating = false;

  /**
   * Flag to indicate when RowCollectionHandler is executing.
   *
   * @memberof XamGridComponent
   */
  isHandlingCollectionChanges = false;

  /**
   * Flag timer to avoid consecutive update of rows filtered
   *
   * @type {*}
   * @memberof XamGridComponent
   */
  refreshRowsFilteredTimer: any;

  /**
   * Additional string filter conditions for the Xam grid.
   *
   * @memberof XamGridComponent
   */
  xamTextFilters = XamGridCustomFilterOperands.instance();

  /**
   * Stores the columns which have been autosized during
   * a horizontal scroll event.
   *
   * @memberof XamGridComponent
   */
  protected autosizedColumns = new Set<IgxColumnComponent>();

  /**
   * Array with data.
   *
   * @type {Array<any>}
   * @memberof XamGridComponent
   */
  protected internalData: Array<any>;

  /**
   * Component's collection wrapper
   * that includes a primary key definition
   * that allows the grid to be edited
   *
   * @protected
   * @memberof XamGridComponent
   */
  protected internalDataWrapper = [];

  /**
   * Columns layout models dictionay
   *
   * @protected
   * @type {SimpleDictionary<any, XamGridModel>}
   * @memberof XamGridComponent
   */
  protected columnLayoutModels: SimpleDictionary<any, XamGridModel>;

  /**
   * The model proxy of XamGridModel
   *
   * @protected
   * @memberof XamGridComponent
   */
  protected modelProxy = ModelProxy.create<XamGridModel>();

  /**
   * Value to limit how many rows are rendered in the DOM when no virtualization is applied
   * This value affects the performance of the grid
   *
   * @protected
   * @type {number}
   * @memberof XamGridComponent
   */
  protected rowLimitNoVirtualization = 2000;

  /**
   * Cells which have a validation message attached.
   *
   * @protected
   * @memberof XamGridComponent
   */
  protected cellsWithValidationMsg = new Set<any>();

  /**
   * The iterable differ for the XamGridColumnComponents
   *
   * @private
   * @type {IterableDiffer<XamGridColumnComponent>}
   * @memberof XamGridComponent
   */
  private differ: IterableDiffer<XamGridColumnComponent>;

  /**
   * The html additional styles elements
   *
   * @private
   * @type {HTMLStyleElement}
   * @memberof XamGridComponent
   */
  private additionalStyles: HTMLStyleElement;

  /**
   * Cached latest grid width used to determine if the columns should be calculated again
   *
   * @private
   * @type {number}
   * @memberof XamGridComponent
   */
  private cachedGridWidth = 0;

  /**
   * Tolerance of grid columns width mechanism
   *
   * @private
   * @type {number}
   * @memberof XamGridComponent
   */
  private toleranceGridColumnWidth = 18;

  /**
   * Forces the calculation of the columns width
   *
   * @private
   * @type {boolean}
   * @memberof XamGridComponent
   */
  private forcedColumnsWidthCalc = false;

  /**
   * Forces the calculation of the columns width for special values
   *
   * @private
   * @type {boolean}
   * @memberof XamGridComponent
   */
  private requiredSpecialValuesSizeReCalc = false;
  /**
   * Flag to determine if the active cell changed in the enterEditHandler
   *
   * @private
   * @type {boolean}
   * @memberof XamGridComponent
   */
  private isActiveCellChanged = false;

  /**
   * Plan to apply columns footer style.
   *
   * @private
   * @type {StylePlan}
   * @memberof XamGridComponent
   */
  private footerStylePlan: StylePlan;

  /**
   * Sorting settings for the grid
   *
   * @readonly
   * @memberof XamGridComponent
   */
  sortingExpressions: ISortingExpression[] = [];

  /**
   * Filtering settings for the grid
   *
   * @readonly
   * @memberof XamGridComponent
   */
  filteringExpressions: IFilteringExpression[] | FilteringExpressionsTree = [];

  /**
   * Get the filteringExpressions as IFilteringExpressionsTree
   * @returns IFilteringExpressionsTree
   * @memberof XamGridComponent
   */
  set filteringExpressionsTree(value: IFilteringExpressionsTree) {
    this.filteringExpressions = value as FilteringExpressionsTree;
  }

  /**
   * Get the filteringExpressions as IFilteringExpressionsTree
   * @returns IFilteringExpressionsTree
   * @memberof XamGridComponent
   */
  get filteringExpressionsTree(): IFilteringExpressionsTree {
    return this.filteringExpressions as IFilteringExpressionsTree;
  }

  /**
   * Handler for the subscriptionEvent of the filteredExpressions
   *
   * @type {*}
   * @memberof XamGridComponent
   */
  private filteredExpressionsHandler: any;

  /**
   * Flag to check when the grid has calculated the first column width
   *
   * @private
   * @type {boolean}
   * @memberof XamGridComponent
   */
  private isColumnsWidthSet = false;

  /**
   * Creates an instance of XamGridComponent.
   *
   * @param {Injector} injector
   * @param {ChangeDetectorRef} cdRef
   * @param {IterableDiffers} differsFactory
   * @param {ComponentFactoryResolver} resolver
   * @param {ElementRef<HTMLElement>} ref
   * @param {*} document
   * @param {IgxIconService} iconService
   * @memberof XamGridComponent
   */
  constructor(
    private injector: Injector,
    private cdRef: ChangeDetectorRef,
    private differsFactory: IterableDiffers,
    private resolver: ComponentFactoryResolver,
    private ref: ElementRef<HTMLElement>,
    @Inject(DOCUMENT) private document,
    private iconService: IgxIconService
  ) {
    super();
    if (this.constructor.name === 'XamGridComponent') {
      this.eventManager = new XamDataGridEventManager(this);
    }
    this.differ = this.differsFactory
      .find([])
      .create<XamGridColumnComponent>(null);
    /* istanbul ignore else */
    if (this.document) {
      this.additionalStyles = document.createElement('style');
      document.head.appendChild(this.additionalStyles);
    }
  }

  /**
   * Gets row from model by key
   *
   * @param {*} rowSelector
   * @param {XamGridComponent} component
   * @returns {XamGridRow}
   * @memberof XamGridComponent
   */
  public getRowFromModelByKey(
    rowSelector: any,
    component: XamGridComponent
  ): XamGridRow {
    if (!component.grid) {
      return null;
    }
    const primaryKey = component.grid.primaryKey;
    if (primaryKey !== undefined && primaryKey !== null) {
      const rowIndex = component.internalDataWrapper.findIndex(
        (row) => row[primaryKey] === rowSelector
      );
      if (rowIndex !== -1) {
        return component.Rows.getItem(rowIndex);
      }
      return null;
    } else {
      return component.Rows.toArray().find((row) => isEqual(row, rowSelector));
    }
  }

  /**
   * Get row from filtered data by key
   *
   * @param {*} rowSelector
   * @returns {XamGridRow}
   * @memberof XamGridComponent
   */
  public getRowFromFilteredDataByKey(rowSelector: any): XamGridRow {
    const primaryKey = this.grid.primaryKey;
    if (primaryKey != null) {
      let rowIndex = -1;
      if (rowSelector instanceof XamGridRow) {
        rowIndex = this.Rows.toArray().findIndex(
          (row) => row.Data == rowSelector.Data
        );
      } else {
        rowIndex = this.grid.filteredSortedData.findIndex(
          (row) => row[primaryKey] === rowSelector
        );
      }

      if (rowIndex !== -1) {
        return this.Rows.getItem(rowIndex);
      }
      return null;
    } else {
      return this.Rows.toArray().find((row) => isEqual(row, rowSelector));
    }
  }

  /**
   * Gets the PagerSettingsComponent reference.
   *
   * @memberof XamGridComponent
   */
  public getPaginationComponent() {
    return this.pagination;
  }

  /**
   * Angular lifecycle hook.
   * Generates column models if needed and adds then to the 'silverlight' model.
   *
   * @memberof XamGridComponent
   */
  ngAfterContentInit() {
    super.ngAfterContentInit();
    if (
      !this.gridColumnsItems.length &&
      this.data?.length &&
      this.autoGenerateColumns
    ) {
      this.generateColumnModels();
    }
    if (this.model.IsFirstTimeLoad) {
      if (this.hasColumnLayout) {
        // Remove the columns from the layout part before populating the model
        const layout = this.columnLayoutItems.columns.toArray();
        const collection = this.gridColumnsItems.filter(
          (each) => !layout.includes(each)
        );
        this.gridColumnsItems.reset(collection);
      }
      this.model.Columns.forEach(
        (item) => (item.ColumnLayout.Grid = this.model)
      );
      if (this.constructor.name === 'XamGridComponent') {
        this.gridColumnsItems.forEach(
          (item) =>
            (item.model.ColumnLayout = this.model.RowsManager.ColumnLayout)
        );
        this.gridColumnsItems
          .filter(
            (item) => !item.model.Parent || item.model.Parent === this.model
          )
          .forEach((item) => this.model.addColumn(item.model));
      }
    }
    this.setupGridSettings();
  }

  /**
   * Returns a new model for the details XamGrid.
   *
   * @param {*} dataItem
   * @returns
   * @memberof XamGridComponent
   */
  populateModel(dataItem: any, index: number) {
    let populateModel: XamGridModel;
    if (!this.columnLayoutModels) {
      this.columnLayoutModels = new SimpleDictionary();
    }
    if (!this.columnLayoutModels.hasKey(dataItem)) {
      populateModel = new XamGridModel();
      populateModel.Parent = this.model;
      this.columnLayoutModels.setItem(dataItem, populateModel);
      this.columnLayoutItems.columns.forEach((col) =>
        populateModel.addColumn(col.model)
      );
      populateModel.SelectionSettings = this.model.SelectionSettings;
      populateModel.FilteringSettings = this.model.FilteringSettings;
    } else {
      populateModel = this.columnLayoutModels.getItem(dataItem);
    }
    if (this.columnLayoutModels.internalArray.length > 0) {
      this.setParentRow(populateModel, index);
    }
    return populateModel;
  }

  /**
   * Angular lifecycle hook.
   *
   * @memberof XamGridComponent
   */
  ngAfterViewInit() {
    super.ngAfterViewInit();
    this.registerHandlerForObservablesCollection();
    this.processFilterCellTooltip();
    this.eventManager?.register();
    // Ignores ignite navigation to set a custom one
    if (this.grid?.navigation) {
      this.grid.navigation.handleNavigation = () => {};
    }
    this.afterViewInitCalled = true;
  }

  /**
   * Angular lifecycle hook.
   *
   * @memberof XamGridComponent
   */
  ngAfterViewChecked() {
    /* istanbul ignore else */
    if (!this.isInternalInherit) {
      this.applyColumnFooterStyles();
    }
  }

  /**
   * Apply footer styles to DOM elements.
   *
   * @memberof XamGridComponent
   */
  applyColumnFooterStyles() {
    const newStylePlan = this.buildFooterStylePlan();
    /* istanbul ignore else */
    if (newStylePlan != null && !newStylePlan.equals(this.footerStylePlan)) {
      newStylePlan.execute();
      this.footerStylePlan = newStylePlan;
    }
  }

  /**
   * Build a footer style plan for the current grid.
   *
   * @return {*}  {StylePlan}
   * @memberof XamGridComponent
   */
  buildFooterStylePlan(): StylePlan {
    const summaryCells = this.ref.nativeElement.querySelectorAll(
      'igx-grid-summary-cell'
    );
    /* istanbul ignore else */
    if (summaryCells.length === 0) {
      return null;
    }
    const stylePlan = new StylePlan();
    const notGroupColumns = this.getAllColumns().internalArray.filter(
      (col) => !(col instanceof XamGridGroupColumnModel)
    );
    for (let i = 0; i < notGroupColumns.length; i++) {
      const col = notGroupColumns[i];
      this.processFooterStyle(stylePlan, summaryCells[i], col.FooterStyle);
    }
    return stylePlan.size > 0 ? stylePlan : null;
  }

  /**
   * Process the given footer style into the style plan.
   *
   * @param {StylePlan} stylePlan
   * @param {Element} element
   * @param {RuntimeStyleInfo} footerStyle
   * @memberof XamGridComponent
   */
  processFooterStyle(
    stylePlan: StylePlan,
    element: Element,
    footerStyle: RuntimeStyleInfo
  ) {
    /* istanbul ignore else */
    if (footerStyle == null) {
      return;
    }
    for (const setter of footerStyle.Setters) {
      /* istanbul ignore else */
      if (
        setter.Property === 'Background' &&
        setter.Value instanceof SolidColorBrush
      ) {
        stylePlan.add(setter, element as HTMLElement);
      } else if (
        setter.Property === 'Foreground' &&
        setter.Value instanceof SolidColorBrush
      ) {
        this.processInnerSpans(stylePlan, element, setter);
      }
    }
  }

  /**
   * Add inner `span` elements into style plan, instead of the given element.
   *
   * @param {StylePlan} stylePlan
   * @param {Element} element
   * @param {Setter} setter
   * @memberof XamGridComponent
   */
  processInnerSpans(stylePlan: StylePlan, element: Element, setter: Setter) {
    element?.querySelectorAll('span').forEach((span) => {
      stylePlan.add(setter, span);
    });
  }

  /**
   * Register a handler for current observableCollection
   *
   * @memberof XamGridComponent
   */
  registerHandlerForObservablesCollection() {
    this.removeItemSourceHandler();
    /* istanbul ignore else */
    if (
      this.data &&
      ReflectionHelper.isInterfaceIsSupported(
        this.data,
        'System.Collections.Specialized.INotifyCollectionChanged'
      )
    ) {
      this.invalidateInternalDataWrapper();
      if (!this.isInternalInherit) {
        this.collectionHandler = this.data.CollectionChanged.insertHandler(
          0,
          this.applyDataUpdate.bind(this.xamGridContext)
        );
      }
    }
  }

  /**
   * Verify grid row selection
   *
   * @memberof XamGridComponent
   */
  verifyGridSelections(): void {
    if (!this.grid) return;
    const selectedIndexes = [];
    // Validates witch rows have indexes greeter than 0
    for (const selected of this.selectionSettings?.SelectedRows.toArray()) {
      const idx = this.isFilteredSortedData
        ? this.getRowIndexFromFilteredData(selected)
        : this.getRowIndex(selected);
      if (idx < 0) {
        this.selectionSettings.SelectedRows.remove(selected);
      } else {
        selectedIndexes.push(idx);
      }
    }
    // Finds the rows keys by index and selects it in the igx-grid
    const rowKeys = [];
    if (this.model.SelectionSettings.RowSelection === XamSelectionMode.None) {
      return;
    }
    selectedIndexes.forEach((x) => {
      const row = this.grid.getRowByIndex(x);
      if (row) {
        rowKeys.push(row.key);
      }
    });

    //cell selection happens by user clicking on a cell (singlor o with Ctrl)
    //or by setting a cell as selected (cell.selected = true), events like changing
    //the items source doesn't necessary clear previous selections, so we will
    //make sure to start with a clean slate
    this.grid.clearCellSelection();
    if (rowKeys.length > 0) {
      this.grid.selectRows(rowKeys, true);
    }
  }

  /**
   * Reassign current grid data. This is required to see changes reflected.
   *
   * @memberof XamGridComponent
   */
  applyDataUpdate(isRendering = false): void {
    if (this.constructor.name !== 'XamGridComponent') {
      return;
    }
    if (this.refreshRowsTimer) {
      clearTimeout(this.refreshRowsTimer);
    }
    this.model.NotifyDataUpdate();
    this.InvalidateSelectionAndActivation();
    this.RowCollectionHandler(isRendering);
  }

  /**
   * Handler used to fill grid data when is required
   *
   * @memberof XamGridComponent
   */
  gridDataHandler() {
    if (this.grid) {
      this.totalPagingRecordsHandler();
      this.grid.endEdit?.(false);
      this.addRowKey = null;
      setTimeout(() => {
        this.verifyGridSelections();
      }, 100);
    }
  }

  /**
   * Returns data
   *
   * @return {any[]}
   * @memberof XamGridComponent
   */
  dataHandler(): any[] {
    // eslint-disable-next-line @typescript-eslint/naming-convention
    this.internalDataWrapper = this.collection?.map((record: any) => ({
      __xam_internal_pk__: uuidv4(),
      data: record,
    }));
    return this.internalDataWrapper;
  }

  /**
   * Angular lifecycle hook.
   * Removes all the event listeners for the disabled overlay.
   *
   * @memberof XamGridComponent
   */
  ngOnDestroy() {
    super.ngOnDestroy();
    const params = this.createEventParams();
    this.model?.ScrolledCellIntoView.removeHandler(
      this.scrollCellIntoViewHandler,
      this
    );
    this.model?.Unloaded.fire([params.sender, params.e]);
    this.unloaded.emit(params);
    /* istanbul ignore else */
    if (typeof this.ref.nativeElement.removeEventListener === 'function') {
      DISABLED_EVENTS.forEach((type) => {
        this.ref.nativeElement.removeEventListener(
          type,
          this.disabledEventsHandler,
          { capture: true }
        );
      });
    }
    this.document?.head?.removeChild(this.additionalStyles);
    this.removeItemSourceHandler();
    this.eventManager?.destroy();
    /* istanbul ignore else */
    if (this.model) {
      this.model.gridComponentInstance = null;
    }
  }

  /**
   * Starts the row adding UI for the XamGrid.
   *
   * @param {number} [index=0]
   * @memberof XamGridComponent
   */
  beginAddRow(index?: number) {
    const isAddTop =
      this.addNewRow?.allowAddNewRow === 'Top' ||
      this.addNewRowInheritance?.allowAddNewRow === 'Top';
    index = index ?? (isAddTop ? 0 : this.grid.dataView.length);
    setTimeout(() => {
      this.grid.beginAddRowByIndex(index);
      this.addRowKey = this.grid.getRowByIndex(index);
    }, 100);
  }

  /**
   * Ends row editing and triggers the event pipeline.
   *
   * @param {boolean} [commit=true]
   * @param {Event} [event]
   * @memberof XamGridComponent
   */
  endRowEdit(commit = true, event?: Event) {
    this.grid.crudService.endRowTransaction(commit, event);
  }

  /**
   * Returns if row is defined
   *
   * @return {*}  {boolean}
   * @memberof XamGridComponent
   */
  rowDefined(): boolean {
    return this.grid?.getRowByIndex(0) !== undefined;
  }

  /**
   * Event emitted when the underlying igx-grid is considered 'ready' in the DOM.
   *
   * @memberof XamGridComponent
   */
  renderedHandler() {
    this.grid.dataCloneStrategy = new CloneStrategy();
    const params = this.createEventParams();
    this.setupDisabledOverlay();
    this.setupRowSelectorsSettings();
    this.setupColumnTracking();
    this.setupCellTracker();
    this.setupAvailableRows();
    this.adjustPagerSettings();

    // Footer workarounds
    /* istanbul ignore else */
    if (this.model.FooterVisibility) {
      this.grid.columns
        .filter((col) => !col.columnGroup)
        .forEach((col) => (col.hasSummary = true));
      this.grid.summaryService.recalculateSummaries();
    }

    // There is a timing issue with the generation of the mocked pks for the bound data source.
    // Since inputs are bound right after the constructor the grid tries to resolve the already bound primaryKey
    // and fails. Thus we setup it here.
    this.grid.primaryKey = '__xam_internal_pk__';
    this.applyDataUpdate(true);
    this.verifyGridSelections();

    this.model.Rendered.fire([params.sender, params.e]);
    this.model.Loaded.fire([params.sender, params.e]);
    this.rendered.emit(params);
    this.loaded.emit(params);
    this.renderedCalled = true;
  }

  /**
   * Renders and rebinds the context for the footers of the Xam grid.
   *
   * @memberof XamGridComponent
   */
  renderFooters() {
    this.gridColumnsItems.forEach((column) => column.setupFooters());
    this.grid.summaryService.recalculateSummaries();
    this.grid.notifyChanges(true);
  }

  /**
   * Called whenever sorting action is done
   * Avoids the sorting 'None' state
   *
   * @param {*} e
   * @memberof XamGridComponent
   */
  sortingHandler(e: any): void {
    // TODO: This code should consider if the click event has the ctrl key pressed,
    // If so, it should conserve the current sorting expressions in the array and add the new one,
    // otherwise, it should clear the sorting expressions and save the last one.
    if (e.sortingExpressions.length > 0) {
      this.columnSortingEventParameters(e);
      this.model.ColumnSorting.fire([this.model, e]);
      this.grid.sortingExpressions = [e.sortingExpressions.at(-1)];
    } else {
      e.cancel = true;
      this.lastSortingExpression[0].dir = SortingDirection.Asc;
      this.grid.sort(this.lastSortingExpression);
    }
  }

  /**
   * The function is called when the user clicks on a column header sorting arrow. It gets the column name from the
   * event and then sets the sorting expression to that column.
   * @param {any} e - any - the sorting event object
   */
  private columnSortingEventParameters(e: any): void {
    this.lastSortingExpression = e.sortingExpressions;
    const key: string = e.sortingExpressions
      .at(-1)
      .fieldName.replace('data.', '');
    e.Column = this.Columns.getColumnByKey(key);
    e.Cancel = e.cancel;
  }

  /**
   * Sorting Done handler, it is called when the sorting is done in the igx-grid
   * The code syncs the sorting expressions with the XamGrid.model.SortingSettings.SortedColumns
   * Also call the columnSorted event.
   *
   * @param {(ISortingExpression | ISortingExpression[])} event
   * @memberof XamGridComponent
   */
  sortingDoneHandler(
    event: ISortingExpression | ISortingExpression[],
    singleColumn = true
  ): void {
    // TODO: We need to determinate if the column is a group of columns (using the CTRL key) or just single column.
    // This code assumes that the sorted column is a single column.
    const params = this.createEventParams();
    if (Array.isArray(event)) {
      singleColumn
        ? this.addColumnFromExpression(event.at(-1))
        : event.map((e) => this.addColumnFromExpression(e));
    } else {
      this.addColumnFromExpression(event);
    }

    // Updating the row collection with the sorted result
    this.updateRowsWithFilterResults();

    this.model.ColumnSorted.fire([params.sender, params.e]);
    this.columnSorted.emit(event);
  }

  /**
   * Handler triggered on scroll event
   * Be aware this event is called several times per scroll
   *
   * @param {IGridScrollEventArgs} event
   * @memberof XamGridComponent
   */
  gridScrollHandler(event: IGridScrollEventArgs): void {
    if (event.direction === 'horizontal' && !this.isScrollingHorizontal) {
      this.isScrollingHorizontal = true;
    } else if (event.direction === 'vertical' && !this.isScrollingVertical) {
      this.isScrollingVertical = setTimeout(() => {
        this.processAllowToolTipsByRow();
        this.isScrollingVertical = undefined;
      }, 5);
    }
  }

  /**
   * Handler triggered after the data has changed
   * Emitted after a data operation, rebinding, pagination, etc
   *
   * @param {any} event
   * @memberof XamGridComponent
   */
  dataChangedHandler(event: any): void {
    // Timeout required to let the grid refresh the items
    setTimeout(() => {
      this.processAllowToolTipsByRow();
    });
  }

  /**
   * Filtering handler
   *
   * @param {IFilteringExpressionsTree} event
   * @memberof XamGridComponent
   */
  filteringHandler(event: IFilteringExpressionsTree) {
    const params = this.createEventParams();
    /* istanbul ignore else */
    if (this.model.FilteringSettings && event.fieldName) {
      const rowFiltersArray =
        this.model.FilteringSettings.RowFiltersCollection.internalArray;
      const idx = rowFiltersArray.findIndex(
        (filter: IRecordFilter) => filter.FieldName === event.fieldName
      );
      if (idx < 0) {
        rowFiltersArray.push({
          Conditions: event.filteringOperands,
          FieldName: event.fieldName,
        });
      } else if (event.filteringOperands.length == 0) {
        rowFiltersArray.splice(idx, 1);
      } else {
        rowFiltersArray[idx].Conditions = event.filteringOperands;
      }

      /* eslint-enable */
    }

    // Updating the row collection with the filtered result
    this.updateRowsWithFilterResults();

    this.model.ColumnFiltered.fire([params.sender, params.e]);
    this.columnFiltered.emit(params);
  }

  updateRowsWithFilterResults(): void {
    /* istanbul ignore else */
    if (this.refreshRowsFilteredTimer) {
      clearTimeout(this.refreshRowsFilteredTimer);
    }
    this.refreshRowsFilteredTimer = setTimeout(() => {
      this.Rows.CollectionChanged.fire([
        this.model,
        new CollectionChangeInfo(CollectionChangeAction.Reset),
      ]);
    }, 20);
  }

  /**
   * Column pinning handler
   *
   * @param {IPinColumnEventArgs} event
   * @memberof XamGridComponent
   */
  pinningHandler(event: IPinColumnEventArgs) {
    const params = this.createEventParams();
    const colKey = event.column.field.replace('data.', '');
    const column = this.getColumnModelByKey(colKey);
    const isStart = this.grid?.pinning?.columns === ColumnPinningPosition.Start;
    const array = isStart
      ? this.model.FixedColumnSettings.FixedColumnsLeft
      : this.model.FixedColumnSettings.FixedColumnsRight;

    /* istanbul ignore else */
    if (column) {
      if (event.isPinned) {
        column.IsFixed = FixedState.NotFixed;
        array.remove(column);
      } else {
        column.IsFixed = isStart ? FixedState.Left : FixedState.Right;
        array.add(column);
      }
    }

    this.model.ColumnFixedStateChanged.fire([params.sender, params.e]);
    this.columnFixed.emit(params);
  }

  /**
   * Row added handler
   *
   * @param {IRowDataEventArgs} event
   * @memberof XamGridComponent
   */
  rowAddedHandler(event: IGridEditEventArgs) {
    if (
      ReflectionHelper.isInterfaceIsSupported(
        this.data,
        'System.Collections.Generic.ICollection`1'
      )
    ) {
      this.data.add(event.newValue.data);
    } else {
      this.data.push(event.rowData.data);
    }
    this.invalidateInternalDataWrapper();

    const row =
      event.rowID === this.addRowKey?.key
        ? this.getAddRow()
        : this.getAddedRow(event);
    const params = [this.model, new EditingRowEventArgs(row)];
    this.model.RowAdded.fire(params);
    // Hide the snackbar after row added
    const hideSnackbar = () =>
      ((
        this.grid.nativeElement.querySelector('igx-snackbar') as HTMLElement
      ).style.visibility = 'hidden');
    setTimeout(hideSnackbar);
  }

  /**
   * Returns the row created from the data
   *
   * @private
   * @param {IGridEditEventArgs} event
   * @memberof XamGridComponent
   */
  private getAddedRow(event: IGridEditEventArgs) {
    const eventRowID = JSON.stringify(event.rowID);
    const rowComponent = this.grid.rowList.find(
      (r) => eventRowID === JSON.stringify(r.key)
    );
    this.createRowFromData(event.newValue, rowComponent?.index);
  }

  /**
   * Row deleted handler
   *
   * @param {IRowDataEventArgs} event
   * @memberof XamGridComponent
   */
  rowDeletedHandler(event: IRowDataEventArgs) {
    const params = this.createEventParams();
    if (
      ReflectionHelper.isInterfaceIsSupported(
        this.data,
        'System.Collections.Generic.ICollection`1'
      )
    ) {
      this.data.remove(event.data.data);
    } else {
      const index = this.data.indexOf(event.data.data);
      this.data.splice(index, 1);
    }
    this.invalidateInternalDataWrapper();
    this.model.RowDeleted.fire([params.sender, params.e]);
    this.rowDeleted.emit(params);
  }

  /**
   * Pagination handler for the control
   *
   * @param {IPageEventArgs} event
   * @memberof XamGridComponent
   */
  paginationHandler(event: IPageEventArgs) {
    const { previous, current } = event;
    const changingEvent = new CancellablePageChangingEventArgs();

    changingEvent.NextPageIndex = current;
    this.model.PageIndexChanging.fire([this.model, changingEvent]);
    this.pageIndexChanging.emit(changingEvent);
    /* istanbul ignore next */
    if (changingEvent.Cancel) {
      event.current = previous;
      return;
    }
    /* istanbul ignore next */
    if (this.model.ItemsSource?.['MoveToPage']) {
      this.model.ItemsSource['PageSize'] = this.model.PagerSettings.PageSize;
      this.model.ItemsSource['MoveToPage'](event.current);
    }

    const changedEvent = new PageChangedEventArgs();
    changedEvent.OldPageIndex = previous;
    this.model.PageIndexChanged.fire([this.model, changedEvent]);
    this.pageIndexChanged.emit(changedEvent);
  }

  /**
   * Flag to know when a style change from the model
   *
   * @memberof XamGridComponent
   */
  cellChanged(): void {
    this.styleChanged = true;
  }

  /**
   * Usable for the grid to know when the style has changed and need to call the AlignmentPipe
   *
   * @memberof XamGridComponent
   */
  public ngAfterContentChecked(): void {
    /* istanbul ignore else */
    if (this.styleChanged) {
      this.styleChanged = false;
      this.isCellChanged += 1;
    }
  }

  /**
   * Angular lifecycle hook. Use to apply the style over the cells and rows
   * In charge of triggering the first and any other re-evaluation of the columns width calculation
   *
   * @memberof XamGridComponent
   */
  public ngDoCheck(): void {
    if (
      !this.grid?.['_init'] &&
      this.afterViewInitCalled &&
      this.isGridVisible &&
      this.cachedGridWidth != null &&
      (!this.isColumnsWidthSet || this.shouldReCalcColumnsWidth())
    ) {
      const reCalcSpecialValues =
        this.requiredSpecialValuesSizeReCalc || !this.isColumnsWidthSet;
      this.setColumnsWidth(reCalcSpecialValues);
      this.isColumnsWidthSet = true;
    }
    /* istanbul ignore else */
    if (this.isScrollingHorizontal && !this.isEvaluatingAutoColumns) {
      this.isScrollingHorizontal = false;
      this.evaluateAutoColumns();
    }
    /* istanbul ignore else */
    if (
      this.validationErrorFlag &&
      this.renderedCalled &&
      !this.isGridVisible
    ) {
      this.grid.endEdit(false);
      this.removeAllErrorMessages();
    }
  }

  /**
   * Initialize model object.
   *
   * @memberof XamGridComponent
   */
  ngOnInit(): void {
    this.model = this.model || new XamGridModel();
    this.setupModel(this.model);
    super.ngOnInit();
    this.registerObservers(
      this.selectedRowsCollectionChanged,
      this.model,
      this.model.SelectedRowsCollectionChanged
    );
    this.registerObservers(
      this.activeCellChanged,
      this.model,
      this.model.ActiveCellChanged
    );
    this.registerObservers(
      this.cellDoubleClicked,
      this.model,
      this.model.CellDoubleClicked
    );
    this.registerObservers(
      this.cellClicked,
      this.model,
      this.model.CellClicked
    );
    this.registerObservers(
      this.cellControlAttached,
      this.model,
      this.model.CellControlAttached
    );
    this.registerObservers(
      this.afterCellControlAttached,
      this.model,
      this.model.AfterCellControlAttached
    );
    this.registerObservers(
      this.cellEnteredEditMode,
      this.model,
      this.model.CellEnteredEditMode
    );
    this.registerObservers(
      this.cellEnteringEditMode,
      this.model,
      this.model.CellEnteringEditMode
    );
    this.registerObservers(
      this.cellExitedEditMode,
      this.model,
      this.model.CellExitedEditMode
    );
    this.registerObservers(this.rowAdded, this.model, this.model.RowAdded);
    this.registerObservers(
      this.rowEnteredEditMode,
      this.model,
      this.model.RowEnteredEditMode
    );
    this.registerObservers(
      this.rowExitedEditMode,
      this.model,
      this.model.RowExitedEditMode
    );
    this.registerObservers(
      this.initializeRow,
      this.model,
      this.model.InitializeRow
    );
    this.registerObservers(
      this.columnResizing,
      this.model,
      this.model.ColumnResizing
    );
    this.registerObservers(
      this.columnFixedStateChanged,
      this.model,
      this.model.ColumnFixedStateChanged
    );
    this.registerObservers(
      this.columnSorted,
      this.model,
      this.model.ColumnSorted
    );
    this.registerObservers(
      this.columnSorting,
      this.model,
      this.model.ColumnSorting
    );
    this.registerObservers(
      this.cellExitingEditMode,
      this.model,
      this.model.CellExitingEditMode
    );
    this.model.ScrolledCellIntoView.addHandler(
      this.scrollCellIntoViewHandler,
      this
    );

    this.iconService.addSvgIconFromText(
      'does-not-end-with',
      iconDoesNotEndWith,
      'filter-icons'
    );
    this.iconService.addSvgIconFromText(
      'does-not-start-with',
      iconDoesNotStartWith,
      'filter-icons'
    );
    this.setupSortedColumns();
    this.setupFilteringExpressions();
    if (this.constructor.name === 'XamGridComponent') {
      this.model.gridComponentInstance = this;
    }
  }

  /**
   * Detects if there are changes on the model.
   *
   * @param {string} [name]
   * @param {*} [args]
   * @memberof XamGridComponent
   */
  modelChangeHandler(name?: string, args?: any) {
    this.processItemSource(name);
    this.processItemsSourceChange(name, args);
    this.processHeaderStyle(name);
    this.processGridSelections(name);
    this.processTriggerExitEditMode(name, args);
    super.modelChangeHandler(name);
  }

  /**
   * Handler for the ScrollIntoView method
   *
   * @param {XamGridCell} cell
   * @memberof XamGridComponent
   */
  scrollCellIntoViewHandler(cell: XamGridCell): void {
    if (cell.Row.Index === -1) return;
    setTimeout(() => {
      this.grid?.navigateTo(cell.Row.Index);
    }, 10);
  }

  /**
   * When SelectedItem is changed verify Grid Selections.
   *
   * @param {string} name
   * @return {*}
   * @memberof XamGridComponent
   */
  processGridSelections(name: string): void {
    /* istanbul ignore else */
    if (name === 'SelectedRowsChanged') {
      setTimeout(() => {
        this.verifyGridSelections();
      }, 150); //Mobilize-Note: change must be reviewed in bug 499127
    }
  }

  /**
   * When itemSource is changed igxGrid reassign the data.
   *
   * @param {string} name
   * @return {*}
   * @memberof XamGridComponent
   */
  processItemSource(name: string): void {
    if (name === undefined || name === 'ItemsSource') {
      this.invalidateInternalDataWrapper();
      this.applyDataUpdate.call(this.xamGridContext);
      /* istanbul ignore else */
      if (name === 'ItemsSource') {
        this.resetScrollPosition();
      }
      this.resetRows();
      this.removeAllErrorMessages();
      this.autosizedColumns.clear();
    }
  }

  /**
   * Apply the style changes for each column.
   *
   * @param {string} name
   * @memberof XamGridComponent
   */
  processHeaderStyle(name: string): void {
    if (name === 'HeaderStyle') {
      this.modelProxy.Columns.forEach(
        (column) => (column.HeaderStyle = this.modelProxy.HeaderStyle)
      );
    }
  }

  /**
   * Process undefined headerstyle for new columns
   *
   * @memberof XamGridComponent
   */
  processDefaultHeaderStyle(): void {
    this.modelProxy.Columns.forEach((column) => {
      /* istanbul ignore else */
      if (!column.HeaderStyle) {
        column.HeaderStyle = this.modelProxy.HeaderStyle;
      }
    });
  }

  /**
   * Unregister and clear `collectionHandler` when `ItemsSource` changes.
   *
   * @param {string} name
   * @param {DependencyPropertyChangedEventArgs} args
   * @memberof XamGridComponent
   */
  processItemsSourceChange(
    name: string,
    args: DependencyPropertyChangedEventArgs
  ) {
    /* istanbul ignore else */
    if (
      name === 'ItemsSourceChanged' &&
      args instanceof DependencyPropertyChangedEventArgs
    ) {
      this.InvalidateSelectionAndActivation();
      /* istanbul ignore else */
      if (
        args.OldValue &&
        ReflectionHelper.isInterfaceIsSupported(
          args.OldValue,
          'System.Collections.Specialized.INotifyCollectionChanged'
        )
      ) {
        args.OldValue.CollectionChanged.removeHandler(this.collectionHandler);
        this.collectionHandler = null;
      }
      /* istanbul ignore else */
      if (
        args.NewValue &&
        ReflectionHelper.isInterfaceIsSupported(
          args.NewValue,
          'System.Collections.Specialized.INotifyCollectionChanged'
        )
      ) {
        if (!this.isInternalInherit) {
          this.collectionHandler = args.NewValue.CollectionChanged.addHandler(
            this.applyDataUpdate.bind(this.xamGridContext)
          );
        }
      }
      this.removeAllErrorMessages();
      this.resetScrollPosition();
      this.autosizedColumns.clear();
    }
  }

  /**
   * Triggers the endEdit for the grid to allow changes to be handled
   *
   * @param {string} name
   * @param {*} commit
   * @memberof XamGridComponent
   */
  processTriggerExitEditMode(name: string, commit: any) {
    /* istanbul ignore else */
    if (name === 'triggerExitEditMode' && typeof commit == 'boolean') {
      this.grid.endEdit(commit);
      this.addRowKey = null;
    }
  }

  /**
   * Validates the selectedRows and update the collection if it's necessary
   * @param {boolean} isSelectingCell - boolean - flag to tell if its selecting a cell
   * while is handling collection changes
   * @memberof XamGridComponent
   * @returns {void}
   */
  InvalidateSelectionAndActivation(isSelectingCell = false): void {
    const collection = new SimpleList<XamGridRow>();
    const itemsSource1: any = this.model.ItemsSource;
    const itemsSourceCount = itemsSource1 ? iuCount(itemsSource1) : 0;
    this.selectionSettings?.SelectedRows?.forEach((item) => {
      if (itemsSourceCount <= item.Index || !itemsSource1.contains(item.Data)) {
        collection.add(item);
      }
    });

    if (collection.count > 0) {
      collection.forEach((item) => {
        this.selectionSettings.SelectedRows.remove(item);
      });
    }
    if (
      this.model.ActiveCell &&
      !(this.model.ActiveCell.Row instanceof AddNewRow) &&
      this.shouldInvalidateActiveCell(itemsSource1) &&
      !this.model.PreventClearActiveCell
    ) {
      this.model.ActiveCell = null;
      this.model.SelectedIndex = null;
      this.model.SelectedColumnIndex = null;
      this.cleanActiveFromIgxGrid();
    }

    if (
      this.gridRef != null &&
      this.isHandlingCollectionChanges &&
      isSelectingCell
    ) {
      this.model.SelectionSettings.SelectedRows.internalArray = [];
      this.gridRef.clearCellSelection();
      this.gridRef.deselectAllRows?.();
    }
  }

  /**
   * Reset the rows
   *
   * @memberof XamGridComponent
   */
  resetRows() {
    if (this.grid) {
      setTimeout(() => {
        this.renderFooters();
      });
    }
  }

  /**
   * Reset the scroll position: vertical scroll resets to top
   * and horizontal scroll resets to left.
   *
   * @memberof XamGridComponent
   */
  resetScrollPosition(): void {
    const firstUnpinnedColumn = this.grid?.columns.find((col) => !col.pinned);
    const firstUnpinnedIndex = firstUnpinnedColumn?.visibleIndex ?? 0;
    this.grid?.navigateTo(0, firstUnpinnedIndex);
  }

  /**
   * Returns columns from model.
   *
   * @return {*}  {*}
   * @memberof XamGridComponent
   */
  getColumns(): any {
    return this.model.getColumns();
  }

  /**
   * Returns columns from a column group
   *
   * @param {XamGridColumnModel} col
   * @returns {GroupColumnsCollection}
   * @memberof XamGridComponent
   */
  getColumnGroup(col: XamGridColumnModel): GroupColumnsCollection {
    return (col as XamGridGroupColumnModel).Columns;
  }

  /**
   * Click Handler event.
   *
   * @param {*} $event
   * @memberof XamGridComponent
   */
  cellClickHandler(event: IGridCellEventArgs): void {
    /* istanbul ignore else */
    if (
      event &&
      !this.validationErrorFlag &&
      !this.hasValidationErrors(this.selectedRow)
    ) {
      /* istanbul ignore else */
      if (
        (this.model.EditingSettings.IsMouseActionEditingEnabled ===
          MouseEditingAction.SingleClick ||
          this.model.EditingSettings.IsOnCellActiveEditingEnabled) &&
        (!this.isCellInEditMode() || !event.cell.editMode)
      ) {
        this.cellEnterEditMode(event.cell);
      }
      const params = [
        this.model,
        new CellClickedEventArgs(this.createCell(event.cell)),
      ];
      this.model.CellClicked.fire(params);
    }
  }

  /**
   * Double-click event handler.
   *
   * @param {IGridCellEventArgs} event
   * @memberof XamGridComponent
   */
  doubleClickHandler(event: IGridCellEventArgs): void {
    if (!this.validationErrorFlag) {
      /* istanbul ignore else */
      if (
        this.model.EditingSettings.IsMouseActionEditingEnabled ===
        MouseEditingAction.DoubleClick
      ) {
        this.cellEnterEditMode(event.cell);
      }
      const params = new CellClickedEventArgs(this.createCell(event.cell));
      this.model.CellDoubleClickHandler(params);
    }
  }

  /**
   * Cell selection event handler.
   *
   * @param {IGridCellEventArgs} event
   * @memberof XamGridComponent
   */
  cellSelectionHandler(event: IGridCellEventArgs): void {
    this.nextColumnWithErrors = this.evaluateColumnDataErrors(
      this.model.ActiveCell?.Row?.Data
    );
    if (this.isHandlingCollectionChanges) {
      this.InvalidateSelectionAndActivation(true);
      return;
    }
    /* istanbul ignore else */
    if (!this.nextColumnWithErrors) {
      if (
        this.model.SelectionSettings.CellClickAction !==
        CellSelectionAction.SelectCell
      ) {
        event.cell.selected = false;
        this.model.SelectedIndex = event.cell.row.index;
        this.model.SelectedColumnIndex = event.cell.column.index;
        return;
      }
      this.model.CellSelectionChangeHandler(event);
      this.model.SelectedIndex = event.cell.row.index;
      this.model.SelectedColumnIndex = event.cell.column.index;
      this.cellSelectionChange.emit(event);
    }
  }

  /**
   * Row selection event handler.
   *
   * @param {*} event
   * @memberof XamGridComponent
   */
  rowSelectionHandler(event: any): void {
    this.nextColumnWithErrors = this.evaluateColumnDataErrors(
      this.model.SelectedRow?.Data
    );
    if (this.nextColumnWithErrors) {
      event.cancel = true;
      return;
    }
    let oldRows,
      newRows = [];
    if (this.grid && this.isFilteredSortedData) {
      oldRows = event.oldSelection.map((key) =>
        this.getRowFromFilteredDataByKey(key)
      );
      newRows = event.newSelection.map((key) =>
        this.getRowFromFilteredDataByKey(key)
      );
    } else {
      oldRows = event.oldSelection.map((key) =>
        this.getRowFromModelByKey(key, this)
      );
      newRows = event.newSelection.map((key) =>
        this.getRowFromModelByKey(key, this)
      );
    }
    // avoid to selected something that is not in the grid yet because is adding a new row
    if (newRows == null || (newRows.length === 1 && newRows[0] == null)) {
      return;
    }
    if (this.selectionSettings.RowSelection === XamSelectionMode.Single) {
      if (newRows.length === 1 && newRows[0]) {
        this.model.SelectedRow = newRows[0];
        this.model.SelectedRow.IsSelected = true;
        this.model.SelectionSettings.SelectedRows.internalArray = [
          this.model.SelectedRow,
        ];
      } else {
        this.model.SelectedRow = null;
        this.model.SelectionSettings.SelectedRows.internalArray = [];
      }

      this.processColumnLayoutForRowSelection(oldRows);
    } else {
      this.model.SelectionSettings.SelectedRows.internalArray = newRows.map(
        (row) => {
          row.IsSelected = true;
          return row;
        }
      );
    }
    this.synchronizeRowCell();
    const params = new SelectionCollectionChangedEventArgs();
    params.NewSelectedItems = new SelectedRowsCollection(newRows);
    params.PreviouslySelectedItems = new SelectedRowsCollection(oldRows);
    this.model.SelectedRowsCollectionChanged.fire([this.model, params]);
    this.model.RowSelectionChangeHandler(params);
  }

  /**
   * Synchronize row
   *
   * @memberof XamGridComponent
   */
  synchronizeRowCell(): void {
    /* istanbul ignore else */
    if (this.model.ActiveCell && this.model.SelectionSettings.SelectedRows) {
      this.model.SelectionSettings.SelectedRows.internalArray.forEach((row) => {
        /* istanbul ignore else */
        if (row.Index === this.model.ActiveCell.Row.Index) {
          this.model.ActiveCell.Row = row;
        }
      });
    }
  }

  /**
   * Internal row selection event handler for column layout.
   *
   * @param {IRowSelectionEventArgs} internalEvent
   * @memberof XamGridComponent
   */
  internalColumnLayoutRowSelectionHandler(
    sender: any,
    e: SelectionCollectionChangedEventArgs<SelectedRowsCollection>
  ): void {
    const newEventArgs =
      new SelectionCollectionChangedEventArgs<SelectedRowsCollection>();
    newEventArgs.NewSelectedItems = new SelectedRowsCollection(
      e.NewSelectedItems.toArray()
    );
    newEventArgs.PreviouslySelectedItems = new SelectedRowsCollection(
      e.PreviouslySelectedItems.toArray()
    );
    if (this.selectionSettings.RowSelection === XamSelectionMode.Single) {
      this.deselectGridRows(sender, newEventArgs);
      if (e.NewSelectedItems.count === 1) {
        this.model.SelectedRow = e.NewSelectedItems.getItem(0);
        this.model.SelectedRow.IsSelected = true;
        this.model.SelectionSettings.SelectedRows.internalArray = [
          this.model.SelectedRow,
        ];
      } else {
        this.model.SelectedRow = null;
        this.model.SelectionSettings.SelectedRows.internalArray = [];
      }
    } else {
      this.model.SelectedRow = null;
      this.model.SelectionSettings.SelectedRows.internalArray = [];
    }

    this.model.SelectedRowsCollectionChanged.fire([this.model, newEventArgs]);
    this.model.RowSelectionChangeHandler(e);
  }

  /**
   * Column selection handler.
   *
   * @param {*} event
   * @memberof XamGridComponent
   */
  columnSelectionHandler(event: any): void {
    this.model.SelectionSettings.SelectedColumns.internalArray =
      event.newSelection.map((key) => this.getColumnModelByKey(key));
    const params = this.createEventParams();
    this.model.ColumnSelectionChanged.fire([params.sender, params.e]);
    this.columnSelectionChanged.emit(event);
  }

  /**
   * Keydown event handler.
   *
   * @param {IGridKeydownEventArgs} event
   * @memberof XamGridComponent
   */
  keydownHandler(e: IGridKeydownEventArgs): void {
    const key = (e.event as KeyboardEvent).key;

    if (
      key === 'Enter' &&
      !this.model.EditingSettings.IsEnterKeyEditingEnabled
    ) {
      e.cancel = true;
      this.grid.endEdit(true); // Commits the changes of the edited row
      this.addRowKey = null;
      this.grid.nativeElement.focus(); // Keeps focus on grid
    }
    if (key === 'F2' && !this.model.EditingSettings.IsF2EditingEnabled) {
      e.cancel = true;
    }

    const params = this.createEventParams();
    this.model.KeyDownHandler(params);
    this.keyDown.emit(params);
  }

  /**
   * Handler for arrowRight keydown event
   * Gets the cursor position and move to the next cell
   *
   * @param {KeyboardEvent} event
   * @memberof XamGridComponent
   */
  arrowRightHandler(event: KeyboardEvent): void {
    const position = (<HTMLInputElement>event.target).selectionStart + 1;
    if (
      this.model.ActiveCell !== null &&
      this.model.ActiveCell.Control !== null &&
      this.model.ActiveCell.Control.Cell !== null
    ) {
      //Cell in line value: before context update
      const inLineValue: string =
        (<HTMLInputElement>event.target).value?.trim() === ''
          ? null
          : (<HTMLInputElement>event.target).value;

      //Value after context update
      let value: string = this.model.ActiveCell.Control.Cell.Value;

      // Validate if the value was updated before the context update
      if (!value || value?.length != inLineValue?.length) {
        value = inLineValue;
      }
      if (position > value?.toString().length || !value) {
        this.grid.navigation.dispatchEvent(event);
      }
    }
  }

  /**
   * Handler for arrowLeft keydown event
   * Gets the cursor position and move to the last cell
   *
   * @param {KeyboardEvent} event
   * @memberof XamGridComponent
   */
  arrowLeftHandler(event: KeyboardEvent): void {
    const position = (<HTMLInputElement>event.target).selectionEnd - 1;
    if (position < 0) {
      this.grid.navigation.dispatchEvent(event);
    }
  }

  /**
   * Handler to know which handler has to use
   *
   * @param {KeyboardEvent} event
   * @memberof XamGridComponent
   */
  arrowsHandler(event: KeyboardEvent): boolean {
    if (event.code == 'ArrowRight') {
      this.arrowRightHandler(event);
      return true;
    } else if (event.code == 'ArrowLeft') {
      this.arrowLeftHandler(event);
      return true;
    } else {
      return false;
    }
  }

  /**
   * If AllowEditing is on Cell type and there is a error message on the active cell,
   * prevent clicks on components in edit mode on table data
   *
   * @return {*}  {boolean}
   * @memberof XamGridComponent
   */
  stopClickOutsideCell(): boolean {
    this.forceRevalidation();
    return (
      this.model.EditingSettings.AllowEditing === XamGridEditingType.Cell &&
      this.validationErrorFlag
    );
  }

  /**
   * Calling this function produces the necessary event to execute the validations of the cell being edited.
   * When used, the `cellEditHandler` function will be called
   *
   * @memberof XamGridComponent
   */
  forceRevalidation(): void {
    const args = this.grid.crudService.cell?.createEditEventArgs(true);
    /* istanbul ignore else */
    if (args) {
      this.grid.cellEdit.emit(args);
    }
  }

  /**
   * Listener for tab keydown event
   * Needs to be done in host listener to trigger even in not editable cells
   *
   * @param {KeyboardEvent} event
   * @memberof XamGridComponent
   */
  @HostListener('keydown', ['$event'])
  tabKeyListener(event: KeyboardEvent): void {
    if (this.internalXamGrid) return;
    if (this.shouldAddNewRow) {
      if (!this.arrowsHandler(event)) {
        this.grid.navigation.dispatchEvent(event);
      }
    } else {
      if (event.code === 'Tab') {
        this.processTabCode(event);
      } else if (!this.arrowsHandler(event)) {
        if (event.code != 'Space') {
          this.grid.navigation.dispatchEvent(event);
        }
      }
    }
  }

  /**
   * Processes the Keyboard event when the code is for the Tab key
   *
   * @memberof XamGridComponent
   */
  private processTabCode(event: KeyboardEvent) {
    event.preventDefault();
    const columnkey = 'data.' + this.model.ActiveCell?.Column?.Key;
    /* istanbul ignore next */
    if (
      this.model.HasColumnType(columnkey) &&
      this.grid.crudService.cellInEditMode
    ) {
      this.forceRevalidation();
      if (this.validationErrorFlag) {
        return;
      }
    }
    this.tabKeyNavigation(event.shiftKey);
  }

  /**
   * Column resize event handler.
   *
   * @param {*} event
   * @memberof XamGridComponent
   */
  resizeHandler(event: any): void {
    const params = this.createEventParams();
    this.setsColumnsToNumericValues(); // force value reset for columns to numeric value
    this.processAllowToolTipsByColumn(event.column);
    this.model.ColumnResized.fire([params.sender, params.e]);
    this.columnResized.emit(params);
  }

  /**
   * Active cell handler
   *
   * @param {IActiveNodeChangeEventArgs} event
   * @memberof XamGridComponent
   */
  activeNodeHandler(event: IActiveNodeChangeEventArgs) {
    this.nextColumnWithErrors = this.evaluateColumnDataErrors(
      this.model.ActiveCell?.Row?.Data
    );
    /* istanbul ignore else */
    if (!this.validationErrorFlag && !this.nextColumnWithErrors) {
      // Bug 481171: Workaround for the issue with the active cell selection when is set from the createCell method
      if (event.column === -1) {
        return;
      }
      let rowSource = this.Rows.getItem(event.row);
      const row = this.grid.getRowByIndex(event.row);
      let rowIndex = event.row;
      if (this.isNewRow(row)) {
        const rowToAdd = this.getAddRow();
        rowSource = rowToAdd;
        rowIndex = -1;
      }
      let cell = null;
      if (event.tag === 'dataCell') {
        let columnName = this.grid.getColumnByVisibleIndex(event.column).field;
        columnName = columnName.substring(5, columnName.length);
        cell = rowSource.Cells.getCellByKey(columnName);
      }
      if (this.model.ActiveCell !== cell) {
        this.exitEditOnRowChanged(rowIndex);
        this.model.ActiveCell = cell;
      }
      /* istanbul ignore else */
      if (this.model.ActiveCell) {
        this.model.ActiveCell.Row['IsSelected'] = this.isNewRow(row)
          ? false
          : true;
      }
    }
    this.nextColumnWithErrors = null;
  }

  /**
   * Cell editing handler
   *
   * @param {IGridEditEventArgs} event
   * @memberof XamGridComponent
   */
  cellEditHandler(event: IGridEditEventArgs) {
    const innerCell = this.grid.getCellByKey(event.rowID, event.column.field);
    if (this.model.HasColumnType(event.column?.field)) {
      if (!event.rowData) {
        return;
      }
      const result = { valid: false, value: event.newValue, editor: null };
      this.calculateCellControlValue(innerCell, event, result);
      if (!result.valid) {
        event.cancel = true;
        this.validationErrorFlag = true;
        this.showErrorMessageOnCell('Input is not in a correct format.', event);
        return;
      } else {
        this.validationErrorFlag = false;
        this.removeErrorMessageOnCell(event);
      }

      innerCell.editValue = result.value;
      event.newValue = result.value;
    }
    this.validateDataErrorInfo(
      event.rowData?.data,
      event.column?.header,
      event
    );
    /* istanbul ignore else */
    if (this.validationErrorFlag) {
      event.cancel = true;
      return;
    }
    const cell = this.createCell(innerCell);
    this.model.CellEditing.fire([this.model, new EditingCellEventArgs(cell)]);
    this.cellEditing.emit(cell);
  }

  /**
   * Calculates the value of the cell control
   *
   * @return {string | null}
   * @memberof XamGridComponent
   */
  private calculateCellControlValue(
    cellComponent: CellType,
    event: any,
    result: { valid: boolean; value: any; editor: any }
  ) {
    const cell = this.createCell(cellComponent);
    const cellType = () =>
      this.grid?.getCellByColumn(cell.Row.Index, 'data.' + cell.Column.Key);
    const control = this.getCellControlIfExists(cellType, cell);
    result.editor = control?.Editor;
    /* istanbul ignore next */
    if (control?.Content?.Text) {
      result.value = control?.Content.Text;
    }
    /* istanbul ignore next */
    if (this.model.HasColumnType(event.column?.field)) {
      this.validateLimits(this.model.GetColumnType(event.column.field), result);
    }
  }

  /**
   * Defines whether to use virtualization or not
   *
   * @return {string | null}
   * @memberof XamGridComponent
   */
  calcVirtualHeight(): string | null {
    const isVirtualCollection = this.data instanceof VirtualCollection;
    let height = null;
    if (this.virtualHeight && !isVirtualCollection) {
      height = this.virtualHeight;
    } else if (
      this.data?.count < this.rowLimitNoVirtualization ||
      isVirtualCollection
    ) {
      height = null;
    } else {
      height = '100%';
    }
    return height;
  }

  /**
   * RowEdit handler catches if state error is true and cancel enter edition
   *
   * @param {*} event
   * @memberof XamGridComponent
   */
  rowEditHandler(event: any): void {
    this.nextColumnWithErrors = this.evaluateColumnDataErrors(
      event.rowData?.data
    );
    if (
      !this.isTabKeyNavigating &&
      (this.validationErrorFlag || this.nextColumnWithErrors)
    ) {
      event.cancel = true;
      if (this.nextColumnWithErrors) {
        const nextCell = this.grid.getCellByColumn(
          0,
          'data.' + this.nextColumnWithErrors
        );
        /* istanbul ignore next */
        if (!nextCell?.selected && !this.model.ActiveCell.Row?.Data.HasErrors) {
          nextCell.selected = true;
          nextCell.row.selected = true;
          this.cellEnterEditMode(nextCell);
        }
        this.nextColumnWithErrors = null;
      }
    }
  }

  /**
   * Cell edited handler
   *
   * @param {IGridEditDoneEventArgs} event
   * @memberof XamGridComponent
   */
  cellEditedHandler(event: IGridEditDoneEventArgs) {
    const cellComponent =
      this.grid.getCellByKey(event.rowID, event.column?.field) ??
      this.grid.getCellByColumn(event.cellID?.rowIndex, event.column?.field);
    const cell = this.createCell(cellComponent);
    this.model.CellEdited.fire([
      this.model,
      new ExitEditingCellEventArgs(cell),
    ]);
    this.cellEdited.emit(cell);
  }

  /**
   * Cell entering edit mode handler
   *
   * @memberof XamGridComponent
   */
  /* istanbul ignore next */
  enterEditHandler(event: IGridEditEventArgs) {
    // Clean the pending transactions before edit again.
    // Right now, the cell.row.data.data is the same as the cellModel.Data. This is a temporal fix,
    // to avoid set a old value from the transaction data to the editValue.
    if (event.rowID !== this.addRowKey?.key) {
      this.grid?.transactions?.endPending(true);
    }
    if (
      this.model.ActiveCell?.Row.Index !== event.cellID?.rowIndex &&
      this.isHandlingCollectionChanges
    ) {
      event.cancel = true;
      return;
    }

    this.isActiveCellChanged = false;
    if (
      this.model.EditingSettings.AllowEditing === XamGridEditingType.None ||
      this.model.EditingSettings.IsMouseActionEditingEnabled ===
        MouseEditingAction.None ||
      (this.model.EditingSettings.IsMouseActionEditingEnabled ===
        MouseEditingAction.DoubleClick &&
        event?.event?.type === 'pointerdown' &&
        this.model.ActiveCell?.Row.Index !== event.cellID.rowIndex)
    ) {
      event.cancel = true;
      return;
    }
    const cell = this.createCell(
      this.grid.getCellByKey(event.rowID, event.column.field)
    );
    // this event is called when the user tries to add a new row, but the cell is null in this case
    if (cell == null) {
      return;
    }

    // we need to update the activeCell when the user clicks on the cell
    if (cell !== this.model.ActiveCell) {
      this.model.ActiveCell = cell;
      this.isActiveCellChanged = true;
    }

    const beginEditingCellEventArgs = new BeginEditingCellEventArgs(cell);
    this.model.CellEnteringEditMode.fire([
      this.model,
      beginEditingCellEventArgs,
    ]);
    if (beginEditingCellEventArgs.Cancel) {
      event.cancel = true;
      return;
    }

    this.model.editorTemplateLoading = true;
    // Emulate cell entered edit handler
    setTimeout(() => {
      const cellEvent = new EditingCellEventArgs(cell);
      const cellQuery = `#${this.grid.activeDescendant}`;
      this.selectInputTextIfTextColumnDefault(cell, cellQuery);
      /* istanbul ignore else */
      if (cellQuery && cell?.Column['EditorTemplate']) {
        const cellSelector = this.ref.nativeElement.querySelector(cellQuery);
        const cellType = () =>
          this.grid?.getCellByColumn(cell.Row.Index, 'data.' + cell.Column.Key);
        const control = this.getCellControlIfExists(cellType, cell);
        cellEvent.Editor = control?.Content;
        if (this.isActiveCellChanged) {
          const params = [this.model, new CellClickedEventArgs(cell)];
          this.model.CellClicked.fire(params);
          const cellToFocus = cellSelector.querySelector(
            'input, textarea'
          ) as HTMLElement;
          cellToFocus?.focus();
        }
      }
      this.model.CellEnteredEditMode.fire([this.model, cellEvent]);
      this.model.editorTemplateLoading = false;
    }, 50);

    this.removeErrorMessageOnCell(event);
  }

  /**
   * If the cell is a text column, select the text in the input
   *
   * @param {XamGridCell} cell - XamGridCell - the cell that is being edited
   * @param {string} cellQuery - string - the query selector for the cell
   * @memberof XamGridComponent
   */
  private selectInputTextIfTextColumnDefault(
    cell: XamGridCell,
    cellQuery: string
  ): void {
    if (cell.Column instanceof XamGridTextColumnModel) {
      const input: HTMLInputElement = this.ref.nativeElement.querySelector(
        `${cellQuery} [igxinput]`
      );
      input && input.setSelectionRange(0, input.value.length);
    } else if (cell.Column instanceof XamGridTemplateColumnModel) {
      const textarea: HTMLTextAreaElement =
        this.ref.nativeElement.querySelector(`${cellQuery} textarea`);
      if (textarea) {
        textarea.focus();
        textarea.setSelectionRange(0, textarea.value.length);
      }
    }
  }

  /**
   * Cell exiting edit mode handler
   *
   * @memberof XamGridComponent
   */
  exitEditHandler(event: IGridEditDoneEventArgs): void {
    /*Note: This 'if' statement is a workaround for a bug in the infragistics grid which triggers this event twice*/
    if (
      this.grid.crudService.row &&
      event.rowID !== this.grid.crudService.row.id
    ) {
      this.endRowEdit(false, event.event);
      return;
    }

    const cellComponent =
      this.grid.getCellByKey(event.rowID, event.column?.field) ??
      this.grid.getCellByColumn(event.cellID?.rowIndex, event.column?.field);
    const cell = this.createCell(cellComponent);
    cell.Control.Content?.bindingExpressions.internalArray.forEach(
      (bindingExpression: any) => {
        bindingExpression.Value.UpdateSource();
      }
    );
    const params = [this.model, new CellExitedEditingEventArgs(cell)];

    const cellEvent = new ExitEditingCellEventArgs(cell);
    const cellQuery = `#${this.grid.activeDescendant}`;
    /* istanbul ignore else */ /* istanbul ignore next */
    if (cellQuery && cell?.Column['EditorTemplate']) {
      /* istanbul ignore next */
      const result = { valid: false, value: null, editor: null };
      this.calculateCellControlValue(cellComponent, event, result);
      cellComponent.editValue = result.value;
    }
    this.model.CellExitingEditMode.fire([this.model, cellEvent]);
    // Update the data for the row
    if (cellComponent) {
      cell.Row.Data = cellComponent.row.data.data;
    }
    this.model.CellExitedEditMode.fire(params);
    setTimeout(() => {
      this.cellControlEvents(cell);
    }, 100);
  }

  /**
   * This function is called when a cell is created and it fires two events that can be used to attach
   * a control to the cell.
   * @param {XamGridCell} cell - XamGridCell - The cell that the control is being attached to.
   * @memberof XamGridComponent
   */
  private cellControlEvents(cell: XamGridCell): void {
    const args = new CellControlAttachedEventArgs();
    args.Cell = cell;
    this.model.CellControlAttached.fire([this.model, args]);
    this.model.AfterCellControlAttached.fire([this.model, args]);
  }

  /**
   * Validates if there are columns with errors
   * @param {any} data
   * @memberof XamGridComponent
   */
  evaluateColumnDataErrors(data: any): string {
    let nextColumnWithErrors = null;
    if (
      data &&
      ReflectionHelper.isInterfaceIsSupported(
        data,
        'System.ComponentModel.IDataErrorInfo'
      )
    ) {
      this.Columns.forEach((column) => {
        const key = column.Key;
        /* istanbul ignore else */
        if (data.getItem(key) && nextColumnWithErrors === null) {
          nextColumnWithErrors = key;
        }
      });
    } else if (
      data &&
      ReflectionHelper.isInterfaceIsSupported(
        data,
        'System.ComponentModel.INotifyDataErrorInfo'
      )
    ) {
      this.Columns.forEach((column) => {
        const key = column.Key;
        /* istanbul ignore else */
        if (data.GetErrors(key) && nextColumnWithErrors === null) {
          nextColumnWithErrors = key;
        }
      });
    } else if (
      !nextColumnWithErrors &&
      this.hasValidationErrors(this.selectedRow)
    ) {
      nextColumnWithErrors = this.Columns.getItem(
        this.model.SelectedColumnIndex
      ).Key;
    }
    return nextColumnWithErrors;
  }

  /**
   * Validates if the row currently has any validation errors
   *
   * @param {XamGridRow} row
   * @returns {boolean}
   * @memberof XamGridComponent
   */
  hasValidationErrors(row: XamGridRow): boolean {
    if (!row) return false;
    const rowRef = this.grid.rowList.get(row.Index)?.element.nativeElement;
    return rowRef?.querySelector('.validationCornerError') != null;
  }

  /**
   * Row exiting edit mode handler
   *
   * @param {IGridEditDoneEventArgs} event
   * @memberof XamGridComponent
   */
  rowExitEditHandler(event: IGridEditDoneEventArgs) {
    /* istanbul ignore else */
    if (this.Columns.count > 0) {
      const eventRowID = JSON.stringify(event.rowID);
      const rowComponent = this.grid.rowList.find(
        (r) => eventRowID === JSON.stringify(r.key)
      );
      if (event.rowData && rowComponent?.index > -1) {
        const row = this.createRowFromData(event.rowData, rowComponent.index);
        const params = [this.model, new EditingRowEventArgs(row)];
        //Delay added to avoid possibles infinite loops when calling ExitEditMode from
        //a user handler attached to precisely to RowExitedEditMode event
        setTimeout(() => this.model.RowExitedEditMode.fire(params));
      }
    }
  }

  /**
   * Row exiting edit mode handler
   *
   * @param {IGridEditDoneEventArgs} event
   * @memberof XamGridComponent
   */
  rowEnterEditHandler(event: IGridEditDoneEventArgs) {
    /* istanbul ignore else */
    if (this.Columns.count > 0) {
      const eventRowID = JSON.stringify(event.rowID);
      const rowComponent = this.grid.rowList.find(
        (r) => eventRowID === JSON.stringify(r.key)
      );
      const row =
        event.rowID === this.addRowKey?.key
          ? this.getAddRow()
          : this.createRowFromData(event.rowData, rowComponent?.index);
      const params = [this.model, new EditingRowEventArgs(row)];
      this.model.RowEnteredEditMode.fire(params);
    }
  }

  /**
   * Triggers the cell edit mode if column is editable and not read-only
   *
   * @param {CellType} cellType cell to enter edit mode
   * @param isAsync
   * @memberof XamGridComponent
   */
  cellEnterEditMode(cellType: CellType, isAsync = false): void {
    const colKey = cellType.column.field.replace('data.', '');
    const colModel = this.getColumnModelByKey(colKey);
    /* istanbul ignore else */
    if (this.isEditable(colModel) && !colModel?.IsReadOnly) {
      cellType.column.editable = true;
      cellType.editMode = true;
      this.isTabKeyNavigating = false;
      if (isAsync) {
        setTimeout(() => {
          this.navigateToCell(cellType);
        }, 0);
      } else {
        this.navigateToCell(cellType);
      }
    }
  }

  /**
   * Navigates and focus the content of a cell.
   *
   * @param {CellType} cellType
   * @type {void}
   * @memberof XamGridComponent
   */
  navigateToCell(cellType: CellType): void {
    this.grid.navigateTo(cellType.row.index, cellType.column.index, (args) => {
      args.target.nativeElement.querySelector('input,textarea')?.focus();
    });
  }

  /**
   * Returns current column data context.
   *
   * @param {*} context
   * @return {*}  {void}
   * @memberof XamGridComponent
   */
  cellContext(context): any {
    return context;
  }

  /**
   * Paging handler
   *
   * @returns true if handler paging is applied
   */
  pagingHandler(): boolean {
    return this.model.PagerSettings.AllowPaging !== PagingLocation.None;
  }

  /**
   * Validates if data implements IDataErrorInfo and checks for errors.
   *
   * @memberof XamGridComponent
   */
  validateDataErrorInfo(
    data: any,
    columnName: string,
    event: IGridEditDoneEventArgs
  ): void {
    if (
      data &&
      ReflectionHelper.isInterfaceIsSupported(
        data,
        'System.ComponentModel.IDataErrorInfo'
      )
    ) {
      const validationError = data.getItem(columnName);
      /* istanbul ignore else */
      if (validationError) {
        this.validationErrorFlag = true;
        this.showErrorMessageOnCell(validationError, event);
      } else {
        this.validationErrorFlag = false;
        this.removeErrorMessageOnCell(event);
      }
    }
  }

  /**
   * Determinate if the column is a editable column
   *
   * @param {XamGridColumnModel} column
   * @return {*} boolean
   * @memberof XamGridComponent
   */
  isEditable(column: XamGridColumnModel): boolean {
    if (
      this.model.EditingSettings.AllowEditing !== XamGridEditingType.None &&
      !column.IsReadOnly
    ) {
      if (
        (column instanceof XamGridTemplateColumnModel &&
          column.EditorTemplate) ||
        (column instanceof XamGridUnboundColumnModel &&
          column.EditorTemplate &&
          column.EditorTemplate.templateRef)
      ) {
        return true;
      }
      return this.processEditableColumn(column);
    }
    return false;
  }

  /**
   * Determine if the column has sumamry
   *
   * @param {any} column
   * @return {*} boolean
   * @memberof XamGridComponent
   */
  hasSummary(column: any): boolean {
    if (column?.HasSummary || column?.FooterText) {
      return true;
    }
    return false;
  }

  /**
   * Determinate if the column is a editable column when the grid is in edit mode
   *
   * @param {XamGridColumnModel} column
   * @return {*}  {boolean}
   * @memberof XamGridComponent
   */
  processEditableColumn(column: XamGridColumnModel): boolean {
    if (column.Editable) {
      if (
        column instanceof XamGridTextColumnModel ||
        column instanceof XamGridCheckboxColumnModel
      ) {
        return true;
      }
      if (
        (column instanceof XamGridTemplateColumnModel &&
          !column.ItemTemplate?.templateRef) ||
        (column instanceof XamGridUnboundColumnModel &&
          !column.ItemTemplate?.templateRef)
      ) {
        return true;
      }
    }
    return false;
  }

  /**
   * Returns number of total items.
   *
   * @return {*}  {number}
   * @memberof XamGridComponent
   */
  totalPagingRecordsHandler(): number {
    const itemsSourcePaged = this.model.ItemsSourceAsPagedCollection;
    if (
      this.grid &&
      this.model.PagerSettings &&
      this.model.PagerSettings.AllowPaging !== 3 &&
      itemsSourcePaged
    ) {
      this.grid.totalRecords = itemsSourcePaged.TotalItemCount;
      return itemsSourcePaged.TotalItemCount;
    } else {
      return (
        this.grid?.totalRecords ??
        (this.model.ItemsSource ? iuCount(this.model.ItemsSource) : 0)
      );
    }
  }

  /**
   * TriggerExitEditMode when a click is called outside a xam grid row and a row and is in edition
   *
   * @param {*} target
   * @memberof XamGridComponent
   */
  /* istanbul ignore next */
  @HostListener('document:mousedown', ['$event.target'])
  clickListener(target: any): void {
    const overlayElement = this.document.querySelector('.igx-overlay');
    const rowsContainer = this.ref?.nativeElement.querySelector(
      '.igx-grid__tbody-content > igx-display-container'
    );
    /* istanbul ignore else */
    if (
      this.isCellOrRowInEditMode() &&
      !rowsContainer.contains(target) &&
      !(
        overlayElement &&
        //should not exit edit mode if a dropdown or datetime picker are opened
        (overlayElement.querySelector('.igx-drop-down__list.igx-toggle') ||
          overlayElement.querySelector(
            '.wm-rad-date-time-picker-overlay__content'
          ))
      ) &&
      !this.model.editorTemplateLoading
    ) {
      this.processTriggerExitEditMode('triggerExitEditMode', true);
    }
  }

  /**
   * Returns true if the cell or row is in EditMode
   *
   * @returns {boolean}
   * @memberof XamGridComponent
   */
  public isCellOrRowInEditMode(): boolean {
    return (
      this.grid?.crudService?.cellInEditMode ||
      this.grid?.crudService?.rowEditing
    );
  }

  /**
   * Returns true if the cell is in EditMode
   *
   * @returns {boolean}
   * @memberof XamGridComponent
   */
  public isCellInEditMode(): boolean {
    return this.grid?.crudService?.cellInEditMode;
  }

  /**
   * Creates the cell component from the infragistics cell component
   *
   * @param {IgxGridCellComponent} cell
   * @param {XamGridRow} [row]
   * @returns
   * @memberof XamGridComponent
   */
  public createCell(cell: CellType, row?: XamGridRow): XamGridCell {
    if (cell == null) {
      return null;
    }
    row =
      cell.row.key === this.addRowKey?.key
        ? this.getAddRow()
        : row ?? this.Rows.getItem(cell.row.index);
    const newCell = row.Cells.getCellByKey(
      cell.column.field.substring(5, cell.column.field.length) ?? ''
    );
    newCell.IsSelected = cell.selected;
    const cellType = () =>
      this.grid?.getCellByColumn(row.Index, 'data.' + newCell.Column.Key);
    newCell.Control = this.getCellControlIfExists(cellType, newCell);
    return newCell;
  }

  /**
   * Validate if a new value is within allowed limits for the given type.
   *
   * @public
   * @param {string} type
   * @param {{valid: boolean, value: any}} result
   * @return {*}  {void}
   * @memberof XamGridComponent
   */
  public validateLimits(
    type: XamGridColumnType,
    result: { valid: boolean; value: any }
  ): void {
    switch (type) {
      case 'int':
        this.checkIntLimits(result);
        return;
      case 'decimal':
        this.checkDecimalLimits(result);
        return;
      case 'int?':
      case 'Nullable<int>':
        this.checkNullableIntLimits(result);
        return;
    }

    throw Error(`There is no validation mechanism for ${type} type`);
  }

  /**
   * Get row index
   *
   * @param {XamGridRow} row
   * @returns
   * @memberof XamGridComponent
   */
  protected getRowIndex(row: XamGridRow): number {
    return this.grid.data.findIndex((value) => {
      return value.data == row.Data;
    });
  }

  /**
   * Get row index from filtered data
   *
   * @param {XamGridRow} row
   * @returns
   * @memberof XamGridComponent
   */
  protected getRowIndexFromFilteredData(row: XamGridRow): number {
    return this.grid.filteredSortedData.findIndex((value) => {
      return value.data == row.Data;
    });
  }

  /** Clears the internal data wrapper.
   * On the next rebind of the grid data from the dataHandler method
   * the internal wrapper will be populated.
   */
  protected invalidateInternalDataWrapper() {
    this.internalDataWrapper = [];
  }

  /**
   * Try to infer the 'shape' of the objects in the passed data array and to generate the columns based on that.
   *
   * @protected
   * @param {any[]} data
   * @return {*}  {string[]}
   * @memberof XamGridComponent
   */
  protected generateDataFields(data: any[]): string[] {
    return Object.keys(data && data.length ? data[0] : 0);
  }

  /**
   * Generates XamColumn instances and the corresponding column models for them.
   *
   * @protected
   * @memberof XamGridComponent
   */
  protected generateColumnModels(): void {
    const factory = this.resolver.resolveComponentFactory(
      XamGridColumnComponent
    );
    const collection = this.generateDataFields(this.data).map((field) => {
      const ref = factory.create(this.injector);
      ref.instance.key = field;
      ref.changeDetectorRef.detectChanges();
      return ref.instance;
    });

    this.gridColumnsItems.reset(collection);
  }

  /**
   * Setup the handling of dynamic adding/removing of columns in XamGrid and
   * keeping both models in sync.
   *
   * @protected
   * @memberof XamGridComponent
   */
  protected setupColumnTracking(): void {
    this.gridColumnsItems.changes?.subscribe(
      (changes: QueryList<XamGridColumnComponent>) => {
        const delta = this.differ.diff(changes);
        /* istanbul ignore else */
        if (delta) {
          // If the new column is added through the 'Silverlight' model, we don't want to duplicate
          // it again there.
          delta.forEachAddedItem((added) => {
            /* istanbul ignore else */
            if (
              !this.model.Columns.contains(added.item.model) &&
              (!added.item.model.Parent ||
                added.item.model.Parent === this.model)
            ) {
              this.model.addColumn(added.item.model);
            }
          });

          delta.forEachRemovedItem((removed) =>
            this.model.Columns.remove(removed.item.model)
          );
        }
      }
    );
    this.processDefaultHeaderStyle();
    this.setColumnProperties(this.getColumns());
  }

  /**
   * Called once after rendering of the XamGrid.
   * Setups the width property for the column models based on the grid `ColumnWidth` property.
   * It is a no-op for Auto, InitialAuto and Star width values.
   *
   * @protected
   * @memberof XamGridComponent
   */
  protected setColumnsWidth(isRendering = false): void {
    if (isRendering) {
      this.evaluateColumns();
    }
    this.calculateAndSetNonSpecialColumnsWidth();
    this.processAllowToolTipsByRow();
  }

  /**
   * Evaluate for which auto columns is neccesary to apply autosize.
   *
   * @return {*}
   * @memberof XamGridComponent
   */
  evaluateAutoColumns() {
    const columnsToAutosize = this.visibleColumns
      .filter((col) => !this.autosizedColumns.has(col))
      .map((col) => ({
        col: col,
        model: this.getColumnModelByKey(col.field, true),
      }))
      .filter((pair) => pair.model != null)
      .filter(
        (pair) => pair.model.WidthResolved.WidthType !== ColumnWidthType.Star
      )
      .filter(
        (pair) => pair.model.WidthResolved.WidthType !== ColumnWidthType.Numeric
      )
      .map((pair) => pair.col);
    /* istanbul ignore else */
    if (columnsToAutosize.length === 0) {
      return;
    }
    this.processAutosize(columnsToAutosize);
  }

  /**
   * Asyncronously apply autosize to the given columns.
   *
   * @param {IgxColumnComponent[]} columns
   * @memberof XamGridComponent
   */
  processAutosize(columns: IgxColumnComponent[]) {
    this.isEvaluatingAutoColumns = true;
    setTimeout(() => {
      const col = columns.shift();
      /* istanbul ignore else */
      if (col == null) {
        this.isEvaluatingAutoColumns = false;
        return;
      }
      col.autosize();
      this.autosizedColumns.add(col);
      this.processAutosize(columns);
    }, 1);
  }

  /**
   * Evaluate columns to apply width
   *
   * @memberof XamGridComponent
   */
  evaluateColumns(): void {
    let hasStarValues = false;
    let failedSpecialCases = false;
    /* istanbul ignore else */
    if (this.grid?.columns) {
      this.grid.columns.forEach((col) => {
        const colModel = this.getColumnModelByKey(col.field, true);
        if (colModel) {
          const colWidhtToApply = colModel.WidthResolved;
          if (
            colWidhtToApply.WidthType !== ColumnWidthType.Star &&
            colWidhtToApply.WidthType !== ColumnWidthType.Numeric
          ) {
            failedSpecialCases =
              failedSpecialCases ||
              !this.setColumnWidthSpecialCase(col, colWidhtToApply);
          } else if (colWidhtToApply.WidthType === ColumnWidthType.Star) {
            hasStarValues = true;
          }
        }
      });
      this.setReCalcColumnsValues(hasStarValues, failedSpecialCases);
    }
  }

  /**
   * Sets if the current columns should recalculated.
   *
   * @param {any} async
   * @param {boolean} hasStarValues
   * @param {boolean} failedSpecialCases
   * @type {void}
   * @memberof XamGridComponent
   */
  setReCalcColumnsValues(
    hasStarValues: boolean,
    failedSpecialCases: boolean
  ): void {
    setTimeout(() => {
      this.forcedColumnsWidthCalc = hasStarValues || failedSpecialCases;
      this.requiredSpecialValuesSizeReCalc = failedSpecialCases;
    }, 50);
  }

  /**
   * Calculates and sets the columns width used for numeric and star values.
   *
   * @protected
   * @memberof XamGridComponent
   */
  protected calculateAndSetNonSpecialColumnsWidth() {
    this.cachedGridWidth = this.grid.calcWidth;
    this.forcedColumnsWidthCalc = false;
    if (this.grid.columns) {
      const columnModels = this.grid.columns
        .map((col) => this.getColumnModelByKey(col.field, true))
        .filter((model) => model != null);
      this.calculateStarColumnsWidth(columnModels);
      this.calculateNumericColumnsWidth(columnModels);
    }
  }

  /**
   * Calculates column width for numeric columns.
   *
   * @protected
   * @param {XamGridColumnModel[]} columnModels
   * @memberof XamGridComponent
   */
  protected calculateNumericColumnsWidth(columnModels: XamGridColumnModel[]) {
    const numericColumnModels = columnModels.filter(
      (model) => model.WidthResolved.WidthType === ColumnWidthType.Numeric
    );
    for (const model of numericColumnModels) {
      model.CalculatedWidth = model.WidthResolved.Value;
    }
  }

  /**
   * Calculates column width for star columns.
   *
   * @protected
   * @param {XamGridColumnModel[]} columnModels
   * @return {*}
   * @memberof XamGridComponent
   */
  protected calculateStarColumnsWidth(columnModels: XamGridColumnModel[]) {
    const [starTotalSpace, usedPixelSize] = this.getGridRemainSpaceInfo();
    const starColumnModels = columnModels.filter(
      (model) => model.WidthResolved.WidthType === ColumnWidthType.Star
    );
    const starValues = {
      percentPerStar: 0,
      starTotalSpace: starTotalSpace,
      usedPixelSize: usedPixelSize,
      gridTotalSpace: this.grid.calcWidth,
      starColumnModels: starColumnModels,
    };
    this.calculatePercentPerStar(starValues);
    /* istanbul ignore else */
    if (starValues.percentPerStar <= 0) {
      this.setColumnsToMinimumWidth(starColumnModels);
      return;
    }
    while (!this.calculateStarColumnsWidthLoop(starValues)) {
      this.calculatePercentPerStar(starValues);
    }
  }

  /**
   * Calculates width percent that should be given to each star unit.
   *
   * @protected
   * @param {{percentPerStar: number, starTotalSpace: number, usedPixelSize: number, gridTotalSpace:number}} starValues
   * @memberof XamGridComponent
   */
  protected calculatePercentPerStar(starValues: {
    percentPerStar: number;
    starTotalSpace: number;
    usedPixelSize: number;
    gridTotalSpace: number;
  }) {
    const freeSpacePercent =
      (1 - starValues.usedPixelSize / starValues.gridTotalSpace) * 100;
    starValues.percentPerStar = freeSpacePercent / starValues.starTotalSpace;
  }

  /**
   * Calculates column width for star columns. If some star column gets assigned
   * a fixed width, it recalculates `usedPixelSize` and `starTotalSpace` and
   * returns `false`, to indicate that width should be recalculated for all
   * remaining star columns.
   *
   * @protected
   * @param {{percentPerStar: number, starTotalSpace: number, usedPixelSize: number, gridTotalSpace:number, starColumnModels: XamGridColumnModel[]}} starValues
   * @return {*}  {boolean} `true` if width for all star columns was calculated, `false` otherwise.
   * @memberof XamGridComponent
   */
  protected calculateStarColumnsWidthLoop(starValues: {
    percentPerStar: number;
    starTotalSpace: number;
    usedPixelSize: number;
    gridTotalSpace: number;
    starColumnModels: XamGridColumnModel[];
  }): boolean {
    for (const model of starValues.starColumnModels) {
      const colWidth = starValues.percentPerStar * model.WidthResolved.Value;
      if (
        !isNaN(model.MinimumWidth) &&
        model.MinimumWidth > starValues.gridTotalSpace * (colWidth / 100)
      ) {
        // Column minimum width is higher than assigned star space.
        // Assign minimum width, treat this column as fixed size, and recalculate other star columns width again.
        model.CalculatedWidth = model.MinimumWidth;
        starValues.usedPixelSize += parseFloat(model.MinimumWidth);
        starValues.starTotalSpace -= model.WidthResolved.Value;
        this.removeModel(starValues.starColumnModels, model);
        return false;
      } else {
        model.CalculatedWidth = `${colWidth}%`;
      }
    }
    return true;
  }

  /**
   * Removes `model` from the `models` array.
   *
   * @protected
   * @param {XamGridColumnModel[]} models
   * @param {XamGridColumnModel} model
   * @memberof XamGridComponent
   */
  protected removeModel(
    models: XamGridColumnModel[],
    model: XamGridColumnModel
  ) {
    const idx = models.findIndex((x) => x === model);
    if (idx !== -1) {
      models.splice(idx, 1);
    }
  }

  /**
   * Sets widths to `MinimumWidth` (or `'0'` if `MinimumWidth`
   * is not available) for all given columns.
   *
   * @protected
   * @param {XamGridColumnModel[]} starColumnModels
   * @memberof XamGridComponent
   */
  protected setColumnsToMinimumWidth(starColumnModels: XamGridColumnModel[]) {
    for (const model of starColumnModels) {
      const min = Number(model.MinimumWidth);
      model.CalculatedWidth = isNaN(min) ? '0' : min.toString();
    }
  }

  /**
   * Gets the remaining available space
   *
   * @protected
   * @returns
   * @memberof XamGridComponent
   */
  protected getGridRemainSpaceInfo() {
    let starTotalSpace = 0;
    let usedPixelSize = 0;
    /* istanbul ignore else */
    if (this.grid.columns) {
      this.grid.columns.forEach((col) => {
        const colModel = this.getColumnModelByKey(col.field);
        if (colModel?.Visibility) {
          switch (colModel.WidthResolved.WidthType) {
            case ColumnWidthType.Numeric:
              usedPixelSize += colModel.WidthResolved.Value;
              break;
            case ColumnWidthType.Star:
              starTotalSpace += colModel.WidthResolved.Value;
              break;
            default:
              usedPixelSize += this.getColumnCalcPixelWidth(col);
              break;
          }
        }
      });
    }
    return [starTotalSpace, usedPixelSize];
  }

  /**
   * Sets the columns width to numeric values when resizing from UI.
   * All columns should be resized to a numeric value.
   *
   * @protected
   * @returns
   * @memberof XamGridComponent
   */
  protected setsColumnsToNumericValues(): void {
    if (this.grid.columns) {
      this.grid.columns.forEach((col) => {
        const colModel = this.getColumnModelByKey(col.field);
        if (colModel) {
          colModel.Width = new ColumnWidth(
            this.getColumnCalcPixelWidth(col),
            ColumnWidthType.Numeric
          );
        }
      });
    }
  }

  /**
   * Gets the column current used pixel width
   *
   * @protected
   * @param {IgxColumnComponent} col
   * @returns
   * @memberof XamGridComponent
   */
  protected getColumnCalcPixelWidth(col: IgxColumnComponent) {
    return col.calcPixelWidth;
  }

  /**
   * Sets the igx column size for special scenarios using autosize
   *
   * @protected
   * @param {*} col
   * @param {ColumnWidth} columnWidth
   * @memberof XamGridComponent
   */
  protected setColumnWidthSpecialCase(
    col: any,
    columnWidth: ColumnWidth
  ): boolean {
    try {
      switch (columnWidth.WidthType) {
        // Note that for both the following width types only the initially rendered columns
        // will be affected.
        case ColumnWidthType.SizeToCells:
        case ColumnWidthType.Auto:
        case ColumnWidthType.InitialAuto:
          col.autosize();
          break;
        case ColumnWidthType.SizeToHeader:
          col.autosize(true);
          break;
        case ColumnWidthType.Star:
        case ColumnWidthType.Numeric:
          col.autosizeHeader = false;
          break;
        default:
          break;
      }
    } catch {
      return false;
    }
    return true;
  }

  /**
   * Set column properties based on the data grid model setting objects.
   * Called only once, during rendering.
   *
   * @protected
   * @memberof XamGridComponent
   */
  protected setColumnProperties(collection: any) {
    collection.forEach((column: XamGridColumnModel) => {
      /* istanbul ignore else */
      if (!this.model.SortingSettings.AllowSorting) {
        column.IsSortable = false;
      }

      /* istanbul ignore else */
      if (this.model.FixedColumnSettings.AllowFixedColumns) {
        column.IsFixable = true;
      }

      /* istanbul ignore else */
      if (this.model.ColumnResizingSettings.AllowColumnResizing) {
        column.IsResizable = true;
      }

      /* istanbul ignore else */
      if (this.model.ColumnMovingSettings.AllowColumnMoving) {
        column.IsMovable = true;
      }

      /* istanbul ignore else */
      if (column instanceof XamGridGroupColumnModel) {
        this.setColumnProperties(column.Columns);
      }
    });
  }

  /**
   * Applies grid selection settings from template directive if defined.
   *
   * @protected
   * @return {*}  {void}
   * @memberof XamGridComponent
   */
  protected setupSelectionSettings(): void {
    if (!this.selection) {
      return;
    }
    this.selectionSettings.CellSelection = this.selection.cellSelection;
    this.selectionSettings.RowSelection = this.selection.rowSelection;
    this.selectionSettings.ColumnSelection = this.selection.columnSelection;
    this.selectionSettings.CellClickAction = this.selection.cellClickAction;
  }

  /**
   * Applies grid editing settings from template directive if defined.
   *
   * @protected
   * @return {*}  {void}
   * @memberof XamGridComponent
   */
  protected setupEditingSettings(): void {
    /* istanbul ignore else */
    if (!this.editingComponent || !this.editingComponent.allowEditing) {
      return;
    }
    /* istanbul ignore else */
    if (XamGridEditingType[this.editingComponent.allowEditing]) {
      this.model.EditingSettings.AllowEditing =
        XamGridEditingType[this.editingComponent.allowEditing];
      /* istanbul ignore else */
      if (this.model.EditingSettings.AllowEditing !== XamGridEditingType.None) {
        this.model.Columns.forEach((column) => {
          /* istanbul ignore else */
          if (!column.IsReadOnly) {
            column.Editable = true;
          }
        });
      }
    }
    /* istanbul ignore else */
    if (MouseEditingAction[this.editingComponent.isMouseActionEditingEnabled]) {
      this.model.EditingSettings.IsMouseActionEditingEnabled =
        MouseEditingAction[this.editingComponent.isMouseActionEditingEnabled];
    }
    this.model.EditingSettings.IsOnCellActiveEditingEnabled =
      this.editingComponent.isOnCellActiveEditingEnabled;
    this.model.EditingSettings.IsEnterKeyEditingEnabled =
      this.editingComponent.isEnterKeyEditingEnabled;
    this.model.EditingSettings.IsF2EditingEnabled =
      this.editingComponent.isF2EditingEnabled;
  }

  /**
   * Applies column resizing settings from template directive if defined.
   *
   * @protected
   * @return {*}  {void}
   * @memberof XamGridComponent
   */
  protected setupColumnResizing(): void {
    if (!this.resizing) {
      return;
    }
    this.model.ColumnResizingSettings.AllowColumnResizing =
      this.resizing.allowColumnResizing;
  }

  /**
   * Applies grid column moving settings from template directive if defined.
   *
   * @protected
   * @return {*}  {void}
   * @memberof XamGridComponent
   */
  protected setupColumnMovingSettings(): void {
    if (!this.columnMoving) {
      return;
    }
    this.model.ColumnMovingSettings.AllowColumnMoving =
      this.columnMoving.allowColumnMoving;
  }

  /**
   * Applies grid filtering settings from template directive if defined.
   *
   * @protected
   * @return {*}  {void}
   * @memberof XamGridComponent
   */
  protected setupFilteringSettings(): void {
    /* istanbul ignore else */
    if (!this.filtering) {
      return;
    }
    this.model.FilteringSettings = this.filtering.model;
  }

  /**
   * Synchronize the grid SortingSettings with the model SortingSettings.
   *
   * @protected
   * @return {*}  {void}
   * @memberof XamGridComponent
   */
  protected setupSortingSettings(): void {
    /* istanbul ignore else */
    if (!this.sortingComponent) {
      return;
    }
    this.model.SortingSettings = this.sortingComponent.model;
  }

  /**
   * Synchronize the grid sortingExpressions with the model SortingSettings.
   *
   * @protected
   * @return {*}  {void}
   * @memberof XamGridComponent
   */
  protected setupSortedColumns(): void {
    this.sortingExpressions.forEach((e) => this.addColumnFromExpression(e));
    this.syncSortedColumns();
    this.sortedColumnsHandler = new NotifyCollectionChangedHandler(
      this.syncSortedColumns.bind(this)
    );
    this.sortedColumnsHandler.trackCollection(
      this.model.SortingSettings.SortedColumns
    );
  }

  /**
   * Sets the grid sortingExpressions based on the model information.
   *
   * @protected
   * @return {*}  {void}
   * @memberof XamGridComponent
   */
  protected syncSortedColumns() {
    if (this.model.SortingSettings.SortedColumns) {
      this.sortingExpressions =
        this.model.SortingSettings.SortedColumns.toArray().map((column) => {
          let sortDirection: SortingDirection = SortingDirection.None;
          switch (column.IsSorted) {
            case SortDirection.Ascending:
              sortDirection = SortingDirection.Asc;
              break;
            case SortDirection.Descending:
              sortDirection = SortingDirection.Desc;
              break;
          }
          return {
            fieldName: 'data.' + column.Key,
            dir: sortDirection,
            ignoreCase: true,
            strategy:
              (column.SortComparer as any) ?? DefaultSortingStrategy.instance(),
          };
        });
    }
  }

  /**
   * Synchronize the grid filteringExpressions with the model FilteringSettings.
   *
   * @protected
   * @return {*}  {void}
   * @memberof XamGridComponent
   */
  protected setupFilteringExpressions(): void {
    this.syncFilteringExpressions();
    this.filteredExpressionsHandler = new NotifyCollectionChangedHandler(
      this.syncFilteringExpressions.bind(this)
    );
    this.filteredExpressionsHandler.trackCollection(
      this.model.FilteringSettings.RowFiltersCollection
    );
  }

  /**
   * Sets the grid filteringExpressions based on the info of the model.
   *
   * @protected
   * @return {*}  {void}
   * @memberof XamGridComponent
   */
  protected syncFilteringExpressions() {
    if (this.grid && this.model.FilteringSettings.RowFiltersCollection) {
      this.grid.clearFilter();
      this.model.RowsManager.InvalidateRows(true);
      this.model.FilteringSettings.RowFiltersCollection.toArray().forEach(
        (filter: IRecordFilter) => {
          if (filter.Conditions && filter.Conditions.length > 0) {
            (
              this.filteringExpressions as FilteringExpressionsTree
            ).filteringOperands.push({
              fieldName: filter.Conditions[0].fieldName,
              filteringOperands: [
                {
                  fieldName: filter.Conditions[0].fieldName,
                  searchVal: filter.Conditions[0].searchVal,
                  condition: filter.Conditions[0].condition,
                  ignoreCase: filter.Conditions[0].ignoreCase,
                },
              ],
            } as IFilteringExpressionsTree);
          }
        }
      );
    }
  }

  /**
   * Applies grid summary settings from template directive if defined.
   *
   * @protected
   * @return {*}  {void}
   * @memberof XamGridComponent
   */
  protected setupSummarySettings(): void {
    if (!this.summary) {
      return;
    }
  }

  /**
   * Applies grid pagination settings from template directive if defined.
   *
   * @protected
   * @return {*}  {void}
   * @memberof XamGridComponent
   */
  protected setupPaginationSettings(): void {
    if (!this.pagination) {
      return;
    }
    this.pagination.setupModelFromParent(this.model.PagerSettings);
    this.model.PagerSettings = this.pagination.model;
    this.xamGridContext.newItemsPerPage =
      this.model.PagerSettings.PageSize.toString();

    this.registerHandler(this.model.PagerSettings.change, (propertyName) => {
      if (propertyName == 'PageSize') {
        if (this.model.ItemsSource['PageSize']) {
          this.model.ItemsSource['PageSize'] =
            this.model.PagerSettings.PageSize;
          this.xamGridContext.newItemsPerPage =
            this.model.PagerSettings.PageSize.toString();
        }
      }
    });
  }

  /**
   * Enables row selectors settings from template directive if defined.
   *
   * @protected
   * @return {*}
   * @memberof XamGridComponent
   */
  protected setupRowSelectorsSettings(): void {
    if (!this.rowSelectors) {
      return;
    }

    this.model.RowSelectorSettings = this.rowSelectors.model;

    /* istanbul ignore else */
    if (this.model.RowSelectorSettings.EnableRowNumbering) {
      // Emulate the the row selector directive as 'being' in the igx-grid.
      this.grid.rowSelectorsTemplates = new QueryList();
      this.grid.rowSelectorsTemplates.reset([
        { templateRef: this.rowSelectors.template },
      ] as any);
    }
  }

  /**
   * Applies Xam grid settings defined in the context of the xam grid as template bindings
   *
   * @protected
   * @memberof XamGridComponent
   */
  protected setupGridSettings(): void {
    this.setupColumnMovingSettings();
    this.setupColumnResizing();
    this.setupSelectionSettings();
    this.setupEditingSettings();
    this.setupFilteringSettings();
    this.setupSortingSettings();
    this.setupSummarySettings();
    this.setupPaginationSettings();
  }

  /**
   * Creates the tracking needed for the even emitter when a new cell has entered
   * the view.
   *
   * @protected
   * @memberof XamGridComponent
   */
  protected setupCellTracker(): void {
    const subscribeCallback = (e: IForOfState) => {
      this.clearResolvedCellControl();
      const { startIndex, chunkSize } = e;
      if (
        this.evaluateColumnDataErrors(this.model.ActiveCell?.Row?.Data) &&
        startIndex > this.model.ActiveCell?.Row?.Index
      ) {
        this.removeAllErrorMessages();
      }
      for (let i = startIndex; i < startIndex + chunkSize; i++) {
        const row = this.grid.getRowByIndex(i);
        if (row) {
          this.processRowCells(row);
        }
      }
    };

    this.grid.verticalScrollContainer?.chunkLoad.subscribe(subscribeCallback);
    this.grid.parentVirtDir?.chunkLoad.subscribe(() =>
      subscribeCallback(this.grid.verticalScrollContainer.state)
    );
  }

  /**
   * Method in charge of reset the cell control content herarchy resolutions when required
   * Used in rows scrolling to avoid wrong references in reused controls
   *
   * @memberof XamGridComponent
   */
  clearResolvedCellControl() {
    this.resolvedCellControlContent.forEach((c) => (c.Content = null));
    this.resolvedCellControlContent = [];
  }

  /**
   * For each available row at rendering it will register its cells.
   *
   * @protected
   * @type {void}
   * @memberof XamGridComponent
   */
  protected setupAvailableRows(): void {
    if (this.internalXamGrid) return;
    const availableRows = this.gridRef?.rowList?.toArray();
    if (availableRows && availableRows.length > 0) {
      availableRows.forEach((row) => {
        this.registerCellControl(row);
      });
    }
  }

  /**
   * Register the available cells on the model.
   *
   * @protected
   * @type {void}
   * @memberof XamGridComponent
   */
  protected registerCellControl(row: any): void {
    const rowBase = this.model.Rows.getItem(row.index);
    row.cells.toArray().forEach((cell: any) => {
      const colKey = rowBase.Cells.getKey(cell);
      const col = this.model.Columns.getColumnByKeyDeep(colKey);
      const cellModel = new XamGridCell(rowBase, col.column);
      cellModel.Control = this.getCellControlIfExists(() => cell, cellModel);
      rowBase.Cells.add(cellModel);
    });
  }

  /**
   * Disables default browser behavior for events, and stops propagation through the DOM tree.
   *
   * @protected
   * @param {Event} event
   * @memberof XamGridComponent
   */
  protected disabledEventsHandler = (event: Event) => {
    /* istanbul ignore else */
    if (this.model.IsEnabled) {
      return;
    }
    event.preventDefault();
    event.stopPropagation();
  };

  /**
   * Workaround for the `IsEnabled` property. The listeners here are registered in the capture phase.
   *
   * @protected
   * @memberof XamGridComponent
   */
  protected setupDisabledOverlay() {
    /* istanbul ignore else */
    if (typeof this.ref.nativeElement.addEventListener === 'function') {
      DISABLED_EVENTS.forEach((type) => {
        this.ref.nativeElement.addEventListener(
          type,
          this.disabledEventsHandler,
          { capture: true }
        );
      });
    }
  }

  /**
   * Manipulate the default bottom pager of the grid component to emulate all the values
   * from the PageLocation enumeration.
   *
   * @protected
   * @param {PagingLocation} value
   * @memberof XamGridComponent
   */
  protected adjustPaginator = (value: PagingLocation) => {
    if (
      value === PagingLocation.Top ||
      value === PagingLocation.Hidden ||
      value === PagingLocation.None
    ) {
      const pager = this.grid?.nativeElement?.querySelector(
        '.igx-grid__footer igx-paginator'
      ) as HTMLElement;
      /*istanbul ignore next */
      if (pager) {
        // if pager is displayed then hide it
        pager.style.display = 'none';
      }
    }
  };

  /**
   * Helper method for creating event params.
   *
   * @private
   * @return {*}
   * @memberof XamGridComponent
   */
  private createEventParams(): any {
    return { sender: this.model, e: this };
  }

  /**
   * Returns a column model by key, if found.
   *
   * @private
   * @param {string} key
   * @return {*}  {(XamGridColumnModel | undefined)}
   * @memberof XamGridComponent
   */
  private getColumnModelByKey(
    key: string,
    searchInGroups = false
  ): XamGridColumnModel | undefined {
    const columnKey = this.getColumnKey(key);
    let colModel = this.model.Columns.internalArray.find(
      (column) => column.Key === columnKey
    );
    if (!colModel && searchInGroups) {
      for (const col of this.model.Columns.internalArray) {
        if (col instanceof XamGridGroupColumnModel) {
          colModel = col.Columns.internalArray.find(
            (column) => column.Key === columnKey
          );
        }
        if (colModel) {
          break;
        }
      }
    }
    return colModel;
  }

  /**
   * Gets the column key
   *
   * @private
   * @param {string} key
   * @returns
   * @memberof XamGridComponent
   */
  private getColumnKey(key: string) {
    return key && key.startsWith('data.') ? key.slice(5) : key ?? '';
  }

  /**
   * Helper method to add a column to a column collection.
   * Used to handle filtering/sorting/grouping.
   *
   * @private
   * @param {*} expression
   * @param {ObservableCollection<XamGridColumnModel>} collection
   * @memberof XamGridComponent
   */
  private addColumnFromExpression(expression: any): void {
    const collection = this.model.SortingSettings.SortedColumns;
    collection.clear();
    const colKey = expression.fieldName.replace('data.', '');
    const column = this.getColumnModelByKey(colKey, true);
    let sortDirection: SortDirection = SortDirection.None;
    switch (expression.dir) {
      case SortingDirection.Asc:
        sortDirection = SortDirection.Ascending;
        break;
      case SortingDirection.Desc:
        sortDirection = SortDirection.Descending;
        break;
    }
    column.IsSorted = sortDirection;
    const matchingSortedCol = iuFirstOrDefault(
      iuWhere((col) => col.Key === colKey, collection)
    );
    if (!matchingSortedCol) {
      collection.add(column);
    }
  }

  /**
   * Returns the DOM element of the cell
   *
   * @param {CellType} cell
   * @return {*} {*}
   * @memberof XamGridComponent
   */
  getNativeElement(cell: CellType): any {
    try {
      // In Silverlight you can access the element for all the rows in the xamGrid,
      // but in Angular you can only access the elements for the visible rows.
      if (cell == null || this.grid?.rowList.length <= 0) {
        return null;
      }
      /* istanbul ignore next */
      return this.ref?.nativeElement?.querySelector(
        `[data-rowindex="${cell.row.index}"][data-visibleindex="${cell.column.visibleIndex}"]`
      );
    } catch {
      return null;
    }
  }

  /**
   * Gets filtering cell DOM elements
   *
   * @returns NodeList
   * @memberof XamGridComponent
   */
  getFilteringCells(): any {
    return this.ref?.nativeElement?.querySelectorAll('igx-grid-filtering-cell');
  }

  /**
   * Exits edit mode on row changed
   *
   * @private
   * @param {number} newRowIndex
   * @memberof XamGridComponent
   */
  private exitEditOnRowChanged(newRowIndex: number): void {
    /* istanbul ignore else */
    if (
      this.inEditMode &&
      this.model.SelectedIndex != newRowIndex &&
      newRowIndex != -1 &&
      this.model.EditingSettings.IsMouseActionEditingEnabled ===
        MouseEditingAction.DoubleClick
    ) {
      this.processTriggerExitEditMode('triggerExitEditMode', true);
    }
  }

  /**
   * Gets cell control if it exists.
   *
   * @param {() => CellType} cell
   * @param {any} cellModel
   * @returns {any}
   * @memberof XamGridComponent
   */
  private getCellControlIfExists(cell: () => CellType, cellModel: any): any {
    const control = new XamGridCellControl();
    control.Column = cellModel.Column;
    control.onDemandLoadDataContext = () =>
      this.resolveCellDataContext(control.Cell);
    control.Cell = cellModel;
    /* istanbul ignore else */
    if (cellModel.Column?.ItemTemplate || cellModel.Column?.EditorTemplate) {
      control.LazyLoadContent = () => {
        const element = this.getNativeElement(cell());
        return this.getModelToUse(control, element);
      };
    } else {
      control.LazyLoadContent = null;
    }
    return control;
  }

  /**
   * Returns component model with tooltip handler
   *
   * @param {any} component
   * @param {any} control
   * @returns {any}
   * @memberof XamGridComponent
   */
  processElementComponent(component: any, control: any): any {
    if (component == null) {
      return null;
    }
    if (control) {
      this.registerHandler(control.ToolTipSet, (obj, ctx) => {
        component.syncToolTip(ctx);
      });
      this.resolvedCellControlContent.push(control);
    }
    return component.model;
  }

  /**
   * Returns model for content use
   *
   * @param {any} control
   * @param {any} element
   * @returns {any}
   * @memberof XamGridComponent
   */
  getModelToUse(control: any, element: any): any {
    let childToUse: Element | null = null;
    childToUse = this.findElement(element);
    if (!childToUse) {
      return null;
    } else if (childToUse['__component']?.model) {
      // Set Tooltip
      return this.processElementComponent(childToUse['__component'], control);
    } else if (childToUse.children?.length === 1) {
      // Set Tooltip
      return this.processElementComponent(
        childToUse.children[0]['__component'],
        control
      );
    }
    return null;
  }

  /**
   * If the element has children, return the first child that doesn't have the class
   * 'validationCornerError'.
   *
   * @param {any} element - any - the element that you want to find the child of
   * @returns the child element that is not a validationCornerError.
   * @memberof XamGridComponent
   */
  findElement(element: any): Element | null {
    const hasChildren = element?.children.length > 0;
    let childToUse: Element | null = null;
    if (!hasChildren) {
      return null;
    }
    for (const child of element.children) {
      if (!child.classList.contains('validationCornerError')) {
        childToUse = child;
        break;
      }
    }
    return childToUse;
  }

  /**
   * Returns cell DataContext
   *
   * @param {any} cellModel
   * @returns {any}
   * @memberof XamGridComponent
   */
  resolveCellDataContext(cellModel: any): any {
    return cellModel.Column instanceof XamGridUnboundColumnModel
      ? this.resolveUnboundColumnDataContext(cellModel)
      : cellModel.Row.Data;
  }

  /**
   * Creates a new UnboundColumnDataContext when the resolver is not defined otherwise just change the existing DataContext value.
   *
   * @param {any} cellModel
   * @returns {UnboundColumnDataContext}
   * @memberof XamGridComponent
   */
  private resolveUnboundColumnDataContext(
    cellModel: any
  ): UnboundColumnDataContext {
    if (!cellModel.UnboundDataContextResolver) {
      cellModel.UnboundDataContextResolver = new UnboundColumnDataContext(
        cellModel.Column.Key,
        cellModel.Row.Data,
        cellModel.Value
      );
    } else {
      const unboundContext: UnboundColumnDataContext =
        cellModel.UnboundDataContextResolver;
      unboundContext.RowData = cellModel.Row.Data;
      unboundContext.Value = cellModel.Value;
    }
    return cellModel.UnboundDataContextResolver;
  }

  /**
   * Create dn select a new XamGridRow
   *
   * @param {RowType} row
   * @return {any}
   * @memberof XamGridComponent
   */
  private processRowCells(row: any): void {
    const gridRow = this.createRow(row);
  }

  /**
   * Create or returns a cached row model from a rowType.
   * Could be a data row or a addNew row.
   *
   * @private
   * @param {RowType} row
   * @return {*}
   * @memberof XamGridComponent
   */
  private createRow(row: RowType) {
    const isNewRow = this.isNewRow(row);
    let rowIndex = row.index;
    if (isNewRow) {
      this.addRowKey = row;
    }
    if (this.addRowKey != null) {
      // we need to adjust the index because models.Rows does not contains the "new added row" when we are adding a new row
      rowIndex = row.index - 1;
    }
    const newRow = isNewRow
      ? this.getAddRow()
      : this.model.Rows.getItem(rowIndex);
    if (newRow == null) {
      return;
    }
    if (isNewRow) {
      newRow.IsSelected = false;
    }
    row.cells?.forEach((cell) => {
      const cellModel = newRow.Cells.registerCellFromUI(
        cell,
        newRow,
        this.Columns
      );
      cellModel.IsSelected = cell.selected;
      const cellType = () =>
        this.grid?.getCellByColumn(
          newRow.Index,
          'data.' + cellModel.Column.Key
        );
      cellModel.Control = this.getCellControlIfExists(cellType, cellModel);
    });
    return newRow;
  }

  /**
   * Validate if the row is an add new Row type.
   *
   * @param {RowType} [row] New row.
   * @return {*}  {boolean} `true` if the row is an add new row Type.
   * @memberof XamGridComponent
   */
  isNewRow(row: RowType): boolean {
    const isNew = row?.addRowUI || row?.key === this.addRowKey?.key;
    return isNew ?? false;
  }

  /**
   * Get the addNewRow position in the grid
   *
   * @return {*}  {*}
   * @memberof XamGridComponent
   */
  getAddRow(): any {
    return this.addNewRowInstance?.allowAddNewRow === 'Top'
      ? this.model.RowsManager.AddNewRowTop
      : this.model.RowsManager.AddNewRowBottom;
  }

  /**
   * The all columns collection
   *
   * @type {ColumnBaseCollection}
   * @memberof XamGridComponent
   */
  allColumns: ColumnBaseCollection;

  /**
   * Value which indicates if a change has occurred in a cell
   *
   * @memberof XamGridComponent
   */
  isCellChanged = 0;

  /**
   * Get all columns
   *
   * @param {ColumnBaseCollection | GroupColumnsCollection} columns
   * @return {ColumnBaseCollection}
   * @memberof XamGridComponent
   */
  getAllColumns(
    columns?: ColumnBaseCollection | GroupColumnsCollection
  ): ColumnBaseCollection {
    if (!columns) {
      columns = this.Columns;
      this.allColumns = new ColumnBaseCollection(
        this.model.RowsManager.ColumnLayout
      );
    }
    for (const column of columns) {
      if (column instanceof XamGridGroupColumnModel) {
        this.allColumns.add(<any>column);
        this.allColumns = this.getAllColumns(column.Columns);
      } else {
        this.allColumns.add(<any>column);
      }
    }
    return this.allColumns;
  }

  /**
   * Get a cell throuht it row and column.
   *
   * @return {any}
   * @memberof XamGridComponent
   */
  getCellByRowColumn(rowIndex: number, column: string): any {
    const row = this.model.Rows.getItem(rowIndex);
    const cell = row?.Cells.getCellByKey(column.substring(5));
    return { row, cell };
  }

  /**
   * Process filtering columns to add a filter tooltip
   *
   * @private
   * @memberof XamGridComponent
   */
  private processFilterCellTooltip(): void {
    const filteringColumns = this.getFilteringCells();
    if (
      this.filterCellTooltip &&
      filteringColumns &&
      filteringColumns.length > 0
    ) {
      filteringColumns.forEach((filteringColumn) => {
        filteringColumn.title = this.filterCellTooltip;
      });
    }
  }

  /**
   * Create row from data
   *
   * @private
   * @param {*} data
   * @param {number} index
   * @return {*}
   * @memberof XamGridComponent
   */
  private createRowFromData(data: any, index: number): any {
    const newRow = this.model.Rows.getItem(index);
    newRow.IsSelected = iuAny(
      this.selectionSettings.SelectedRows,
      (row: XamGridRow) => row.Data === data
    );
    return newRow;
  }

  /**
   * Remove  the attached subscription
   *
   * @private
   * @memberof XamGridComponent
   */
  private removeItemSourceHandler() {
    /* istanbul ignore else */
    if (this.collectionHandler) {
      this.data.CollectionChanged.removeHandler(this.collectionHandler);
      this.collectionHandler = null;
    }
  }

  /**
   * Process column layout when a row is selected
   *
   * @private
   * @param {XamGridRow[]} oldRows
   * @memberof XamGridComponent
   */
  private processColumnLayoutForRowSelection(oldRows: XamGridRow[]) {
    /* istanbul ignore else */
    if (this.gridColumnLayouts) {
      const lookInColumnLayout = oldRows.length === 0;
      this.gridColumnLayouts.forEach((colLayout) => {
        if (lookInColumnLayout) {
          colLayout.grid.selectedRows
            .map((key) => this.getRowFromModelByKey(key, colLayout))
            .forEach((r) => {
              if (r != null) {
                oldRows.push(r);
              }
            });
        }
        //deselectAllRows doesn't clear cell selection which happens by user clicking on a cell (singlor o with Ctrl)
        //or by setting a cell as selected (cell.selected = true)
        colLayout.grid.clearCellSelection();
        colLayout.grid.deselectAllRows(false);
      });
    }
  }

  /**
   * Deselects the rows from the main grid and column layouts grids.
   *
   * @param {*} sender
   * @param {SelectionCollectionChangedEventArgs<SelectedRowsCollection>} newEventArgs
   * @returns
   * @memberof XamGridComponent
   */
  private deselectGridRows(
    sender: any,
    newEventArgs: SelectionCollectionChangedEventArgs<SelectedRowsCollection>
  ) {
    /* istanbul ignore else */
    if (this.selectionSettings.RowSelection === XamSelectionMode.Single) {
      /* istanbul ignore else */
      if (newEventArgs.PreviouslySelectedItems.count === 1) {
        return;
      } else {
        this.processPreviousSelectedRows(sender, newEventArgs);
      }
    }
  }

  /**
   * Process previous selected rows when a row is selected in a column layout.
   *
   * @private
   * @param {*} sender
   * @param {SelectionCollectionChangedEventArgs<SelectedRowsCollection>} newEventArgs
   * @memberof XamGridComponent
   */
  private processPreviousSelectedRows(
    sender: any,
    newEventArgs: SelectionCollectionChangedEventArgs<SelectedRowsCollection>
  ) {
    /* istanbul ignore else */
    if (this.gridColumnLayouts) {
      this.gridColumnLayouts.forEach((colLayout) => {
        /* istanbul ignore else */
        if (colLayout.model !== sender) {
          colLayout.grid.selectedRows
            .map((key) => this.getRowFromModelByKey(key, colLayout))
            .forEach((row) => {
              /* istanbul ignore else */
              if (row != null) {
                newEventArgs.PreviouslySelectedItems.add(row);
              }
            });
          //deselectAllRows doesn't clear cell selection which happens by user clicking on a cell (singlor o with Ctrl)
          //or by setting a cell as selected (cell.selected = true)
          colLayout.grid.clearCellSelection();
          colLayout.grid.deselectAllRows(false);
        }
      });
    }
    const oldSelectedRows = this.grid.selectedRows.map((key) =>
      this.getRowFromModelByKey(key, this)
    );
    oldSelectedRows.forEach((r) => newEventArgs.PreviouslySelectedItems.add(r));
    //deselectAllRows doesn't clear cell selection which happens by user clicking on a cell (singlor o with Ctrl)
    //or by setting a cell as selected (cell.selected = true)
    this.grid.clearCellSelection();
    this.grid.deselectAllRows(false);
  }

  /**
   * Defines whether to show or not the cell tooltip by changing the title property
   *
   * @private
   * @param {IgxColumnComponent} column
   * @memberof XamGridComponent
   */
  private processAllowToolTipsByColumn(column: IgxColumnComponent): void {
    const colModel = this.getColumnModelByKey(column.field);
    // Updates only the cells of the current visible rows
    this.grid.dataRowList?.forEach((row) => {
      const columnCells = row.cells.filter((each) => each.column == column);
      // Sets tooltip visibility for each cell
      columnCells.forEach((cell) => {
        this.processAllowToolTips(cell, colModel);
      });
    });
  }

  /**
   * Process AllowToolTip property for all visible rows
   *
   * @private
   * @memberof XamGridComponent
   */
  private processAllowToolTipsByRow(): void {
    this.grid.dataRowList?.forEach((row) => {
      let colModel: XamGridColumnModel;
      // Sets tooltip visibility for each cell
      row.cells.forEach((cell) => {
        colModel = this.getColumnModelByKey(cell.column.field, true);
        this.processAllowToolTips(cell, colModel);
      });
    });
  }

  /**
   * Auxiliary function that defines the cell's tooltip by
   * changing the cell's element title property
   *
   * @param {CellType} cell
   * @param {XamGridColumnModel} model
   * @memberof XamGridComponent
   */
  private processAllowToolTips(
    cell: CellType,
    model: XamGridColumnModel
  ): void {
    const element: HTMLElement = this.getNativeElement(cell);
    if (!element) return;
    switch (model?.AllowToolTips) {
      case AllowToolTips.Always:
        element.title = cell.value;
        break;
      case AllowToolTips.Overflow:
        const isOverflow =
          element.firstElementChild.clientWidth <
          element.firstElementChild.scrollWidth;
        element.title = isOverflow ? cell.value : '';
        break;
      default:
        element.title = '';
        break;
    }
  }

  /**
   * Display an error message on the cell asociated with event.
   *
   * @param {string} msg
   * @param {IGridEditDoneEventArgs} event
   * @memberof XamGridComponent
   */
  showErrorMessageOnCell(msg: string, event: IGridEditDoneEventArgs): void {
    const element = this.getCellElementByEvent(event);
    this.addValidationHelper(element, msg);
    this.cellsWithValidationMsg.add(element);
  }

  /**
   * Removes the error message from the cell asociated with event, if there is any.
   *
   * @param {IGridEditDoneEventArgs} event
   * @memberof XamGridComponent
   */
  removeErrorMessageOnCell(event: IGridEditDoneEventArgs): void {
    const element = this.getCellElementByEvent(event);
    this.removeValidationHelper(element);
    this.cellsWithValidationMsg.delete(element);
  }

  /**
   * Removes error messages from all cells.
   *
   * @memberof XamGridComponent
   */
  removeAllErrorMessages(): void {
    for (const element of this.cellsWithValidationMsg.values()) {
      this.removeValidationHelper(element);
    }
    this.cellsWithValidationMsg.clear();
    this.validationErrorFlag = false;
  }

  /**
   * Removes the validation helper from an element, if it exists.
   *
   * @param {*} element
   * @memberof XamGridComponent
   */
  removeValidationHelper(element: any) {
    /* istanbul ignore else */
    if (element.validationHelper) {
      (
        element.validationHelper as ValidationHelper
      ).unregisterValidationMsgService();
      element.validationHelper = null;
    }
  }

  /**
   * Attach a validation helper to the given element.
   *
   * @param {*} element
   * @param {string} msg
   * @memberof XamGridComponent
   */
  addValidationHelper(element: any, msg: string) {
    /* istanbul ignore else */
    if (!element.validationHelper) {
      element.validationHelper = new ValidationHelper(
        new ElementRef(element),
        this.injector
      );
    }
    (element.validationHelper as ValidationHelper).registerValidationMsgService(
      msg,
      undefined,
      undefined,
      true
    );
  }

  /**
   * Gets the cell associated with the given event.
   *
   * @private
   * @param {IGridEditDoneEventArgs} event
   * @return {*}  {*}
   * @memberof XamGridComponent
   */
  private getCellElementByEvent(event: IGridEditDoneEventArgs): any {
    return this.getNativeElement(
      this.grid.getRowByKey(event.rowID).cells[event.cellID.columnID]
    );
  }

  /**
   * Converts the given value to `null` if it is an empty string,
   * otherwise it converts the value to `number` and check if it
   * is within allowed limits for `int` type.
   *
   * @private
   * @param {{valid: boolean, value: any}} result
   * @return {*}  {void}
   * @memberof XamGridComponent
   */
  private checkNullableIntLimits(result: { valid: boolean; value: any }): void {
    /* istanbul ignore else */
    if (result.value === '' || result.value == null) {
      result.value = null;
      result.valid = true;
      return;
    }

    this.checkIntLimits(result);
  }

  /**
   * Converts the given value to `number` and check if
   * it is within allowed limits for `int` type.
   *
   * @private
   * @param {{valid: boolean, value: any}} result
   * @return {*}  {void}
   * @memberof XamGridComponent
   */
  private checkIntLimits(result: { valid: boolean; value: any }): void {
    let value = result.value;
    if (typeof value === 'string' && /^\s*(\+|-)?\d+\s*$/.test(value)) {
      value = Number.parseInt(value, 10);
    }

    if (
      typeof value === 'number' &&
      value <= 2147483647 &&
      value >= -2147483648
    ) {
      result.value = value;
      result.valid = true;
      return;
    }

    result.valid = false;
  }

  /**
   * Converts the given value to `number` and check if
   * it is within allowed limits for `decimal` type.
   *
   * NOTE: `number` limits are much lower than `decimal` limits,
   *       so a true check for decimal limits is not possible
   *       with primitive JS `number` type.
   *
   * @private
   * @param {{valid: boolean, value: any}} result
   * @return {*}  {void}
   * @memberof XamGridComponent
   */
  private checkDecimalLimits(result: { valid: boolean; value: any }): void {
    let value = result.value;
    if (
      typeof value === 'string' &&
      /^\s*(?:\+|-)?\d+(?:.\d+)?\s*$/.test(value)
    ) {
      value = Number.parseFloat(value);
    }

    if (
      typeof value === 'number' &&
      value <= Number.MAX_SAFE_INTEGER &&
      value >= Number.MIN_SAFE_INTEGER
    ) {
      result.value = value;
      result.valid = true;
      return;
    }

    result.valid = false;
  }

  /**
   * Indicates if the columns width calculation mechanism should be trigger again
   *
   * @private
   * @returns
   * @memberof XamGridComponent
   */
  private shouldReCalcColumnsWidth() {
    return (
      (this.grid.calcWidth !== this.cachedGridWidth &&
        Math.abs(this.grid.calcWidth - this.cachedGridWidth) >=
          this.toleranceGridColumnWidth) ||
      this.forcedColumnsWidthCalc
    );
  }

  /**
   * Manages the tab key navigation for the grid cells
   *
   * @param {boolean} isShift if the shift key is being pressed
   */
  /* istanbul ignore next */
  private tabKeyNavigation(isShift: boolean): void {
    if (!this.model.ActiveCell) return;
    this.isTabKeyNavigating = true;
    const currentCell = this.model.ActiveCell;
    const igxCol = this.grid.getColumnByName('data.' + currentCell.Column.Key);
    const nextCell = isShift
      ? this.grid.getPreviousCell(currentCell.Row.Index, igxCol.visibleIndex)
      : this.grid.getNextCell(currentCell.Row.Index, igxCol.visibleIndex);
    const colField = this.grid.getColumnByVisibleIndex(
      nextCell.visibleColumnIndex
    ).field;
    let cellModel: CellBase = this.getCellByRowColumn(
      nextCell.rowIndex,
      colField
    ).cell;

    // Clear selection on row changed
    if (
      this.selectionSettings.RowSelection === XamSelectionMode.Multiple &&
      currentCell.Row.Index !== nextCell.rowIndex
    ) {
      this.model.ClearSelectedRows();
      this.grid.deselectAllRows();
    }

    // Changes to the next cell
    if (
      currentCell.Row.Index !== nextCell.rowIndex &&
      this.evaluateColumnDataErrors(this.model.ActiveCell?.Row?.Data)
    ) {
      cellModel = this.getCellByRowColumn(currentCell.Row.Index, colField).cell;
    }
    this.model.ActiveCell = cellModel;
    this.grid.navigation.setActiveNode({
      row: cellModel.Row.Index,
      column: nextCell.visibleColumnIndex,
    });
  }

  /**
   * Triggers a collection changed for each row
   *
   * @private
   * @memberof XamGridComponent
   */
  private RowCollectionHandler(isRendering = false): void {
    this.isHandlingCollectionChanges = true;
    if ((this.renderedCalled || isRendering) && this.grid) {
      this.grid.data = this.dataHandler();
    } else {
      return;
    }
    this.Rows.CollectionChanged.fire([
      this.model,
      new CollectionChangeInfo(CollectionChangeAction.Reset),
    ]);
    this.callProcessActiveCellFlag = true;
    this.refreshRowsTimer = setTimeout(() => {
      this.callProcessActiveCellFlag = false;
      this.executeInitializeRowSequence();
      this.gridDataHandler();
      this.InvalidateSelectionAndActivation();
      if (this.model.Visibility === true && !this.grid?.cdr?.['destroyed']) {
        if (this.isColumnsWidthSet) this.setColumnsWidth(true);
        setTimeout(() => {
          this.grid.markForCheck?.();
        }, 100);
      }
      // Try to set the state of the activeCell in the igx-grid
      this.model.contextActiveCell?.();
      this.detectChangesAction();
      this.isHandlingCollectionChanges = false;
    });
  }

  /**
   * "For each row in the model, fire the InitializeRow event, then for each cell in the row, fire the
   * CellControlAttached event."
   *
   * memberof XamGridComponent
   */
  executeInitializeRowSequence(): void {
    for (const row of this.model.Rows.toArray()) {
      this.model.InitializeRow.fire([
        this.model,
        new InitializeRowEventArgs(row),
      ]);
      row.Cells?.internalArray.forEach((cell) => {
        this.cellControlEvents(cell);
      });
    }
  }

  /**
   * Adjust the pager settings and initialize required fields
   *
   * @private
   * @memberof XamGridComponent
   */
  private adjustPagerSettings() {
    // Workaround for the page location settings
    this.adjustPaginator(this.model.PagerSettings.AllowPaging);
    if (this.pagination) {
      this.pagination.allowPagingChange.subscribe(this.adjustPaginator);
    }
    if (this.pagingHandler()) {
      this.xamGridContext.newItemsPerPage =
        this.model.PagerSettings.PageSize.toString();
    }
  }

  /**
   * Set the Active Cell in editMode if the conditions are met
   *
   * @memberof XamGridComponent
   */
  processActiveCell(
    isOnCellActiveEditingEnabled: boolean,
    isReadOnly: boolean
  ): void {
    const cellType = this.grid?.getCellByColumn(
      this.model.ActiveCell?.Row.Index,
      'data.' + this.model.ActiveCell?.Column.Key
    );
    /* istanbul ignore else */
    if (cellType && isOnCellActiveEditingEnabled && !isReadOnly) {
      this.cellEnterEditMode(cellType, true);
    } else if (cellType && !isReadOnly && cellType.column.index === 0) {
      this.grid.navigateTo(
        cellType?.row.index,
        cellType?.column.index,
        (args) => {
          args.target.activate();
        }
      );
    }
  }

  /**
   * Clean the active cell of the xam-grid component
   *
   * @memberof XamGridComponent
   */
  cleanActiveFromIgxGrid(): void {
    if (this.grid?.navigation?.activeNode) {
      this.grid.navigation._activeNode = {} as any;
    }
  }

  /**
   * Changes the page base on the newItemsPerPage value
   *
   * @memberof XamGridComponent
   */
  changePage(): void {
    this.model.PagerSettings.PageSize = parseInt(this.newItemsPerPage);
    this.allowChangeItemsPerPage = false;
  }

  /**
   * Lost focus handler for page size change control textarea
   *
   * @memberof XamGridComponent
   */
  lostFocusTextPerPage(): void {
    this.allowChangeItemsPerPage = true;
    let value: number;
    if (
      !(
        smTryParseFloat(
          this.newItemsPerPage,
          out((v) => (value = v))
        ) &&
        value % 1 === 0 &&
        value > 0
      )
    ) {
      this.newItemsPerPage = this.model.PagerSettings.PageSize.toString();
    }
  }

  /**
   * Returns true if the FilteringSettings.AllowFiltering is enabled, otherwise false.
   *
   * @type {boolean}
   * @memberof XamGridComponent
   */
  get filteringSettingsEnabled(): boolean {
    return this.model.FilteringSettings.AllowFiltering !== 0;
  }

  /**
   * Validates is the grid is already rendered on screen
   *
   * @return {boolean}
   * @memberof XamGridComponent
   */
  get isGridVisible(): boolean {
    if (!this.grid) return false;
    const rect = this.grid.nativeElement.getBoundingClientRect();
    return (
      this.renderedCalled &&
      !!this.grid.calcWidth &&
      rect.width >= this.grid.calcWidth &&
      rect.height >= this.grid.calcHeight
    );
  }

  /**
   * Explicit mark to be added to the grid to indicate the type of filtering being applied, so custom code can
   * do css rules customizations, possible values are:
   *  none|excelStyleFilter|quickFilter
   *
   * @readonly
   * @type {string}
   * @memberof XamGridComponent
   */
  get wmFilterApplied(): string {
    /* istanbul ignore else */
    if (!this.filteringSettingsEnabled) {
      return 'none';
    }
    return this.model.FilteringSettings.AllowFiltering === 3
      ? 'excelStyleFilter'
      : 'quickFilter';
  }

  /**
   * If the column has a SortComparer, return it. Otherwise, return null.
   * @param {XamGridColumnModel} col - XamGridColumnModel - The column model that is being sorted.
   * @returns The comparer function that will be used to sort the column.
   */
  getStrategy(col: XamGridColumnModel): any {
    if (col.SortComparer) {
      return col.SortComparer;
    }
    return DefaultSortingStrategy.instance();
  }

  /**
   * Returns true if the column IsFilterable and AllowFiltering is true for the grid model. Otherwise, return false.
   * @param {XamGridColumnModel} col - XamGridColumnModel - The column model that is evaluated.
   * @returns boolean.
   */
  getFilterable(col: XamGridColumnModel): any {
    return col.IsFilterable && this.model.FilteringSettings.AllowFiltering;
  }

  /**
   * "If the itemsSource is null or empty, or the active cell's row index is greater than the number of
   * items in the itemsSource, or the active cell's row data is not in the itemsSource, then return
   * true."
   *
   *
   * @param {any} itemsSource1 - The data source for the grid.
   * @returns The return value is a boolean.
   * @memberof XamGridComponent
   */
  private shouldInvalidateActiveCell(itemsSource1: any) {
    return (
      !itemsSource1 ||
      iuCount(itemsSource1) <= this.model.ActiveCell.Row.Index ||
      !itemsSource1.contains(this.model.ActiveCell.Row.Data)
    );
  }

  /**
   *  Sets the parent row property of nested rows
   * @param {XamGridModel} model - Model that contains the nested rows
   * @param {any} rowInternalIndex - The parent row internal index data
   * @memberof XamGridComponent
   */

  private setParentRow(model: XamGridModel, rowInternalIndex: any): void {
    const index = this.grid.getRowByKey(
      rowInternalIndex?.__xam_internal_pk__
    )?.index;
    if (index != -1) {
      const parentRow = this.Rows.getItem(index);
      model.Rows?.toArray().forEach((item) => {
        item.ParentRow = parentRow;
      });
    }
  }

  /**
   * Gets GridSelectionMode depending of the selection value
   * @returns GridSelectionMode
   * @memberof XamGridComponent
   */
  getGridSelectionMode(selection: string): GridSelectionMode {
    switch (selection) {
      case 'None': {
        return GridSelectionMode.none;
      }
      case 'Single': {
        return GridSelectionMode.single;
      }
      case 'Multiple': {
        return GridSelectionMode.multiple;
      }
    }
    return GridSelectionMode.none;
  }

  /**
   * Select true if CellClickAction is SelectRow
   * @returns The return value is a boolean.
   * @memberof XamGridComponent
   */
  get selectRowOnClick(): boolean {
    return (
      this.selectionSettings.CellClickAction === CellSelectionAction.SelectRow
    );
  }
}

/**
 * Custom filter operands for xam grid.
 *
 * @class XamGridCustomFilterOperands
 * @extends {IgxStringFilteringOperand}
 */
class XamGridCustomFilterOperands extends IgxStringFilteringOperand {
  /**
   * Creates an instance of XamGridCustomFilterOperands.
   *
   * @memberof XamGridCustomFilterOperands
   */
  private constructor() {
    super();
    this.operations = [
      ...this.operations.slice(0, 4),
      new DoesNotStartWithOperand().operand,
      new DoesNotEndWithOperand().operand,
      ...this.operations.slice(4),
    ];
  }
}
<ng-container *ngIf="model.Visibility">
  <div
    #igxBodyOverlayOutlet
    igxOverlayOutlet
    class="xamGridClass"
    [ngClass]="{
      'xam-grid-with-paging-bottom': model.PagerSettings.AllowPaging === 1
    }"
    [style.border-style]="borderStyle"
    [style.border-color]="borderBrush"
    [style.border-width]="borderThickness"
    [style.margin]="margin"
  >
    <!-- Top pager section -->
    <ng-container *ngIf="grid?.rendered$ | async">
      <igx-paginator
        #paginator
        *ngIf="
          grid &&
          (model.PagerSettings.AllowPaging === 4 ||
            model.PagerSettings.AllowPaging === 0)
        "
        [(page)]="model.PagerSettings.CurrentPageIndex"
        [totalRecords]="grid.totalRecords"
        [(perPage)]="model.PagerSettings.PageSize"
        [totalRecords]="totalPagingRecordsHandler()"
      >
        <igx-paginator-content>
          <label class="igx-page-size__label">Items Per Page</label>
          <div class="igx-page-size__select">
            <textarea
              class="itemsPerPage"
              [(ngModel)]="newItemsPerPage"
              (blur)="lostFocusTextPerPage()"
              maxlength="4"
            ></textarea>
            <div
              class="setItemsPerPageBorder"
              [class.disabled]="!allowChangeItemsPerPage"
            >
              <button class="setItemsPerPage" (click)="changePage()">Go</button>
            </div>
          </div>
          <igx-page-nav></igx-page-nav>
        </igx-paginator-content>
      </igx-paginator>
    </ng-container>
    <!-- End top pager section -->

    <igx-grid
      #grid
      *ngIf="model?.Columns"
      [data]="dataHandler | memoize: collection"
      displayDensity="compact"
      [rowEditable]="model.EditingSettings.AllowEditing === 2"
      [allowFiltering]="filteringSettingsEnabled"
      [attr.wm-filter-applied]="wmFilterApplied"
      [filterMode]="
        model.FilteringSettings.AllowFiltering === 3
          ? 'excelStyleFilter'
          : 'quickFilter'
      "
      [hideRowSelectors]="selectionSettings.HideRowCheckboxes"
      [cellSelection]="getGridSelectionMode(selectionSettings.CellSelection)"
      [rowSelection]="getGridSelectionMode(selectionSettings.RowSelection)"
      [columnSelection]="
        getGridSelectionMode(selectionSettings.ColumnSelection)
      "
      (rendered)="renderedHandler()"
      [selectRowOnClick]="selectRowOnClick"
      [height]="calcVirtualHeight()"
      [rowHeight]="dataGridRowHeight"
      (rowSelectionChanging)="rowSelectionHandler($event)"
      (onColumnSelectionChange)="columnSelectionHandler($event)"
      (cellClick)="cellClickHandler($event)"
      (selected)="cellSelectionHandler($event)"
      (gridKeydown)="keydownHandler($event)"
      (keydown.control.enter)="this.beginAddRow()"
      (doubleClick)="doubleClickHandler($event)"
      (columnResized)="resizeHandler($event)"
      (columnPin)="pinningHandler($event)"
      (sorting)="sortingHandler($event)"
      (sortingDone)="sortingDoneHandler($event)"
      (gridScroll)="gridScrollHandler($event)"
      (filteringDone)="filteringHandler($event)"
      (cellEditDone)="cellEditedHandler($event)"
      (cellEdit)="cellEditHandler($event)"
      (cellEditEnter)="enterEditHandler($event)"
      (cellEditExit)="exitEditHandler($event)"
      (rowEdit)="rowEditHandler($event)"
      (rowEditExit)="rowExitEditHandler($event)"
      (rowEditEnter)="rowEnterEditHandler($event)"
      (activeNodeChange)="activeNodeHandler($event)"
      (rowAdd)="rowAddedHandler($event)"
      (rowDeleted)="rowDeletedHandler($event)"
      (pagingDone)="paginationHandler($event)"
      (dataChanged)="dataChangedHandler($event)"
      [sortingExpressions]="sortingExpressions"
      [(filteringExpressionsTree)]="filteringExpressionsTree"
      [pagingMode]="
        model.PagerSettings.AllowPaging !== 3 &&
        model.PagerSettings.AllowPaging !== 4 &&
        model.ItemsSourceAsPagedCollection
          ? 1
          : 0
      "
      class="igxGrid"
    >
      <!-- Toolbar area for row adding -->
      <igx-grid-toolbar *ngIf="shouldAddNewRow">
        <igx-grid-toolbar-actions>
          <button
            igxButton="outlined"
            (click)="beginAddRow()"
            [disabled]="disableAddNewRow"
          >
            Add row
          </button>
        </igx-grid-toolbar-actions>
      </igx-grid-toolbar>

      <!-- Column layout section -->
      <ng-container *ngIf="hasColumnLayout">
        <ng-template igxGridDetail let-dataItem let-index>
          <div style="width: 100%; height: 100%">
            <wm-xam-grid
              #gridColumnLayout
              class="hierarchical-grid"
              [model]="populateModel(dataItem.data, index)"
              [virtualHeight]="null"
              [data]="dataItem.data[columnLayoutItems.key]"
              (selectedRowsCollectionChanged)="
                internalColumnLayoutRowSelectionHandler($event.sender, $event.e)
              "
            >
            </wm-xam-grid>
          </div>
        </ng-template>
      </ng-container>
      <!-- End layout section -->

      <!-- Column rendering -->
      <ng-container *ngFor="let col of columnsToRender">
        <!-- Top level default column -->
        <igx-column
          *ngIf="!col.IsGroupColumn"
          #column
          [autosizeHeader]="col.AutoSizeHeader"
          [cellStyles]="
            col.HorizontalContentAlignment
              | alignmentMap
                : col.VerticalContentAlignment
                : col.CellStyle
                : col.ConditionalFormatCollection
                : this
                : this.isCellChanged
          "
          [headerStyles]="
            col.HorizontalContentAlignment
              | alignmentMap
                : col.VerticalContentAlignment
                : col.HeaderStyle
                : null
                : null
                : null
          "
          [hasSummary]="model.FooterVisibility"
          [summaries]="col.footerOperand"
          [filters]="col.DataType === 'string' ? xamTextFilters : undefined"
          [dataType]="col.DataType"
          [hasSummary]="hasSummary(col)"
          [minWidth]="col.MinimumWidth"
          [maxWidth]="col.MaximumWidth"
          [width]="col.CalculatedWidth"
          [cellTemplate]="
            col.ItemTemplate?.templateRef ||
            (col.TextWrapping ? customCell : null) ||
            (col.DataType === 'boolean' ? customBooleanTemplate : null)
          "
          [cellEditorTemplate]="col.EditorTemplate?.templateRef"
          [filterCellTemplate]="col.FilterTemplate?.templateRef"
          [headerTemplate]="
            col.HeaderTemplate?.templateRef ||
            (col.HeaderStyle !== null ||
            col.HeaderTextHorizontalAlignment !== null
              ? customHeader
              : null)
          "
          [header]="col.HeaderText || col.Key"
          [field]="'data.' + col.Key"
          [editable]="isEditable(col)"
          [hidden]="!col.Visibility"
          [filterable]="getFilterable(col)"
          [sortable]="col.IsSortable && model.SortingSettings.AllowSorting"
          [sortStrategy]="getStrategy(col)"
          [groupable]="col.IsGroupable"
          [resizable]="
            col.IsResizable && model.ColumnResizingSettings.AllowColumnResizing
          "
          [movable]="
            col.IsMovable && model.ColumnMovingSettings.AllowColumnMoving
          "
          [pinned]="col.IsFixed !== 0"
          [disableHiding]="col.IsHideable"
          [disablePinning]="
            !col.IsFixable && model.FixedColumnSettings.AllowFixedColumns
          "
          [formatter]="
            col.FormatString
              | xamFormatString: col.ValueConverter:col:col.DataType
          "
        >
          <ng-template
            igxCell
            let-context="cell.row.data.data"
            *ngIf="col?.ItemTemplate?.TemplateComponentConstructor"
            #customItemTemplate
          >
            <ng-container
              *ngComponentOutlet="
                col.ItemTemplate.TemplateComponentConstructor;
                injector: context
                  | xamTemplateToInjector: col.ItemTemplate?.declaringContext
              "
            >
            </ng-container>
          </ng-template>

          <ng-template
            igxCellEditor
            let-context="cell.row.data.data"
            *ngIf="col?.EditorTemplate?.TemplateComponentConstructor"
            #customEditorTemplate
          >
            <ng-container
              *ngComponentOutlet="
                col.EditorTemplate.TemplateComponentConstructor;
                injector: context
                  | xamTemplateToInjector: col.EditorTemplate?.declaringContext
              "
            >
            </ng-container>
          </ng-template>

          <ng-template #customHeader>
            <!-- prettier-ignore -->
            <div
              [ngStyle]="
                col.HeaderStyle | styleInfo: col.HeaderTextHorizontalAlignment
              ">{{ col.HeaderText || col.Key }}</div>
          </ng-template>

          <ng-template #customCell let-value>
            <!-- prettier-ignore -->
            <div [ngStyle]="col.TextWrapping | textWrapping">{{ column.formatter ? column.formatter(value) : value }}</div>
          </ng-template>

          <ng-template *ngIf="col.TemplateInHeaderStyle" igxHeader>
            <ng-container
              *ngComponentOutlet="
                col.TemplateInHeaderStyle.controlType;
                injector: col.TemplateInHeaderStyle.controlModel
                  | xamGridToInjector
              "
            >
            </ng-container>
          </ng-template>
        </igx-column>
        <!-- End top level default column -->

        <!-- Top level column group -->
        <igx-column-group
          *ngIf="col.IsGroupColumn"
          [headerGroupStyles]="
            col.HorizontalContentAlignment
              | alignmentMap
                : col.VerticalContentAlignment
                : col.HeaderStyle
                : null
                : null
                : null
          "
          [minWidth]="col.MinimumWidth"
          [maxWidth]="col.MaximumWidth"
          [width]="col.CalculatedWidth"
          [header]="col.HeaderText || col.Key"
          [field]="'data.' + col.Key"
          [resizable]="
            col.IsResizable && model.ColumnResizingSettings.AllowColumnResizing
          "
          [movable]="
            col.IsMovable && model.ColumnMovingSettings.AllowColumnMoving
          "
          [pinned]="col.IsFixed !== 0"
          [hidden]="!col.Visibility"
          [disableHiding]="col.IsHideable"
          [disablePinning]="
            !col.IsFixable && model.FixedColumnSettings.AllowFixedColumns
          "
        >
          <!-- LOOP START -->
          <ng-template #defaultColumn let-col>
            <igx-column
              #column
              [autosizeHeader]="col.AutoSizeHeader"
              [cellStyles]="
                col.HorizontalContentAlignment
                  | alignmentMap
                    : col.VerticalContentAlignment
                    : col.CellStyle
                    : col.ConditionalFormatCollection
                    : this
                    : this.isCellChanged
              "
              [headerStyles]="
                col.HorizontalContentAlignment
                  | alignmentMap
                    : col.VerticalContentAlignment
                    : col.HeaderStyle
                    : null
                    : null
                    : null
              "
              [hasSummary]="model.FooterVisibility"
              [summaries]="col.footerOperand"
              [filters]="col.DataType === 'string' ? xamTextFilters : undefined"
              [dataType]="col.DataType"
              [hasSummary]="col.HasSummary"
              [minWidth]="col.MinimumWidth"
              [maxWidth]="col.MaximumWidth"
              [width]="col.CalculatedWidth"
              [cellTemplate]="
                col.ItemTemplate?.templateRef ||
                (col.TextWrapping ? customCell : null) ||
                (col.DataType === 'boolean' ? customBooleanTemplate : null)
              "
              [cellEditorTemplate]="col.EditorTemplate?.templateRef"
              [filterCellTemplate]="col.FilterTemplate?.templateRef"
              [headerTemplate]="
                col.HeaderTemplate?.templateRef ||
                col.HeaderStyle !== null ||
                col.HeaderTextHorizontalAlignment !== null
                  ? customHeader
                  : null
              "
              [header]="col.HeaderText || col.Key"
              [field]="'data.' + col.Key"
              [editable]="!col.ItemTemplate?.templateRef && col.Editable"
              [hidden]="!col.Visibility"
              [filterable]="getFilterable(col)"
              [sortable]="col.IsSortable && model.SortingSettings.AllowSorting"
              [sortStrategy]="getStrategy(col)"
              [groupable]="col.IsGroupable"
              [resizable]="
                col.IsResizable &&
                model.ColumnResizingSettings.AllowColumnResizing
              "
              [movable]="
                col.IsMovable && model.ColumnMovingSettings.AllowColumnMoving
              "
              [pinned]="col.IsFixed !== 0"
              [disableHiding]="col.IsHideable"
              [disablePinning]="
                !col.IsFixable && model.FixedColumnSettings.AllowFixedColumns
              "
              [formatter]="
                col.FormatString
                  | xamFormatString: col.ValueConverter:col:col.DataType
              "
            >
              <ng-template
                igxCell
                let-context="cell.row.data.data"
                *ngIf="col?.ItemTemplate?.TemplateComponentConstructor"
                #customItemTemplate
              >
                <ng-container
                  *ngComponentOutlet="
                    col.ItemTemplate.TemplateComponentConstructor;
                    injector: context
                      | xamTemplateToInjector
                        : col.ItemTemplate?.declaringContext
                  "
                >
                </ng-container>
              </ng-template>

              <ng-template
                igxCellEditor
                let-context="cell.row.data.data"
                *ngIf="col?.EditorTemplate?.TemplateComponentConstructor"
                #customEditorTemplate
              >
                <ng-container
                  *ngComponentOutlet="
                    col.EditorTemplate.TemplateComponentConstructor;
                    injector: context
                      | xamTemplateToInjector
                        : col.EditorTemplate?.declaringContext
                  "
                >
                </ng-container>
              </ng-template>

              <ng-template #customHeader>
                <!-- prettier-ignore -->
                <div
                  [ngStyle]="
                    col.HeaderStyle
                      | styleInfo: col.HeaderTextHorizontalAlignment
                  ">{{ col.HeaderText || col.Key }}</div>
              </ng-template>

              <ng-template #customCell let-value>
                <!-- prettier-ignore -->
                <div [ngStyle]="col.TextWrapping | textWrapping">{{ column.formatter ? column.formatter(value) : value }}</div>
              </ng-template>
            </igx-column>
          </ng-template>

          <ng-template #groupColumn let-col>
            <igx-column-group
              *ngIf="col.IsGroupColumn"
              [autosizeHeader]="col.AutoSizeHeader"
              [headerGroupStyles]="
                col.HorizontalContentAlignment
                  | alignmentMap
                    : col.VerticalContentAlignment
                    : col.HeaderStyle
                    : null
                    : null
                    : null
              "
              [minWidth]="col.MinimumWidth"
              [maxWidth]="col.MaximumWidth"
              [width]="col.CalculatedWidth"
              [header]="col.HeaderText || col.Key"
              [field]="'data.' + col.Key"
              [resizable]="
                col.IsResizable &&
                model.ColumnResizingSettings.AllowColumnResizing
              "
              [movable]="
                col.IsMovable && model.ColumnMovingSettings.AllowColumnMoving
              "
              [pinned]="col.IsFixed !== 0"
              [hidden]="!col.Visibility"
              [disableHiding]="col.IsHideable"
              [disablePinning]="
                !col.IsFixable && model.FixedColumnSettings.AllowFixedColumns
              "
            >
              <ng-template #defaultColumn let-col>
                <igx-column
                  #column
                  [cellStyles]="
                    col.HorizontalContentAlignment
                      | alignmentMap
                        : col.VerticalContentAlignment
                        : col.CellStyle
                        : col.ConditionalFormatCollection
                        : this
                        : this.isCellChanged
                  "
                  [headerStyles]="
                    col.HorizontalContentAlignment
                      | alignmentMap
                        : col.VerticalContentAlignment
                        : col.HeaderStyle
                        : null
                        : null
                        : null
                  "
                  [hasSummary]="model.FooterVisibility"
                  [summaries]="col.footerOperand"
                  [filters]="
                    col.DataType === 'string' ? xamTextFilters : undefined
                  "
                  [dataType]="col.DataType"
                  [hasSummary]="col.HasSummary"
                  [minWidth]="col.MinimumWidth"
                  [maxWidth]="col.MaximumWidth"
                  [width]="col.CalculatedWidth"
                  [cellTemplate]="
                    col.ItemTemplate?.templateRef ||
                    (col.TextWrapping ? customCell : null) ||
                    (col.DataType === 'boolean' ? customBooleanTemplate : null)
                  "
                  [cellEditorTemplate]="col.EditorTemplate?.templateRef"
                  [filterCellTemplate]="col.FilterTemplate?.templateRef"
                  [headerTemplate]="
                    col.HeaderTemplate?.templateRef ||
                    col.HeaderStyle !== null ||
                    col.HeaderTextHorizontalAlignment !== null
                      ? customHeader
                      : null
                  "
                  [header]="col.HeaderText || col.Key"
                  [field]="'data.' + col.Key"
                  [editable]="!col.ItemTemplate?.templateRef && col.Editable"
                  [hidden]="!col.Visibility"
                  [filterable]="getFilterable(col)"
                  [sortable]="
                    col.IsSortable && model.SortingSettings.AllowSorting
                  "
                  [sortStrategy]="getStrategy(col)"
                  [groupable]="col.IsGroupable"
                  [resizable]="
                    col.IsResizable &&
                    model.ColumnResizingSettings.AllowColumnResizing
                  "
                  [movable]="
                    col.IsMovable &&
                    model.ColumnMovingSettings.AllowColumnMoving
                  "
                  [pinned]="col.IsFixed !== 0"
                  [disableHiding]="col.IsHideable"
                  [disablePinning]="
                    !col.IsFixable &&
                    model.FixedColumnSettings.AllowFixedColumns
                  "
                  [formatter]="
                    col.FormatString
                      | xamFormatString: col.ValueConverter:col:col.DataType
                  "
                >
                  <ng-template
                    igxCell
                    let-context="cell.row.data.data"
                    *ngIf="col?.ItemTemplate?.TemplateComponentConstructor"
                    #customItemTemplate
                  >
                    <ng-container
                      *ngComponentOutlet="
                        col.ItemTemplate.TemplateComponentConstructor;
                        injector: context
                          | xamTemplateToInjector
                            : col.ItemTemplate?.declaringContext
                      "
                    >
                    </ng-container>
                  </ng-template>

                  <ng-template
                    igxCellEditor
                    let-context="cell.row.data.data"
                    *ngIf="col?.EditorTemplate?.TemplateComponentConstructor"
                    #customEditorTemplate
                  >
                    <ng-container
                      *ngComponentOutlet="
                        col.EditorTemplate.TemplateComponentConstructor;
                        injector: context
                          | xamTemplateToInjector
                            : col.EditorTemplate?.declaringContext
                      "
                    >
                    </ng-container>
                  </ng-template>

                  <ng-template #customHeader>
                    <!-- prettier-ignore -->
                    <div
                      [ngStyle]="
                        col.HeaderStyle
                          | styleInfo: col.HeaderTextHorizontalAlignment
                      ">{{ col.HeaderText || col.Key }}</div>
                  </ng-template>

                  <ng-template #customCell let-value>
                    <!-- prettier-ignore -->
                    <div [ngStyle]="col.TextWrapping | textWrapping">{{ column.formatter ? column.formatter(value) : value }}</div>
                  </ng-template>
                </igx-column>
              </ng-template>

              <ng-template #groupColumn let-col>
                <igx-column-group
                  *ngIf="col.IsGroupColumn"
                  [headerGroupStyles]="
                    col.HorizontalContentAlignment
                      | alignmentMap
                        : col.VerticalContentAlignment
                        : col.HeaderStyle
                        : null
                        : null
                        : null
                  "
                  [minWidth]="col.MinimumWidth"
                  [maxWidth]="col.MaximumWidth"
                  [width]="col.CalculatedWidth"
                  [header]="col.HeaderText || col.Key"
                  [field]="'data.' + col.Key"
                  [resizable]="
                    col.IsResizable &&
                    model.ColumnResizingSettings.AllowColumnResizing
                  "
                  [movable]="
                    col.IsMovable &&
                    model.ColumnMovingSettings.AllowColumnMoving
                  "
                  [pinned]="col.IsFixed !== 0"
                  [hidden]="!col.Visibility"
                  [disableHiding]="col.IsHideable"
                  [disablePinning]="
                    !col.IsFixable &&
                    model.FixedColumnSettings.AllowFixedColumns
                  "
                >
                  <ng-template #defaultColumn let-col>
                    <igx-column
                      #column
                      [cellStyles]="
                        col.HorizontalContentAlignment
                          | alignmentMap
                            : col.VerticalContentAlignment
                            : col.CellStyle
                            : col.ConditionalFormatCollection
                            : this
                            : this.isCellChanged
                      "
                      [headerStyles]="
                        col.HorizontalContentAlignment
                          | alignmentMap
                            : col.VerticalContentAlignment
                            : col.HeaderStyle
                            : null
                            : null
                            : null
                      "
                      [hasSummary]="model.FooterVisibility"
                      [summaries]="col.footerOperand"
                      [filters]="
                        col.DataType === 'string' ? xamTextFilters : undefined
                      "
                      [dataType]="col.DataType"
                      [hasSummary]="col.HasSummary"
                      [minWidth]="col.MinimumWidth"
                      [maxWidth]="col.MaximumWidth"
                      [width]="col.CalculatedWidth"
                      [cellTemplate]="
                        col.ItemTemplate?.templateRef ||
                        (col.TextWrapping ? customCell : null) ||
                        (col.DataType === 'boolean'
                          ? customBooleanTemplate
                          : null)
                      "
                      [cellEditorTemplate]="col.EditorTemplate?.templateRef"
                      [filterCellTemplate]="col.FilterTemplate?.templateRef"
                      [headerTemplate]="
                        col.HeaderTemplate?.templateRef ||
                        col.HeaderStyle !== null ||
                        col.HeaderTextHorizontalAlignment !== null
                          ? customHeader
                          : null
                      "
                      [header]="col.HeaderText || col.Key"
                      [field]="'data.' + col.Key"
                      [editable]="
                        !col.ItemTemplate?.templateRef && col.Editable
                      "
                      [hidden]="!col.Visibility"
                      [filterable]="getFilterable(col)"
                      [sortable]="
                        col.IsSortable && model.SortingSettings.AllowSorting
                      "
                      [sortStrategy]="getStrategy(col)"
                      [groupable]="col.IsGroupable"
                      [resizable]="
                        col.IsResizable &&
                        model.ColumnResizingSettings.AllowColumnResizing
                      "
                      [movable]="
                        col.IsMovable &&
                        model.ColumnMovingSettings.AllowColumnMoving
                      "
                      [pinned]="col.IsFixed !== 0"
                      [disableHiding]="col.IsHideable"
                      [disablePinning]="
                        !col.IsFixable &&
                        model.FixedColumnSettings.AllowFixedColumns
                      "
                      [formatter]="
                        col.FormatString
                          | xamFormatString: col.ValueConverter:col:col.DataType
                      "
                    >
                      <ng-template
                        igxCell
                        let-context="cell.row.data.data"
                        *ngIf="col?.ItemTemplate?.TemplateComponentConstructor"
                        #customItemTemplate
                      >
                        <ng-container
                          *ngComponentOutlet="
                            col.ItemTemplate.TemplateComponentConstructor;
                            injector: context
                              | xamTemplateToInjector
                                : col.ItemTemplate?.declaringContext
                          "
                        >
                        </ng-container>
                      </ng-template>

                      <ng-template
                        igxCellEditor
                        let-context="cell.row.data.data"
                        *ngIf="
                          col?.EditorTemplate?.TemplateComponentConstructor
                        "
                        #customEditorTemplate
                      >
                        <ng-container
                          *ngComponentOutlet="
                            col.EditorTemplate.TemplateComponentConstructor;
                            injector: context
                              | xamTemplateToInjector
                                : col.EditorTemplate?.declaringContext
                          "
                        >
                        </ng-container>
                      </ng-template>

                      <ng-template #customHeader>
                        <!-- prettier-ignore -->
                        <div
                          [ngStyle]="
                            col.HeaderStyle
                              | styleInfo: col.HeaderTextHorizontalAlignment
                          ">{{ col.HeaderText || col.Key }}</div>
                      </ng-template>

                      <ng-template #customCell let-value>
                        <!-- prettier-ignore -->
                        <div [ngStyle]="col.TextWrapping | textWrapping">{{
                            column.formatter ? column.formatter(value) : value
                          }}</div>
                      </ng-template>
                    </igx-column>
                  </ng-template>

                  <ng-template #groupColumn let-col>
                    <igx-column-group
                      *ngIf="col.IsGroupColumn"
                      [headerGroupStyles]="
                        col.HorizontalContentAlignment
                          | alignmentMap
                            : col.VerticalContentAlignment
                            : col.HeaderStyle
                            : null
                            : null
                            : null
                      "
                      [minWidth]="col.MinimumWidth"
                      [maxWidth]="col.MaximumWidth"
                      [width]="col.CalculatedWidth"
                      [header]="col.HeaderText || col.Key"
                      [field]="'data.' + col.Key"
                      [resizable]="
                        col.IsResizable &&
                        model.ColumnResizingSettings.AllowColumnResizing
                      "
                      [movable]="
                        col.IsMovable &&
                        model.ColumnMovingSettings.AllowColumnMoving
                      "
                      [pinned]="col.IsFixed !== 0"
                      [hidden]="!col.Visibility"
                      [disableHiding]="col.IsHideable"
                      [disablePinning]="
                        !col.IsFixable &&
                        model.FixedColumnSettings.AllowFixedColumns
                      "
                    >
                      <ng-template #defaultColumn let-col>
                        <igx-column
                          #column
                          [cellStyles]="
                            col.HorizontalContentAlignment
                              | alignmentMap
                                : col.VerticalContentAlignment
                                : col.CellStyle
                                : col.ConditionalFormatCollection
                                : this
                                : this.isCellChanged
                          "
                          [headerStyles]="
                            col.HorizontalContentAlignment
                              | alignmentMap
                                : col.VerticalContentAlignment
                                : col.HeaderStyle
                                : null
                                : null
                                : null
                          "
                          [hasSummary]="model.FooterVisibility"
                          [summaries]="col.footerOperand"
                          [filters]="
                            col.DataType === 'string'
                              ? xamTextFilters
                              : undefined
                          "
                          [dataType]="col.DataType"
                          [hasSummary]="col.HasSummary"
                          [minWidth]="col.MinimumWidth"
                          [maxWidth]="col.MaximumWidth"
                          [width]="col.CalculatedWidth"
                          [cellTemplate]="
                            col.ItemTemplate?.templateRef ||
                            (col.TextWrapping ? customCell : null) ||
                            (col.DataType === 'boolean'
                              ? customBooleanTemplate
                              : null)
                          "
                          [cellEditorTemplate]="col.EditorTemplate?.templateRef"
                          [filterCellTemplate]="col.FilterTemplate?.templateRef"
                          [headerTemplate]="
                            col.HeaderTemplate?.templateRef ||
                            col.HeaderStyle !== null ||
                            col.HeaderTextHorizontalAlignment !== null
                              ? customHeader
                              : null
                          "
                          [header]="col.HeaderText || col.Key"
                          [field]="'data.' + col.Key"
                          [editable]="
                            !col.ItemTemplate?.templateRef && col.Editable
                          "
                          [hidden]="!col.Visibility"
                          [filterable]="getFilterable(col)"
                          [sortable]="
                            col.IsSortable && model.SortingSettings.AllowSorting
                          "
                          [sortStrategy]="getStrategy(col)"
                          [groupable]="col.IsGroupable"
                          [resizable]="
                            col.IsResizable &&
                            model.ColumnResizingSettings.AllowColumnResizing
                          "
                          [movable]="
                            col.IsMovable &&
                            model.ColumnMovingSettings.AllowColumnMoving
                          "
                          [pinned]="col.IsFixed !== 0"
                          [disableHiding]="col.IsHideable"
                          [disablePinning]="
                            !col.IsFixable &&
                            model.FixedColumnSettings.AllowFixedColumns
                          "
                          [formatter]="
                            col.FormatString
                              | xamFormatString
                                : col.ValueConverter
                                : col
                                : col.DataType
                          "
                        >
                          <ng-template
                            igxCell
                            let-context="cell.row.data.data"
                            *ngIf="
                              col?.ItemTemplate?.TemplateComponentConstructor
                            "
                            #customItemTemplate
                          >
                            <ng-container
                              *ngComponentOutlet="
                                col.ItemTemplate.TemplateComponentConstructor;
                                injector: context
                                  | xamTemplateToInjector
                                    : col.ItemTemplate?.declaringContext
                              "
                            >
                            </ng-container>
                          </ng-template>

                          <ng-template
                            igxCellEditor
                            let-context="cell.row.data.data"
                            *ngIf="
                              col?.EditorTemplate?.TemplateComponentConstructor
                            "
                            #customEditorTemplate
                          >
                            <ng-container
                              *ngComponentOutlet="
                                col.EditorTemplate.TemplateComponentConstructor;
                                injector: context
                                  | xamTemplateToInjector
                                    : col.EditorTemplate?.declaringContext
                              "
                            >
                            </ng-container>
                          </ng-template>

                          <ng-template #customHeader>
                            <!-- prettier-ignore -->
                            <div
                              [ngStyle]="
                                col.HeaderStyle
                                  | styleInfo: col.HeaderTextHorizontalAlignment
                              ">{{ col.HeaderText || col.Key }}</div>
                          </ng-template>

                          <ng-template #customCell let-value>
                            <!-- prettier-ignore -->
                            <div [ngStyle]="col.TextWrapping | textWrapping">{{
                                column.formatter
                                  ? column.formatter(value)
                                  : value
                              }}</div>
                          </ng-template>
                        </igx-column>
                      </ng-template>

                      <ng-template #groupColumn let-col>
                        <igx-column-group
                          *ngIf="col.IsGroupColumn"
                          [headerGroupStyles]="
                            col.HorizontalContentAlignment
                              | alignmentMap
                                : col.VerticalContentAlignment
                                : col.HeaderStyle
                                : null
                                : null
                                : null
                          "
                          [minWidth]="col.MinimumWidth"
                          [maxWidth]="col.MaximumWidth"
                          [width]="col.CalculatedWidth"
                          [header]="col.HeaderText || col.Key"
                          [field]="'data.' + col.Key"
                          [resizable]="
                            col.IsResizable &&
                            model.ColumnResizingSettings.AllowColumnResizing
                          "
                          [movable]="
                            col.IsMovable &&
                            model.ColumnMovingSettings.AllowColumnMoving
                          "
                          [pinned]="col.IsFixed !== 0"
                          [hidden]="!col.Visibility"
                          [disableHiding]="col.IsHideable"
                          [disablePinning]="
                            !col.IsFixable &&
                            model.FixedColumnSettings.AllowFixedColumns
                          "
                        >
                          <ng-template #defaultColumn let-col>
                            <igx-column
                              #column
                              [cellStyles]="
                                col.HorizontalContentAlignment
                                  | alignmentMap
                                    : col.VerticalContentAlignment
                                    : col.CellStyle
                                    : col.ConditionalFormatCollection
                                    : this
                                    : this.isCellChanged
                              "
                              [headerStyles]="
                                col.HorizontalContentAlignment
                                  | alignmentMap
                                    : col.VerticalContentAlignment
                                    : col.HeaderStyle
                                    : null
                                    : null
                                    : null
                              "
                              [hasSummary]="model.FooterVisibility"
                              [summaries]="col.footerOperand"
                              [filters]="
                                col.DataType === 'string'
                                  ? xamTextFilters
                                  : undefined
                              "
                              [dataType]="col.DataType"
                              [hasSummary]="col.HasSummary"
                              [minWidth]="col.MinimumWidth"
                              [maxWidth]="col.MaximumWidth"
                              [width]="col.CalculatedWidth"
                              [cellTemplate]="
                                col.ItemTemplate?.templateRef ||
                                (col.TextWrapping ? customCell : null) ||
                                (col.DataType === 'boolean'
                                  ? customBooleanTemplate
                                  : null)
                              "
                              [cellEditorTemplate]="
                                col.EditorTemplate?.templateRef
                              "
                              [filterCellTemplate]="
                                col.FilterTemplate?.templateRef
                              "
                              [headerTemplate]="
                                col.HeaderTemplate?.templateRef ||
                                col.HeaderStyle !== null ||
                                col.HeaderTextHorizontalAlignment !== null
                                  ? customHeader
                                  : null
                              "
                              [header]="col.HeaderText || col.Key"
                              [field]="'data.' + col.Key"
                              [editable]="
                                !col.ItemTemplate?.templateRef && col.Editable
                              "
                              [hidden]="!col.Visibility"
                              [filterable]="getFilterable(col)"
                              [sortable]="
                                col.IsSortable &&
                                model.SortingSettings.AllowSorting
                              "
                              [sortStrategy]="getStrategy(col)"
                              [groupable]="col.IsGroupable"
                              [resizable]="
                                col.IsResizable &&
                                model.ColumnResizingSettings.AllowColumnResizing
                              "
                              [movable]="
                                col.IsMovable &&
                                model.ColumnMovingSettings.AllowColumnMoving
                              "
                              [pinned]="col.IsFixed !== 0"
                              [disableHiding]="col.IsHideable"
                              [disablePinning]="
                                !col.IsFixable &&
                                model.FixedColumnSettings.AllowFixedColumns
                              "
                              [formatter]="
                                col.FormatString
                                  | xamFormatString
                                    : col.ValueConverter
                                    : col
                                    : col.DataType
                              "
                            >
                              <ng-template
                                igxCell
                                let-context="cell.row.data.data"
                                *ngIf="
                                  col?.ItemTemplate
                                    ?.TemplateComponentConstructor
                                "
                                #customItemTemplate
                              >
                                <ng-container
                                  *ngComponentOutlet="
                                    col.ItemTemplate
                                      .TemplateComponentConstructor;
                                    injector: context
                                      | xamTemplateToInjector
                                        : col.ItemTemplate?.declaringContext
                                  "
                                >
                                </ng-container>
                              </ng-template>

                              <ng-template
                                igxCellEditor
                                let-context="cell.row.data.data"
                                *ngIf="
                                  col?.EditorTemplate
                                    ?.TemplateComponentConstructor
                                "
                                #customEditorTemplate
                              >
                                <ng-container
                                  *ngComponentOutlet="
                                    col.EditorTemplate
                                      .TemplateComponentConstructor;
                                    injector: context
                                      | xamTemplateToInjector
                                        : col.EditorTemplate?.declaringContext
                                  "
                                >
                                </ng-container>
                              </ng-template>

                              <ng-template #customHeader>
                                <!-- prettier-ignore -->
                                <div
                                  [ngStyle]="
                                    col.HeaderStyle
                                      | styleInfo
                                        : col.HeaderTextHorizontalAlignment
                                  ">{{ col.HeaderText || col.Key }}</div>
                              </ng-template>

                              <ng-template #customCell let-value>
                                <!-- prettier-ignore -->
                                <div
                                  [ngStyle]="col.TextWrapping | textWrapping"
                                >{{
                                    column.formatter
                                      ? column.formatter(value)
                                      : value
                                  }}</div>
                              </ng-template>
                            </igx-column>
                          </ng-template>

                          <ng-template #groupColumn let-col>
                            <igx-column-group
                              *ngIf="col.IsGroupColumn"
                              [headerGroupStyles]="
                                col.HorizontalContentAlignment
                                  | alignmentMap
                                    : col.VerticalContentAlignment
                                    : col.HeaderStyle
                                    : null
                                    : null
                                    : null
                              "
                              [minWidth]="col.MinimumWidth"
                              [maxWidth]="col.MaximumWidth"
                              [width]="col.CalculatedWidth"
                              [header]="col.HeaderText || col.Key"
                              [field]="'data.' + col.Key"
                              [resizable]="
                                col.IsResizable &&
                                model.ColumnResizingSettings.AllowColumnResizing
                              "
                              [movable]="
                                col.IsMovable &&
                                model.ColumnMovingSettings.AllowColumnMoving
                              "
                              [pinned]="col.IsFixed !== 0"
                              [hidden]="!col.Visibility"
                              [disableHiding]="col.IsHideable"
                              [disablePinning]="
                                !col.IsFixable &&
                                model.FixedColumnSettings.AllowFixedColumns
                              "
                            >
                              <ng-template #defaultColumn let-col>
                                <igx-column
                                  #column
                                  [autosizeHeader]="col.AutoSizeHeader"
                                  [cellStyles]="
                                    col.HorizontalContentAlignment
                                      | alignmentMap
                                        : col.VerticalContentAlignment
                                        : col.CellStyle
                                        : col.ConditionalFormatCollection
                                        : this
                                        : this.isCellChanged
                                  "
                                  [headerStyles]="
                                    col.HorizontalContentAlignment
                                      | alignmentMap
                                        : col.VerticalContentAlignment
                                        : col.HeaderStyle
                                        : null
                                        : null
                                        : null
                                  "
                                  [hasSummary]="model.FooterVisibility"
                                  [summaries]="col.footerOperand"
                                  [filters]="
                                    col.DataType === 'string'
                                      ? xamTextFilters
                                      : undefined
                                  "
                                  [dataType]="col.DataType"
                                  [hasSummary]="col.HasSummary"
                                  [minWidth]="col.MinimumWidth"
                                  [maxWidth]="col.MaximumWidth"
                                  [width]="col.CalculatedWidth"
                                  [cellTemplate]="
                                    col.ItemTemplate?.templateRef ||
                                    (col.TextWrapping ? customCell : null) ||
                                    (col.DataType === 'boolean'
                                      ? customBooleanTemplate
                                      : null)
                                  "
                                  [cellEditorTemplate]="
                                    col.EditorTemplate?.templateRef
                                  "
                                  [filterCellTemplate]="
                                    col.FilterTemplate?.templateRef
                                  "
                                  [headerTemplate]="
                                    col.HeaderTemplate?.templateRef ||
                                    col.HeaderStyle !== null ||
                                    col.HeaderTextHorizontalAlignment !== null
                                      ? customHeader
                                      : null
                                  "
                                  [header]="col.HeaderText || col.Key"
                                  [field]="'data.' + col.Key"
                                  [editable]="
                                    !col.ItemTemplate?.templateRef &&
                                    col.Editable
                                  "
                                  [hidden]="!col.Visibility"
                                  [filterable]="getFilterable(col)"
                                  [sortable]="
                                    col.IsSortable &&
                                    model.SortingSettings.AllowSorting
                                  "
                                  [sortStrategy]="getStrategy(col)"
                                  [groupable]="col.IsGroupable"
                                  [resizable]="
                                    col.IsResizable &&
                                    model.ColumnResizingSettings
                                      .AllowColumnResizing
                                  "
                                  [movable]="
                                    col.IsMovable &&
                                    model.ColumnMovingSettings.AllowColumnMoving
                                  "
                                  [pinned]="col.IsFixed !== 0"
                                  [disableHiding]="col.IsHideable"
                                  [disablePinning]="
                                    !col.IsFixable &&
                                    model.FixedColumnSettings.AllowFixedColumns
                                  "
                                  [formatter]="
                                    col.FormatString
                                      | xamFormatString
                                        : col.ValueConverter
                                        : col
                                        : col.DataType
                                  "
                                >
                                  <ng-template
                                    igxCell
                                    let-context="cell.row.data.data"
                                    *ngIf="
                                      col?.ItemTemplate
                                        ?.TemplateComponentConstructor
                                    "
                                    #customItemTemplate
                                  >
                                    <ng-container
                                      *ngComponentOutlet="
                                        col.ItemTemplate
                                          .TemplateComponentConstructor;
                                        injector: context
                                          | xamTemplateToInjector
                                            : col.ItemTemplate?.declaringContext
                                      "
                                    >
                                    </ng-container>
                                  </ng-template>

                                  <ng-template
                                    igxCellEditor
                                    let-context="cell.row.data.data"
                                    *ngIf="
                                      col?.EditorTemplate
                                        ?.TemplateComponentConstructor
                                    "
                                    #customEditorTemplate
                                  >
                                    <ng-container
                                      *ngComponentOutlet="
                                        col.EditorTemplate
                                          .TemplateComponentConstructor;
                                        injector: context
                                          | xamTemplateToInjector
                                            : col.EditorTemplate
                                                ?.declaringContext
                                      "
                                    >
                                    </ng-container>
                                  </ng-template>

                                  <ng-template #customHeader>
                                    <!-- prettier-ignore -->
                                    <div
                                      [ngStyle]="
                                        col.HeaderStyle
                                          | styleInfo
                                            : col.HeaderTextHorizontalAlignment
                                      ">{{ col.HeaderText || col.Key }}</div>
                                  </ng-template>

                                  <ng-template #customCell let-value>
                                    <!-- prettier-ignore -->
                                    <div
                                      [ngStyle]="
                                        col.TextWrapping | textWrapping
                                      ">{{
                                        column.formatter
                                          ? column.formatter(value)
                                          : value
                                      }}</div>
                                  </ng-template>
                                </igx-column>
                              </ng-template>

                              <ng-template #groupColumn let-col>
                                <igx-column-group
                                  *ngIf="col.IsGroupColumn"
                                  [headerGroupStyles]="
                                    col.HorizontalContentAlignment
                                      | alignmentMap
                                        : col.VerticalContentAlignment
                                        : col.HeaderStyle
                                        : null
                                        : null
                                        : null
                                  "
                                  [minWidth]="col.MinimumWidth"
                                  [maxWidth]="col.MaximumWidth"
                                  [width]="col.CalculatedWidth"
                                  [header]="col.HeaderText || col.Key"
                                  [field]="'data.' + col.Key"
                                  [resizable]="
                                    col.IsResizable &&
                                    model.ColumnResizingSettings
                                      .AllowColumnResizing
                                  "
                                  [movable]="
                                    col.IsMovable &&
                                    model.ColumnMovingSettings.AllowColumnMoving
                                  "
                                  [pinned]="col.IsFixed !== 0"
                                  [hidden]="!col.Visibility"
                                  [disableHiding]="col.IsHideable"
                                  [disablePinning]="
                                    !col.IsFixable &&
                                    model.FixedColumnSettings.AllowFixedColumns
                                  "
                                >
                                  <ng-container
                                    *ngFor="let child of getColumnGroup(col)"
                                  >
                                    <ng-container
                                      *ngTemplateOutlet="
                                        child.IsGroupColumn
                                          ? groupColumn
                                          : defaultColumn;
                                        context: { $implicit: child }
                                      "
                                    ></ng-container>
                                  </ng-container>
                                </igx-column-group>
                              </ng-template>

                              <ng-container
                                *ngFor="let child of getColumnGroup(col)"
                              >
                                <ng-container
                                  *ngTemplateOutlet="
                                    child.IsGroupColumn
                                      ? groupColumn
                                      : defaultColumn;
                                    context: { $implicit: child }
                                  "
                                ></ng-container>
                              </ng-container>
                            </igx-column-group>
                          </ng-template>

                          <ng-container
                            *ngFor="let child of getColumnGroup(col)"
                          >
                            <ng-container
                              *ngTemplateOutlet="
                                child.IsGroupColumn
                                  ? groupColumn
                                  : defaultColumn;
                                context: { $implicit: child }
                              "
                            ></ng-container>
                          </ng-container>
                        </igx-column-group>
                      </ng-template>

                      <ng-container *ngFor="let child of getColumnGroup(col)">
                        <ng-container
                          *ngTemplateOutlet="
                            child.IsGroupColumn ? groupColumn : defaultColumn;
                            context: { $implicit: child }
                          "
                        ></ng-container>
                      </ng-container>
                    </igx-column-group>
                  </ng-template>

                  <ng-container *ngFor="let child of getColumnGroup(col)">
                    <ng-container
                      *ngTemplateOutlet="
                        child.IsGroupColumn ? groupColumn : defaultColumn;
                        context: { $implicit: child }
                      "
                    ></ng-container>
                  </ng-container>
                </igx-column-group>
              </ng-template>

              <ng-container *ngFor="let child of getColumnGroup(col)">
                <ng-container
                  *ngTemplateOutlet="
                    child.IsGroupColumn ? groupColumn : defaultColumn;
                    context: { $implicit: child }
                  "
                ></ng-container>
              </ng-container>
            </igx-column-group>
          </ng-template>

          <!-- LOOP END -->
          <ng-container *ngFor="let child of getColumnGroup(col)">
            <ng-container
              *ngTemplateOutlet="
                child.IsGroupColumn ? groupColumn : defaultColumn;
                context: { $implicit: child }
              "
            ></ng-container>
          </ng-container>
        </igx-column-group>
        <!-- End top level column group  -->
      </ng-container>
      <!-- End column rendering -->

      <!-- Bottom pager section -->
      <igx-paginator
        *ngIf="
          grid &&
          model.PagerSettings.AllowPaging !== 3 &&
          model.PagerSettings.AllowPaging !== 4
        "
        [(page)]="model.PagerSettings.CurrentPageIndex"
        [(perPage)]="model.PagerSettings.PageSize"
      >
        <igx-paginator-content>
          <label class="igx-page-size__label">Items Per Page</label>
          <div class="igx-page-size__select">
            <textarea
              class="itemsPerPage"
              [(ngModel)]="newItemsPerPage"
              (blur)="lostFocusTextPerPage()"
              maxlength="4"
            ></textarea>
            <div
              class="setItemsPerPageBorder"
              [class.disabled]="!allowChangeItemsPerPage"
            >
              <button class="setItemsPerPage" (click)="changePage()">Go</button>
            </div>
          </div>
          <igx-page-nav></igx-page-nav>
        </igx-paginator-content>
      </igx-paginator>
      <!-- End bottom pager section -->
    </igx-grid>
  </div>

  <ng-template igxCell let-context="cell" #customBooleanTemplate>
    <igx-checkbox
      [(ngModel)]="context.value"
      [disableRipple]="!context.editable"
      [disableTransitions]="!context.editable"
      [readonly]="!context.editable"
      class="checkbox-editor-behavior"
    >
    </igx-checkbox>
  </ng-template>

  <ng-container *ngIf="!model.IsEnabled">
    <div class="igx-grid--disabled autoHeightWidth"></div>
  </ng-container>
</ng-container>

./xam-grid.component.scss

@import '~igniteui-angular/lib/core/styles/themes/index';
@import '../../scss/styles.scss';
@import '../../scss/variables';

$filter-icon-theme: icon-theme(
  $color: $xam-grid-filtering-icon-color,
);

$custom-chip-theme: chip-theme(
  $background: $accent-background,
  $hover-background: $accent-background,
  $border-radius: 0,
);

$custom-drop-down-theme: drop-down-theme(
  $background-color: $accent-background,
  $item-text-color: $accent-color,

  $hover-item-background: $default-control-item-background-color-hover,

  $selected-item-background: $default-control-item-background-color-selected,
  $focused-item-background: $default-control-item-background-color-selected,
  $selected-focus-item-background:
    $default-control-item-background-color-selected,
  $selected-hover-item-background:
    $default-control-item-background-color-selected,
);

:host {
  position: relative;
  display: block;
}

.igx-grid--disabled {
  @extend %default-control-disabled-state;
  position: absolute;
  top: 0;
  left: 0;
  background-color: #eee;
  z-index: 99999;
}

.xamGridClass {
  width: inherit;
  height: inherit;
  min-height: inherit;
  min-width: inherit;
  box-sizing: border-box;

  .igxGrid {
    min-height: inherit;
    min-width: inherit;
  }

  igx-paginator {
    color: unset;
  }

  .itemsPerPage {
    border: $xam-grid-itemsperpage-border;
    resize: none;
    box-sizing: border-box;
    height: $xam-grid-itemsperpage-height;
    width: $xam-grid-itemsperpage-width;

    &:focus {
      outline: none !important;
      border: $xam-grid-itemsperpage-border-active;
    }
  }

  .setItemsPerPageBorder {
    border-radius: $xam-grid-btnpagesize-border-radius;
    border-width: $xam-grid-btnpagesize-div-border-width;
    border-color: var(--xam-grid-pager-setitemsperpage-background-color, black);
    border-style: solid;
    margin: $xam-grid-btnpagesize-div-border-margin;
    padding: $xam-grid-btnpagesize-padding;

    .setItemsPerPage {
      opacity: inherit;
      border-style: none;
      border-radius: $xam-grid-btnpagesize-border-radius;
      height: 100%;
      width: 100%;
      background-color: var(
        --xam-grid-pager-setitemsperpage-background-color,
        grey
      );
      color: var(--xam-grid-pager-setitemsperpage-foreground, white);

      &:hover:enabled {
        background-color: var(
          --xam-grid-pager-setitemsperpage-background-color-hover,
          rgb(149, 128, 128)
        );
      }

      &:focus-visible {
        outline: 0em;
      }
    }

    &:focus-visible {
      outline: 0em;
    }
  }
}

.xam-grid-with-paging-bottom {
  height: 96% !important;
}

::ng-deep .igx-grid__tbody-message {
  display: none;
}

:host ::ng-deep {
  @include css-vars($custom-drop-down-theme);
  @include css-vars($custom-chip-theme);
  @include css-vars($filter-icon-theme);

  igx-grid-cell {
    > igx-checkbox {
      //For those rare cases where an igx-checkbox is used for boolean columns values, we want to make sure
      //they are centered on the cell
      margin: auto;
    }
  }

  .igx-grid-th {
    .igx-grid-th__title {
      opacity: unset;
      overflow: visible;
      line-height: normal;

      div {
        white-space: pre;
        overflow-wrap: break-word;
        width: auto;
        height: auto;
        overflow: hidden;
      }

      > span {
        white-space: pre;
        width: auto;
        height: auto;
      }
    }

    &__icons {
      .sort-icon {
        color: $xam-grid-header-sort-icon-color;
        opacity: unset;

        &:hover {
          color: $xam-grid-header-sort-icon-hover-color;
        }

        &::after {
          background: transparent;
        }
      }
      .igx-excel-filter__icon {
        --igx-icon-color: $xam-grid-header-excel-filter-icon-color;
      }
    }

    &--sortable {
      .igx-grid-th__icons {
        min-width: auto;
        margin-left: 0.2em;
      }
    }

    &--active {
      box-shadow: none;
    }
  }

  .igx-grid-thead__wrapper {
    color: unset;

    .igx-grid-thead__item {
      .igx-grid-th--compact {
        padding: 0 0.4rem;
      }
    }

    .igx-grid__filtering-cell {
      background-color: $accent-background;
      padding: 0;

      .igx-chip-area {
        height: 100%;

        .igx-chip {
          width: 100%;
          height: 100%;

          &__content {
            display: none;
          }

          &__item {
            justify-content: flex-start;
            height: 100%;
            color: unset;
          }
        }
      }
    }
  }

  .igx-grid__tbody {
    .igx-grid__tr {
      .igx-grid__td {
        line-height: normal;
        font-size: inherit;
        overflow: hidden;
        padding: var(--xam-grid-cell-padding, $grid-cell-padding);

        .checkbox-editor-behavior {
          pointer-events: none;
        }

        div {
          font-size: inherit !important;
        }

        &:not([style*='justify-content: space-between'])
          > *[style*='width: 100%']:not(.horizontal-selfalign) {
          // Width has to be auto to recreate Silverlight behavior
          // workaround for in line style in base component
          width: auto !important;
        }

        > *[style*='height: 100%'] {
          // Height has to be auto to recreate Silverlight behavior
          // workaround for in line style in base component
          height: auto !important;
          margin-top: auto;
          margin-bottom: auto;
        }
      }

      .igx-grid__td--editing {
        // needs to override default igx padding that also contains an !important
        padding: var(
          --xam-grid-editing-cell-padding,
          $grid-cell-padding
        ) !important;

        .igx-input-group__input {
          // !important should be used because infragistics internally used so is the only way to override
          line-height: normal !important;
          font-size: inherit !important;
          height: $xam-grid-editing-cell-input-group-height !important;
          outline: $xam-grid-editing-cell-input-group-outline !important;
          background: $xam-grid-editing-cell-input-group-background !important;
        }

        // text selection color white and background black
        // TODO: refactoring need for scss to remove the important.
        [igxinput]::selection {
          background: $default-editing-selection-background-color !important;
          color: $default-editing-selection-foreground-color !important;
        }

        [igxinput]::-moz-selection {
          background: $default-editing-selection-background-color !important;
          color: $default-editing-selection-foreground-color !important;
        }

        // textarea text selection color white and background black
        // TODO: refactoring need for scss to remove the important.
        textarea::selection {
          background: $default-editing-selection-background-color !important;
          color: $default-editing-selection-foreground-color !important;
        }

        textarea::-moz-selection {
          background: $default-editing-selection-background-color !important;
          color: $default-editing-selection-foreground-color !important;
        }

        .checkbox-editor-behavior {
          pointer-events: all;
        }
      }

      &--even {
        background-color: $xam-grid-background-color-even-row;
        color: unset;
      }

      &--odd {
        color: unset;
      }
    }

    .igx-grid__tr:hover:not(.igx-grid__tr--selected) {
      background-color: $xam-grid-background-color-hover;
    }

    .igx-grid__tr--selected,
    .igx-grid__td--selected {
      background-color: $xam-grid-background-color-selected;
    }

    &-content {
      color: unset;
    }
  }

  .igx-grid__tr-container {
    &--active {
      box-shadow: none;
    }
  }

  .igx-grid__hierarchical-indent {
    margin: 0;
  }

  .igx-overlay__content {
    .igx-drop-down__list {
      .igx-drop-down__item {
        &--selected {
          border: $default-control-item-border-selected;
        }
      }
    }
  }
}

$custom-toast-theme: toast-theme(
  $background: $xam-grid-error-msg-background,
  $text-color: $xam-grid-error-msg-text-color,
  $border-radius: $xam-grid-error-msg-border-radius,
);

$custom-grid-theme: grid-theme(
  $edit-mode-color: --var($default-igx-grid-theme, 'row-border-color'),
  $cell-disabled-color: unset,
  $resize-line-color: $xam-grid-column-resize-splitter-background,
  $cell-editing-background: $xam-grid-background-color-selected,
  $filtering-header-background:
    var(--xam-grid-header-background, $xam-grid-filtering-header-background),
);

@include css-vars($custom-toast-theme);
@include css-vars($custom-grid-theme);

:host ::ng-deep [role='gridcell'] {
  border-right: solid 1px $xam-tile-splitter-background-color;
}
Legend
Html element
Component
Html element with directive

result-matching ""

    No results matching ""