Our blazing fast Grid component built with pure JavaScript


Post by Yamo93 »

I'm trying to add a tree column dynamically by accessing the ColumnStore and executing a "columns.insert(index, records)". But the tree carets don't expand correctly, and also I am getting this error in the console whenever I try to expand a record:

grid.umd.js?0469:111800 Uncaught (in promise) TypeError: Cannot read property 'id' of undefined
at Tree._callee$ (webpack-internal:///./node_modules/@bryntum/grid/grid.umd.js:111795)
at tryCatch (webpack-internal:///./node_modules/@bryntum/grid/grid.umd.js:148416)
at Generator.invoke [as _invoke] (webpack-internal:///./node_modules/@bryntum/grid/grid.umd.js:148646)
at Generator.eval [as next] (webpack-internal:///./node_modules/@bryntum/grid/grid.umd.js:148471)
at asyncGeneratorStep (webpack-internal:///./node_modules/@bryntum/grid/grid.umd.js:131285)
at _next (webpack-internal:///./node_modules/@bryntum/grid/grid.umd.js:131307)

This is my test case (in TypeScript):

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

const Prototyping = (): ReactElement => {
    const [customGridData, setCustomGridData] = useState([]);
    const userGridRef = useRef(null);

useEffect(() => {
    setCustomGridData([
        {
            id: 123,
            username: 'User123',
            children: [
                {
                    id: 124,
                    username: 'User124',
                },
                {
                    id: 125,
                    username: 'User125',
                },
                {
                    id: 126,
                    username: 'User126',
                },
            ],
        },
        {
            id: 127,
            username: 'User127',
        },
        {
            id: 128,
            username: 'User128',
        },
        {
            id: 129,
            username: 'User129',
        },
        {
            id: 130,
            username: 'User130',
        },
    ]);
}, []);

useEffect(() => {
    // Dynamically insert a tree column
    userGridRef.current.gridInstance.columns.insert(0, {
        type: 'tree',
        field: 'username',
        text: 'Username',
        flex: 1,
        editor: false,
    });
}, []);

const customGridConfig = {
    data: customGridData,
    treeFeature: true,
    autoHeight: true,
    columns: [
        {
            field: 'id',
            text: 'User ID',
            flex: 1,
        },
    ],
};

return (
    <BryntumGrid ref={userGridRef} {...customGridConfig} />
);
};

export default Prototyping;

Why isn't this working?


Post by mats »

When using the Tree feature it requires a Tree type column to be available as part of the initial columns config.


Post by Yamo93 »

Thanks for the quick answer, Mats. This was what I suspected too.

Do you think this is a correct approach then?

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

const Prototyping = (): ReactElement => {
    const [customGridData, setCustomGridData] = useState([]);
    const userGridRef = useRef(null);

useEffect(() => {
    setCustomGridData([
        {
            id: 123,
            username: 'User123',
            children: [
                {
                    id: 124,
                    username: 'User124',
                },
                {
                    id: 125,
                    username: 'User125',
                },
                {
                    id: 126,
                    username: 'User126',
                },
            ],
        },
        {
            id: 127,
            username: 'User127',
        },
        {
            id: 128,
            username: 'User128',
        },
        {
            id: 129,
            username: 'User129',
        },
        {
            id: 130,
            username: 'User130',
        },
    ]);
}, []);

useEffect(() => {
    // Dynamically update tree column fields
    userGridRef.current.gridInstance.columns.first.field = 'username';
    userGridRef.current.gridInstance.columns.first.text = 'Username';
}, []);

const customGridConfig = {
    data: customGridData,
    treeFeature: true,
    autoHeight: true,
    columns: [
        {
            type: 'tree',
            field: '',
            text: '',
        },
        {
            field: 'id',
            text: 'User ID',
            flex: 1,
        },
    ],
};

return (
    <BryntumGrid ref={userGridRef} {...customGridConfig} />
);
};

export default Prototyping;

Basically, I'm adding a tree column with empty fields, and then populating them whenever I get the data from the backend.

Just making sure that I'm doing things the Bryntum way. :)


Post by pmiklashevich »

column.text is documented as a property, you can set the value dynamically: https://www.bryntum.com/docs/grid/#Grid/column/Column#property-text but column.field is a config only: https://www.bryntum.com/docs/grid/#Grid/column/Column#config-field

If you don't know the field names in advance, you can send a request and get the data structure first. Then create a grid with the fields/columns you need. Also you can describe record Model dynamically if you wish: https://www.bryntum.com/docs/grid/#Core/data/Model

Pavlo Miklashevych
Sr. Frontend Developer


Post by Yamo93 »

Thanks for the answer @pmiklashevich.

I see, I tried to achieve that but failed.

I don't seem to get how I can delay the grid creation though, so that I can do the network request first, get the field names, and then create the grid. Do you have any suggestion?


Post by pmiklashevich »

This is a React component. If customGridData.length is 0, you return null from the functional component. Or just a template with "Data is loading..." message. Then when your side effect (request) is finished and you set data to the state, the component gets re-rendered. You get to the function again and customGridData.length > 0, so you define customGridConfig and return BryntumGrid component. Please learn about conditional rendering in React:
https://reactjs.org/docs/conditional-rendering.html

I assume you have a resource to return a set of field definitions. You can use axios, our tools (https://www.bryntum.com/docs/grid/#Core/helper/AjaxHelper), or vanilla JS (https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch) to send a request.

Also you can create an AjaxStore, load data. And on load update the state and create the grid. You can set the store instance directly to the grid: https://www.bryntum.com/docs/grid/#Grid/view/Grid#config-store

Pavlo Miklashevych
Sr. Frontend Developer


Post by Yamo93 »

Ah, you're right. Conditional rendering of course! Thanks.


Post Reply