Our blazing fast Grid component built with pure JavaScript


Post by zaclangley »

When I create a summary for a column that follows a grouped header. The summary columns to do not line up correctly.

Column Setup:
export const columns = [
        {
            type: 'rownumber',
            text: '#',
            width: 50,
            locked: true

        },
        {
            field: 'selected',
            type: 'check',
            text: 'Selected',
            width: 80,
            editor: true,
            locked: true
        },
        {
            field: 'firstname',
            text: 'First Name',
            editor: true,
            width: 120,
            locked: true
        },
        {
            field: 'lastname',
            text: 'Last Name',
            editor: true,
            width: 120,
            locked: true
        },
        {
            text: 'Gender',
            field: 'gender',
            width: 100,
            editor: {
                type: 'dropdown',
                items: [{
                    text: 'Male'
                }, {
                    text: 'Female'
                }, {
                    text: 'Other 1'
                }]
            }
            },
        {
            text: 'Race',
            field: 'race',
            default: 'None',
            width: 200,
            editor: {
                type: 'dropdown',
                items: [{
                    text: 'None'
                }, {
                    text: 'Dragonborn'
                }, {
                    text: 'Dwarf'
                }, {
                    text: 'Elf'
                }, {
                    text: 'Gnome'
                }, {
                    text: 'Half-Elf'
                }, {
                    text: 'Halfling'
                }, {
                    text: 'Half-Orc'
                }, {
                    text: 'Human'
                }, {
                    text: 'Tiefling'
                }, {
                    text: 'Goliath'
                }, {
                    text: 'Genasi'
                }, {
                    text: 'Aarakocra'
                }, {
                    text: 'Warforged'
                }, {
                    text: 'Kobold'
                }]
            },
            sum: (result, current, index) => {
                if(index === 0) {
                    result = {};
                }

                const race = current.race;

                if(!result.hasOwnProperty(race)) {
                    result[race] = 1;
                } else {
                    ++result[race];
                }

                return result;
            },
            summaryRenderer: ({sum}) => {
                let value = 0;
                let mostPopularRace = '';

                Object.keys(sum).forEach(key => {
                    if(value < sum[key]) {
                        value = sum[key];
                        mostPopularRace = key;
                    }
                });

                return `Most Popular: ${mostPopularRace}`;
            }
        },
        {
            text: 'Ability Scores',
            children: [
                {
                    text: 'Str',
                    field: 'str',
                    width: 100,
                    editor: {
                        type: 'dropdown',
                        items: [{
                            text: 8
                        }, {
                            text: 9
                        }, {
                            text: 10
                        }, {
                            text: 11
                        }, {
                            text: 12
                        }, {
                            text: 13
                        }, {
                            text: 14
                        }, {
                            text: 15
                        }, {
                            text: 16
                        }, {
                            text: 17
                        }, {
                            text: 18
                        }, {
                            text: 19
                        }, {
                            text: 20
                        }]
                    },
                },
                {
                    text: 'Dex',
                    field: 'dex',
                    default: 0,
                    width: 100,
                    editor: {
                        type: 'dropdown',
                        items: [{
                            text: 8
                        }, {
                            text: 9
                        }, {
                            text: 10
                        }, {
                            text: 11
                        }, {
                            text: 12
                        }, {
                            text: 13
                        }, {
                            text: 14
                        }, {
                            text: 15
                        }, {
                            text: 16
                        }, {
                            text: 17
                        }, {
                            text: 18
                        }, {
                            text: 19
                        }, {
                            text: 20
                        }]
                    }
                },
                {
                    text: 'Con',
                    field: 'con',
                    default: 0,
                    width: 100,
                    editor: {
                        type: 'dropdown',
                        items: [{
                            text: 8
                        }, {
                            text: 9
                        }, {
                            text: 10
                        }, {
                            text: 11
                        }, {
                            text: 12
                        }, {
                            text: 13
                        }, {
                            text: 14
                        }, {
                            text: 15
                        }, {
                            text: 16
                        }, {
                            text: 17
                        }, {
                            text: 18
                        }, {
                            text: 19
                        }, {
                            text: 20
                        }]
                    }
                },
                {
                    text: 'Int',
                    field: 'int',
                    default: 0,
                    width: 100,
                    editor: {
                        type: 'dropdown',
                        items: [{
                            text: 8
                        }, {
                            text: 9
                        }, {
                            text: 10
                        }, {
                            text: 11
                        }, {
                            text: 12
                        }, {
                            text: 13
                        }, {
                            text: 14
                        }, {
                            text: 15
                        }, {
                            text: 16
                        }, {
                            text: 17
                        }, {
                            text: 18
                        }, {
                            text: 19
                        }, {
                            text: 20
                        }]
                    }
                },
                {
                    text: 'Wis',
                    field: 'wis',
                    default: 0,
                    width: 100,
                    editor: {
                        type: 'dropdown',
                        items: [{
                            text: 8
                        }, {
                            text: 9
                        }, {
                            text: 10
                        }, {
                            text: 11
                        }, {
                            text: 12
                        }, {
                            text: 13
                        }, {
                            text: 14
                        }, {
                            text: 15
                        }, {
                            text: 16
                        }, {
                            text: 17
                        }, {
                            text: 18
                        }, {
                            text: 19
                        }, {
                            text: 20
                        }]
                    }
                },
                {
                    text: 'Cha',
                    field: 'cha',
                    default: 0,
                    width: 100,
                    editor: {
                        type: 'dropdown',
                        items: [{
                            text: 8
                        }, {
                            text: 9
                        }, {
                            text: 10
                        }, {
                            text: 11
                        }, {
                            text: 12
                        }, {
                            text: 13
                        }, {
                            text: 14
                        }, {
                            text: 15
                        }, {
                            text: 16
                        }, {
                            text: 17
                        }, {
                            text: 18
                        }, {
                            text: 19
                        }, {
                            text: 20
                        }]
                    },
                },
            ],
        },
        {
            text: 'Class',
            field: 'class',
            width: 200,
            editor: {
                type: 'dropdown',
                items: [{
                    text: 'None'
                }, {
                    text: 'Barbarian'
                }, {
                    text: 'Bard'
                }, {
                    text: 'Cleric'
                }, {
                    text: 'Druid'
                }, {
                    text: 'Fighter'
                }, {
                    text: 'Paladin'
                }, {
                    text: 'Ranger'
                }, {
                    text: 'Rogue'
                }, {
                    text: 'Sorceror'
                }, {
                    text: 'Warlock'
                }, {
                    text: 'Wizard'
                }, {
                    text: 'Murder Hobo'
                }],
            },
            sum: (result, current, index) => {
                if(index === 0) {
                    result = {};
                }

                // @ts-ignore
                const className = current.class;

                if(!result.hasOwnProperty(className)) {
                    result[className] = 1;
                } else {
                    ++result[className];
                }

                return result;
            },
            summaryRenderer: ({sum}) => {
                let value = 0;
                let mostPopularClass = '';

                Object.keys(sum).forEach(key => {
                    if(value < sum[key]) {
                        value = sum[key];
                        mostPopularClass = key;
                    }
                });

                return `Most Popular: ${mostPopularClass}`;
            }
        },
        {
            field: 'age',
            text: 'Age',
            type: 'number',
            min: 0,
            max: 100,
            width: 80,
            editor: true
        },
        {
            field: 'level',
            text: 'Level',
            type: 'number',
            min: 0,
            max: 100,
            width: 80,
            editor: true
        },
        {
            field: 'rating',
            type: 'rating',
            text: 'Rating',
            max: 7,
            default: 5,
            width: 215,
            editor: false
        },
        {
            field: 'startdate',
            text: 'Start Date',
            type: 'date',
            format: 'MM-DD-YYYY',
            width: 200,
            editor: true
        },
        {
            field: 'enddate',
            text: 'End Date',
            type: 'date',
            format: 'MM-DD-YYYY',
            width: 200,
            editor: true
        },
        {
            field: 'progress',
            text: 'EXP Progress',
            type: 'percent',
            width: 200,
            editor: true
        },
        {
            type : 'template',
            text : 'Location',
            field : 'city',
            template : ({value}) => `Lives in ${value}`,
            width: 120
        },
        {
            type : 'widget',
            text : 'Button Widget',
            field : 'color',
            widgets : [ {
                type: 'button',
                cls: 'b-raised b-orange',
                onClick: () => { console.log('Button Clicked'); }
            }],
            width: 150
        },
        {
            type : 'widget',
            text : 'Power Level',
            field : 'powerlevel',
            widgets : [ {
                type: 'slider',
                min: 0,
                max: 100,
                default: 50,
                onClick: () => { console.log('Button Clicked'); }
            }],
            width: 150
        }
];
Row Setup:
export const generateData = (num: number) => {
    let data: Object[] = [];
    for(let i = 0; i < num; i++) {
        data.push(
            {id: i, rowHeight: Math.floor(Math.random() * 100) + 80, selected: false, firstname: 'Jane', lastname: 'Doe', age: 30, str: 18, dex: 16, con: 14, int: 12, wis: 10, cha: 8, level: 3, rating: 6, startdate: '02-10-2018', enddate: '03-10-2018', progress: 23, city: 'Denver', color: 'TPK', gender: 'Male', class: 'Barbarian', race: 'Dragonborn'}
        );
    }
    return data;
};
Component Setup:
import React from 'react';
import BryntumGrid from '../../../bryntum/BryntumGrid.jsx';
import '../../../bryntum/grid.dark.css';
import './bryntumScheduleMainTable.less';
import { columns } from './columns/bryntumSchedulerMainTableColumns';
import { generateData } from './__mocks__/mockBryntumData';

export class BryntumTableWrapper extends React.Component {

    // @ts-ignore
    private BryntumGridReference: Element;

    setBrytumGridReference = (node) => {
        this.BryntumGridReference = node;
    }

    handleSelectionChange = ({selected, mode}) => {
        if (mode === 'row' && selected.length) {
            this.setState({selectedTeam: selected[0].team || 'None'});
        }
    }

    render() {
        return(
            <div className="bryntum-grid-container">
                <BryntumGrid
                    ref={this.setBrytumGridReference}
                    height={740}
                    rowHeight={60}
                    // Columns in grid
                    columns={columns}

                    // Rows to display in grid
                    data={generateData(10000)}
                    columnReorder={true}
                    columnResize={true}
                    regionResize={true}
                    stripe={true}
                    summary={true}
                    onSelectionChange={this.handleSelectionChange}
                />
            </div>
        );
    }
}
If I make the summary column follow a non-grouped column, the summary is still misaligned.
If I remove the grouped header, it aligns perfectly.
If I put a summary column before the grouped header, it works just fine.

Post by pmiklashevich »

I'm afraid I cannot reproduce the issue. Maybe I missed something. Could you please start changing examples/react/app.jsx then zip it up and attach here, so I can replace our app.jsx and see in VCS what have been changed? Runnable test case is always preferable than code snippets. Also it would be nice if you can provide more detailed instructions of what to do to see the issue and it would be nice to have a screenshot from you where I should look at to see the misalignment.

Pavlo Miklashevych
Sr. Frontend Developer


Post by pmiklashevich »

Accepted! Reproduced on the Summary demo. Thanks for the report! Here's the ticket to track the progress: https://app.assembla.com/spaces/bryntum/tickets/7357

Pavlo Miklashevych
Sr. Frontend Developer


Post by johan.isaksson »

I have pushed a fix for this bug, it will be part of our next release (1.2). Existing customers can find it in nightlies tomorrow.
Best regards,
Johan Isaksson

Post Reply