Our blazing fast Grid component built with pure JavaScript


Post by henrikbackman »

Hi,

Is there a way to auto adjust the height of a row based on the height of the content in a cell and not the nr of events in the cell?

Right now we have rows where the first cell has plain text in it (without white-space: nowrap) and it can span from 1 row up too many. But I can't seem to find any way of auto adjusting the rows height based on the content of that first cell.

Post by pmiklashevich »

I'm afraid it's not supported

Pavlo Miklashevych
Sr. Frontend Developer


Post by johan.isaksson »

You could try implementing your own measuring in a renderer. Renderers can determine the rows height by assigning to `renderData.size.height`.

Something similar to:
1. In the renderer, add the text to an offscreen element with same css classes applied
2. Check that elements offsetHeight
3. Add any other height needed to the offsetHeight value and assign it to `size.height`
Best regards,
Johan Isaksson

Post by kerstin »

We have found a way to make it work as we want it to.
Below is updated code from your example "groupedheaders". Parts of the code is copied from your function "resizeToFitContent". Is this an ok way of doing it or will it possibly stop working after one of your updates?
import { Grid,DataGenerator, DomHelper } from '../../build/grid.module.js';
import shared from '../_shared/shared.module.js';

var grid;
var rendererTimer;

function cellRenderer({record, value, size}) {
    var html = "";
    if (value != null) {
        if (value === "John") {
            html = '<div>This is a string ' + value + " in a div</div>";
        } else if (value == "New York") {
            html = '<table cellspacing="0" cellpadding="0"><tbody><tr> <td><div>Helsinki</div></td><td><div>Oslo</div></td><td><div>Auckland New Zeeland</div></td></tr><tr><td></td><td><div>Uppsala</div></td><td></td></tr><tr><td></td><td><div>San Fransisco</div></td><td></td></tr><tr><td></td><td><div>San Fransisco</div></td><td></td></tr><tr><td></td><td><div>San Fransisco</div></td><td></td></tr><tr><td></td><td><div>San Fransisco</div></td><td></td></tr></tbody></table>';
        } else {
            html = value;
        }
    }
    const cellElement = this.grid.element.querySelector(`.b-grid-cell[data-column-id=${this.id}]`);
    const parentElement = this.grid.getSubGridFromColumn(this).element;
    const useHTML = true;

    var cellSize = measureTextWidthAndHeight(html, cellElement, useHTML, parentElement);
    size.height = cellSize.height; 

    return html;
}

function measureTextWidthAndHeight(text, sourceElement, useHTML, parentElement) {
    const offScreenDiv = DomHelper.getMeasureElement(sourceElement, parentElement);

    offScreenDiv[useHTML ? 'innerHTML' : 'innerText'] = text;

    const width = offScreenDiv.clientWidth;
    const height = offScreenDiv.clientHeight;
    offScreenDiv.className = '';

    return {width: width, height: height};
}


grid = new Grid({

    appendTo : 'container',
    autoHeight: false,
    minHeight : '20em',

    features : {
        columnPicker : true,
        regionResize : true,
    },

    columns : [
        { text : 'Customer#', field : 'id', width: 150, locked: true },
        {
            text     : 'Contact',
            children : [
                { text : 'First name', field : 'firstName', flex: 1, htmlEncode:false, renderer: cellRenderer,  },
                { text : 'Surname', field : 'surName', flex: 1, htmlEncode:false, renderer: cellRenderer,  },
                { text : 'City', field : 'city', flex: 1, htmlEncode:false, renderer: cellRenderer,  },
            ]
        },
        {
            text     : 'Favorites',
            children : [
                { text : 'Food', field : 'food', flex : 1 },
                { text : 'Color', field : 'color', flex : 1 }
            ]
        },
    ],

    data : DataGenerator.generateData(50)
});

Post by johan.isaksson »

Hi,

I do not see anything used that is likely to change any time soon :) You could save a line and some performance, cellElement gets passed to the cellRenderer:
function cellRenderer({record, value, size, cellElement}) {
Best regards,
Johan Isaksson

Post by gregc »

The measure text width and height function doesnt calculate a correct value for me so I just went with for now

function cellRenderer({record, value, size, cellElement}) {  
var html = value ? value : '';
const parentElement = this.grid.getSubGridFromColumn(this).element;
const useHTML = true;
var count = (html.match(/<br\/>/g) || []).length; var minheight = (count * 12) + (12 * ((html.length <40 ? 40 : html.length)/40)); if (minheight < 20) { minheight = 20; } if (size.height < minheight) { size.height = minheight; } return '<span>' + html + '</span>'; }

Note that since it calls on each column I use minheight.
I think its fairly important to support it out the box though, for example this doesn't update the row height when I change the column width dynamically.
I am sure there are libraries for calculating a spans height properly.


Post by johan.isaksson »

We plan to add support for auto height on cells. Opened a feature request on supporting it on a per column basis: https://github.com/bryntum/support/issues/2236

Best regards,
Johan Isaksson

Post by gregc »

This was marked resolved, how was it implemented - I assume I still need a renderer function to return the raw HTML but there is a column property that will mean I don't need to set the cell height manually?


Post by johan.isaksson »

Hi,

Yes, there is (in still unreleased version 4.1.0, available in Customer Zone) a new autoHeight config on Column. When set to true, the cells height will be measured after running the renderer and that height will be used to determine the row height (highest height on a row applies).

Best regards,
Johan Isaksson

Post by gregc »

I downloaded the Jan 15th 4.0.1-beta but autoHeight doesn't do anything on the column, nor do I see anything different in grid.module.js Same with the Jan-20 nightly build.

Last edited by gregc on Wed Jan 20, 2021 7:09 pm, edited 2 times in total.

Post Reply