Search code examples
javascriptcsshandsontable

Handsontable persistent CSS


according to this question CSS applied on Handsontable grid row on Scroll is not working properly I'm using a custom renderer to apply styles for my cells (bold, italic, underline, font size, font family).

As is suggested in the answer to the question above, I have a backing array of objects, each one representing each cell in my table with its own attributes so that renderer would know what to render (ie bold: true, italic: false).

However, this seems like a clunky way to do it because when I insert a row/col, I need to reflect this change in the backing array too, so that I can render it again. This seems like too much hassle to me and I can't imagine there's not a simpler way to do it (imagine having a full 100x100 table with custom CSS all over and inserting a col to the beginning).

Example of my code:

var myRenderer = function myRenderer(instance, td, row, col, prop, value, cellProperties) {
    Handsontable.renderers.TextRenderer.apply(this, arguments);

    var id = row+","+col;
    var result = $.grep(arr, function(e){ return e.id == id; });
    if (result[0] == undefined) {
        return;
    }
    if (result[0].bold) {
        var cell = $("table tr:eq(" + row + ") td:eq(" + col + ")");
        cell.css("font-weight", "bold");
    }
    ...
}

Is there a simpler way to store CSS styles directly in the handsontable instance so that I don't have to have a backing array?


Solution

  • I found out that CSS classes are persistent in cell metadata. This means that it should be possible to have a class for each style (or create them programmatically in runtime) and just append it to the cell classes.

    style.css

    .myBold {
        font-weight: bold;
    }
    

    script.js

    function addClass(row, col, mClass) {
        // row is row of the cell, col is column of the cell
    
        var cell = $("table tr:eq(" + row + ") td:eq(" + col + ")");
    
        // OPTIONAL - remove highlights from cells if you selected them by dragging
        cell.removeClass("area");
        cell.removeClass("highlight");
        cell.removeClass("current");
        // END OPTIONAL
    
        var classes = cell.attr("class");
        classes += mClass; //"myBold" in this case
    
        var hotCells = hot.getSettings().cell; //hot is Handsontable instance
    
        var containsCell = false;
        for (var i = 0; i < hotCells.length; i++) {
            if (hotCells[i].row == row && hotCells[i].col == col) {
                hotCells[i].className = classes;
                containsCell = true;
            }
        }
    
        if (!containsCell) {
            hotCells.push({row: row, col: col, className: classes});
        }
    
        hot.updateSettings({
            cell: hotCells
        });
    }
    
    function removeClass(row, col, mClass) {
        var cell = $("table tr:eq(" + row + ") td:eq(" + col + ")");
    
        cell.removeClass(mClass);
    
        var classes = cell.attr("class");
    
        var hotCells = hot.getSettings().cell;
        for (var i = 0; i < hotCells.length; i++) {
            if (hotCells[i].row == row && hotCells[i].col == col) {
                hotCells[i].className = classes;
            }
        }
    
        hot.updateSettings({
            cell: hotCells
        });
    }
    

    Remember that hot.updateSettings() is a slow operation so make sure to do it outside of loops.