Wijmo flex grid high memory consumption

Posted by: madhavan.v on 24 February 2025, 2:48 am EST

  • Posted 24 February 2025, 2:48 am EST

    Hi,

    I’m using flex grid in Angular to create a large dynamic table (multiple rows in column header and dynamic columns). I’ve added wjFlexGridCellTemplate in template to create custom templates for Cell, CellEdit, ColumnHeader etc. It looks like the memory consumption is increasing after an edit happened to table when I’ve more than 300 rows.

    I’ve

    <wj-flex-grid-column *ngFor="let header of headers"
    in table to create the columns. I think it re-creates table each time when a change happened to the table.

    If I use formatItem, I can not render Angular components inside template.

    Will this leads to high memory usage?

    Is there any suggested approach to handle the large dynamic table with custom templates in Angular?

  • Posted 26 February 2025, 3:09 am EST

    Hi Madhavan,

    I tested this at my end with some sample data and I see low to no increase at all in memory consumption when using ngFor vs not using ngFor with all columns using Cell Template for 300-500 rows.

    That said yes increasing complexity in the column binding(using ngFor and CellTemplate) will cause your grid to consume more memory over all.

    >> Is there any suggested approach to handle the large dynamic table with custom templates in Angular?

    Could you please provide a sample that reproduces this issue? Alternatively, you can modify the following sample to demonstrate the problem and share it with us. Additionally, please include screenshots of your observations so we can replicate the issue on our end and get back you on this accordingly.

    Sample: https://stackblitz.com/edit/asd32sa-dvpy1ewu?file=src%2Fapp%2Fapp.component.ts

  • Posted 27 February 2025, 2:18 am EST

    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) => {});
    }
  • Posted 28 February 2025, 6:23 am EST

    Hi Madhavan,

    We tried to replicate the issue with the code snippet you shared, but we are still unable to replicate the issue on our end. Please refer to the attached sample on which we tested the issue. Could you please modify the attached sample to reproduce the issue and share it with us, so that we can investigate the issue further and assist you accordingly?

    In case, if there is something we missed, please let us know.

    Regards

    grid_sample.zip

Need extra support?

Upgrade your support plan and get personal unlimited phone support with our customer engagement team

Learn More

Forum Channels