Thanks Akshay. I’ll add more details here.
Columns are dynamically created based on a data that comes from NgRx state. Let’s say,
{"item":{"name":"Laptop","dependentItems":[{"name":"Charger"},{"name":"Mouse"},{"name":"Laptop Bag"}],"table":{"columns":[{"id":"col1","header1":"Product ID","header2":"Product Name","header3":"Price","type":"text","position":1},{"id":"col2","header1":"Availability","header2":"Discount","header3":"Rating","type":"number","position":2}],"rows":[{"position":1,"cells":[{"id":"cell1","columnId":"col1","position":1,"value":"12345"},{"id":"cell2","columnId":"col2","position":1,"value":"In Stock"}]},{"position":2,"cells":[{"id":"cell3","columnId":"col1","position":2,"value":"Laptop"},{"id":"cell4","columnId":"col2","position":2,"value":"15% Off"}]},{"position":3,"cells":[{"id":"cell5","columnId":"col1","position":3,"value":"$999"},{"id":"cell6","columnId":"col2","position":3,"value":"4.5"}]}]}}}
In template something like,
<wj-flex-grid #flexGrid [(itemsSource)]="collectionView" [selectionMode]="'MultiRange'"
(initialized)="onTableInitialize(flexGrid)">
<wj-flex-grid-column *ngFor="let column of item.table.columns; trackBy: trackByColumn" [binding]="column.id" width="*"
[minWidth]="125" [isRequired]="false">
<ng-template wjFlexGridCellTemplate [cellTypeStr]="'ColumnHeader'" let-cell="cell">
<column-header [tableCell]="cell" [column]="column" (iconClicked)="onIconClick($event)"></column-header>
</ng-template>
<ng-template wjFlexGridCellTemplate [cellTypeStr]="'Cell'" let-cell="cell">
<table-cell [tableCell]="cell" [cell]="item.table.rows[cell.row.index].cells[cell.col.index]" [column]="column"
(cellClicked)="grid.startEditing(true, $event.row, $event.col)"></table-cell>
</ng-template>
<ng-template wjFlexGridCellTemplate [cellTypeStr]="'Cell'" let-cell="cell">
<table-cell [tableCell]="cell" [cell]="item.table.rows[cell.row.index].cells[cell.col.index]" [column]="column"
(cellClicked)="grid.startEditing(true, $event.row, $event.col)"></table-cell>
</ng-template>
<ng-template wjFlexGridCellTemplate [cellTypeStr]="'CellEdit'" let-cell="cell">
<div [hidden]="someCondition">
<wj-multi-select #multiSelect displayMemberPath="value" checkedMemberPath="checked" [selectedIndex]="-1"
[showFilterInput]="true" [checkOnFilter]="false"
(isDroppedDownChanged)="onDropdownChange(multiSelect, false, cell.row.index, cell.col.index)"
[showSelectAllCheckbox]="true" selectAllLabel="All"></wj-multi-select>
</div>
<div [hidden]="someCondition">
<wj-combo-box #comboBox selectedValuePath="value" displayMemberPath="value" [selectedIndex]="-1"
[handleWheel]="false" [isEditable]="false"
(isDroppedDownChanged)="onDropdownChange(comboBox, true, cell.row.index, cell.col.index)"
(formatItem)="formatCombobox(comboBox, $event)">
</wj-combo-box>
</div>
</ng-template>
</wj-flex-grid-column>
</wj-flex-grid>
In component file, create collectionView.sourceCollection from item.table.rows.cells as a key-value pair(columnId - cellValue).
onTableInitialize(flexGrid: wjcGrid.FlexGrid) {
this.makeMultiHeaderGrid(2) // this.grid.columnHeaders.rows.push(new wjcGrid.Row())
if (this.hasMerged) this.addMergedHeader() // Add one moew row to columnHeaders
this.grid.mergeManager = this._getCustomMergeManager(); // Merge if value of one prop from nearest columns are same.
/* Showing 300 rows in table initially (with this custom cell template and iteration) was taking so much time to initial render. So set visible=false initially for the rows after 20. */
// Added "scrollPositionChanged" listener to show rows on scroll position reached to the last row.
this.grid.scrollPositionChanged.addHandler((s: wjcGrid.FlexGrid) => {
if (s.viewRange.bottomRow >= this.rowsVisible - 1 && this.rowsVisible < this.item.table.rows.length) {
let newCount = Math.min(s.rows.length, this.rowsVisible + 20);
for (let i = this.rowsVisible; i < newCount; i++) s.rows[i].visible = true;
this.rowsVisible = newCount;
}
});
// Click listener
this.grid.hostElement.addEventListener('click', (e) => {
let ht = this.grid.hitTest(e);
...
});
// Contextmenu listener
this.grid.hostElement.addEventListener('contextmenu', (e) => {
let ht = this.grid.hitTest(e);
...
});
// Double-Click listener
this.grid.hostElement.addEventListener('dblclick', (e) => {
let ht = this.grid.hitTest(e);
...
});
// Double-Click listener
this.grid.hostElement.addEventListener('dblclick', (e) => {
let ht = this.grid.hitTest(e);
...
});
// Listeners to show tooltip with wjcCore.Tooltip
this.grid.hostElement.addEventListener('mousemove', (mOverEvt) => {});
this.grid.hostElement.addEventListener('mouseout', (mOverEvt) => {});
// FormatItem handler
this.grid.formatItem.addHandler((s: wjcGrid.FlexGrid, e: wjcGrid.FormatItemEventArgs) => {
if (e.panel.cellType === wjcGrid.CellType.RowHeader) { /* Adding number to row header */ }
if (e.panel.cellType === wjcGrid.CellType.ColumnHeader) { /* Style changes */ }
if (e.panel.cellType === wjcGrid.CellType.Cell) { /* Cell value validation */ }
});
// Keydown listener to track keyboard shortcuts (copy, cut, paste etc)
this.grid.hostElement.addEventListener('keydown', (e: any) => {});
// CellEditEnded listener to get the value and update state, API call etc.
this.grid.cellEditEnded.addHandler((s, e) => {});
}