Our blazing fast Grid component built with pure JavaScript


Post by Yamo1993 »

Example code in TypeScript:

import React, { ReactElement, useRef } from 'react';
import { BryntumGrid } from '@bryntum/grid-react';

interface TreeNode {
    id: number,
    username: string,
    children?: TreeNode[],
}

class TreeDataGenerator {
    nodes: [];
    idCount: number;
    numberOfUsers: number;
    levels: number;

constructor (numberOfUsers = 10, levels = 3) {
    this.nodes = [];
    this.idCount = 1;
    this.numberOfUsers = numberOfUsers;
    this.levels = levels;
}

private isEven (value: number): boolean {
    return value % 2 === 0;
}

public generateData (treeData = []): TreeNode[] {
    this.levels--;
    
    for (let i = 0; i < this.numberOfUsers; i++) {
        const node: TreeNode = {
            id: this.idCount,
            username: `User ${this.idCount}`,
        };
        if (this.levels) {
            node.children = [];
        }
        treeData.push(node);
        this.idCount++;

        if (this.levels && this.isEven(this.numberOfUsers)) {
            this.generateData(node.children);
        }
    }

    return treeData;
}
}

const MyGrid = (): ReactElement => {
    const grid = useRef(null);

function expandAll (): void {
    grid.current.gridInstance.expandAll();
}

function collapseAll (): void {
    const gridInstance = grid.current.gridInstance;
    const store = gridInstance.store;
    store.traverse((record: any) => {
        if (record.isExpanded(store)) {
            gridInstance.collapse(record);
        }
    });
}

const generator = new TreeDataGenerator();

return (
    <>
        <button onClick={expandAll}>Expand all</button>
        <button onClick={collapseAll}>Collapse all</button>
        <BryntumGrid
            ref={grid}
            treeFeature
            height={400}
            data={generator.generateData()}
            columns={[
                { field: 'id', text: 'Id', type: 'tree' },
                { field: 'username', text: 'Username' },
            ]}
        />
    </>
);
};

export default MyGrid;

Steps to reproduce:

  1. Click on "Expand all".
  2. Scroll to bottom of TreeGrid.
  3. Click on "Collapse all".
  4. Scroll up and notice the error messages:
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'id')
    at RowManager.getOffsetHeight (grid.umd.js?0469:108654)
    at RowManager.displayRecordAtTop (grid.umd.js?0469:109367)
    at RowManager.renderFromRow (grid.umd.js?0469:108949)
    at RowManager.refresh (grid.umd.js?0469:109032)
    at Grid.onStoreRemove (grid.umd.js?0469:112604)
    at Store.trigger (grid.umd.js?0469:45991)
    at Store.internalToggleTreeSubRecords (grid.umd.js?0469:15519)
    at Store.onNodeCollapse (grid.umd.js?0469:15635)
    at Store.toggleCollapse (grid.umd.js?0469:15594)
    at Tree.toggleCollapse (grid.umd.js?0469:103696)

Post by Animal »

Your function collapseAll should look like this:

async function collapseAll (): void {
    const gridInstance = grid.current.gridInstance;
    await gridInstance.collapseAll();
}

Post by Yamo1993 »

The reason why I am not using collapseAll is to avoid the issue that I recently reported here: viewtopic.php?f=43&t=19795

I just tried the async await approach with the test case mentioned above, and it still doesn't work.


Post by Animal »

I just went into our tree Grid example and defined this in the debugger:

function collapseAll() {
    const store = grid.store;
    store.traverse((record) => {
        if (record.isExpanded(store)) {
            grid.collapse(record);
        }
    });
}

When I executed the function it worked.

Can you reproduce this in a grid example page?


Post by Yamo1993 »

I managed to reproduce this in the tree example page (https://bryntum.com/examples/grid/tree/):

Example code:

import { TreeGrid, GridRowModel } from '../../build/grid.module.js?455383';
import shared from '../_shared/shared.module.js?455383';

function collapseAll(tree) {
    const store = tree.store;
    store.traverse((record) => {
        if (record.isExpanded(store)) {
            tree.collapse(record);
        }
    });
}

class TreeDataGenerator {
constructor (numberOfUsers, levels) {
    this.nodes = [];
    this.idCount = 1;
    this.numberOfUsers = 10;
    this.levels = 3;
}

isEven (value) {
    return value % 2 === 0;
}

generateData (treeData = []) {
    this.levels--;
    
for (let i = 0; i < this.numberOfUsers; i++) { const node = { id: this.idCount, username: `User ${this.idCount}`, }; if (this.levels) { node.children = []; } treeData.push(node); this.idCount++; if (this.levels && this.isEven(this.numberOfUsers)) { this.generateData(node.children); } } return treeData; } } const generator = new TreeDataGenerator(); let tree = new TreeGrid({ maxHeight: 300, appendTo : 'container', features : { cellEdit : true, filter : true, rowReorder : true, stripe : true }, loadMask : 'Loading tree data...', columns : [ { field: 'id', text: 'Id', type: 'tree' }, { field: 'username', text: 'Username' }, ], store : { data : generator.generateData(), }, tbar : [ { type : 'button', ref : 'customButton', icon : 'b-fa-folder-open', pressedIcon : 'b-fa-plane', text : 'Use custom tree icons', toggleable : true, onToggle({ pressed }) { tree.store.readUrl = 'data/' + (pressed ? 'ohare-airport.json' : 'kastrup-airport.json'); tree.element.classList[pressed ? 'add' : 'remove']('ohare-airport'); tree.store.load(); } }, { type : 'button', ref : 'expandAllButton', icon : 'b-fa b-fa-angle-double-down', text : 'Expand all', onAction : () => tree.expandAll() }, { type : 'button', ref : 'collapseAllButton', icon : 'b-fa b-fa-angle-double-up', text : 'Collapse all', onAction : () => collapseAll(tree) } ] });

Post by Maxim Gorkovsky »

Reproduced, ticket opened here: https://github.com/bryntum/support/issues/3930
Thank you for report!


Post by Yamo1993 »

You're welcome!


Post Reply