Our blazing fast Grid component built with pure JavaScript


Post by prashantgoel »

We ran into a weird issue with a grid we created. We have two widget columns in our grid. Both with button widgets. The grid loads correctly the first time, but as soon as you hide or show a column, the buttons in the second widget column use the same class as the first widget column and also the onAction from the buttons in the first widget column fires if button in the second widget column are clicked. I tried making this change in your example, and I was able to replicate the issue. Let me know if I should attached a video to demo the problem.

import { Model, Grid, DataGenerator } from '../../build/grid.module.js?474079';
import shared from '../_shared/shared.module.js?474079';

// Define a model class representing the data shown in the grid
class Person extends Model {
    static get fields() {
        return [
            'name',
            'age',
            'verified',
            'approved',
            'reviewed'
        ];
    }
}

new Grid({
    appendTo  : 'container',
    rowHeight : 60,
    columns   : [
        {
            // Basic column showing the name
            text  : 'Name',
            field : 'name',
            flex  : '0 0 10em'
        },
        {
            // Number column showing the age
            text  : 'Age',
            field : 'age'
        },
        {
            text    : 'Buttons',
            align   : 'center',
            width   : 120,
            type    : 'widget',
            // An array of Button widgets
            widgets : [
                {
                    type     : 'button',
                    icon     : 'b-fa b-fa-minus',
                    cls      : 'b-blue b-raised',
                    onAction : ({ source: btn }) => {
                        btn.cellInfo.record.age--;
                    }
                },
                {
                    type     : 'button',
                    icon     : 'b-fa b-fa-plus',
                    cls      : 'b-blue b-raised',
                    onAction : ({ source: btn }) => {
                        // Every widget is decorated with a `cellInfo` object with the `record` and `column` instances
                        btn.cellInfo.record.age++;
                    }
                }
            ]
        },
{
            text    : 'Buttons',
            align   : 'center',
            width   : 120,
            type    : 'widget',
            // An array of Button widgets
            widgets : [
                {
                    type     : 'button',
                   icon     : 'b-fa b-fa-minus',


            },
            {
                type     : 'button',
                icon     : 'b-fa b-fa-plus',

            }
        ]
    },
    {
        text    : 'Field bound to name',
        type    : 'widget',
        width   : 200,
        widgets : [
            // A simple text field widget mapped to the `name` field
            {
                type : 'textfield',
                name : 'name'
            }
        ]
    },
    {
        text    : 'Slider bound to age',
        type    : 'widget',
        width   : 250,
        cls     : 'slidercell',
        widgets : [
            {
                type                 : 'slider',
                name                 : 'age',
                triggerChangeOnInput : true,
                showValue            : false,
                showTooltip          : true
            }
        ]
    },
    {
        text     : 'Checkboxes',
        type     : 'widget',
        align    : 'center',
        width    : 200,
        renderer : ({ widgets }) => {
            // We have access to the widgets inside the cell renderer method, so you can hide / show widgets or
            // mutate their value or state
        },
        widgets : [
            // Toggling these checkboxes will redraw the row and trigger an update of the progress bar column
            {
                type    : 'checkbox',
                tooltip : 'Reviewed',
                name    : 'reviewed'
            },
            {
                type    : 'checkbox',
                tooltip : 'Verified',
                name    : 'verified'
            },
            {
                type    : 'checkbox',
                tooltip : 'Approved',
                name    : 'approved'
            }
        ]
    },
    {
        text     : 'Progress',
        cellCls  : 'progresscell',
        editor   : false,
        renderer : ({ record }) => {
            return {
                class : 'progressbar',
                style : `height:${(Number(record.reviewed) + Number(record.verified) + Number(record.approved)) * 100 / 3}%`
            };
        }
    }
],

store : {
    // Configure the data store with the person model
    modelClass : Person,
    data       : DataGenerator.generateData(50).map(rowData => {
        rowData.reviewed = Math.random() > 0.5;
        rowData.verified = Math.random() > 0.5;
        rowData.approved = Math.random() > 0.5;
        return rowData;
    })
}
});

Post by tasnim »

Thank you very much for your detailed report. We'll investigate it. Here is the ticket to track progress https://github.com/bryntum/support/issues/8484

Best regards,
Tasnim


Post by prashantgoel »

Thank you.

In the meantime, since this is a roadblock for us, is it possible to create the first widget columns with links instead of buttons? I don't see a widget type of link in the API docs, but maybe there is an alternate method.


Post by Animal »

The issue is fixed and is in 5.6.6: https://github.com/bryntum/support/issues/8388


Post by prashantgoel »

I have 5.6.6 installed and I'm still seeing this behavior. I'm using a grid. Do I need to download a minor version or nightly build for the fix?


Post by Animal »

That is strange. Let me try again with that bug.


Post by Animal »

Yes. reopened. Must be a similar issue to what was fixed before. Will investigate.


Post by Animal »

For now, you can work round this by ensuring that the same configs are used on all buttons so that when the button is pulled from the cache and reused, it will be fully reconfigured.

So all buttons must have cls, icon and onAction.

So the configs get set correctly wherever the button is reused.


Post by prashantgoel »

Thanks, that workaround worked.


Post by prashantgoel »

Update.. it mostly worked. Our second column has a button widget with a menu attached. Because of this, once we show/hide another column, the buttons in the first column start showing a down arrow as if there is a menu available. Any way to prevent this? I tried adding a "menu" tag, but then the menu dropdown always shows. Please see link to the image below:

https://www.dropbox.com/scl/fi/yc74bxi0r93pofmo8xgy6/Button-widget.jpg?rlkey=6ji3oz3lyt6vksfa24qcfxqlc&dl=0


Post Reply