Handsontable:在运行时更新单元格渲染器

Posted

技术标签:

【中文标题】Handsontable:在运行时更新单元格渲染器【英文标题】:Handsontable: Updating a cell renderer at runtime 【发布时间】:2016-02-10 15:37:21 【问题描述】:

我正在使用handsontable,如果单元格的值被编辑和更改,我想更改单元格的背景颜色。如果我的数据源是数组数组,我可以轻松做到这一点(参见小提琴:http://jsfiddle.net/chiman24/3o2c3c7m/)。

document.addEventListener("DOMContentLoaded", function() 

    // Row Styles
    var blank = function(instance, td, row, col, prop, value,
        cellProperties) 
        Handsontable.renderers.TextRenderer.apply(this, arguments);
        td.style.backgroundColor = '#ABAAAA'
    ;

    var align = function(instance, td, row, col, prop, value,
        cellProperties) 
        Handsontable.renderers.TextRenderer.apply(this, arguments);
        td.style.verticalAlign = 'middle';
        td.style.fontWeight = 'bold';
    ;

    var highlight1 = function(instance, td, row, col, prop, value,
        cellProperties) 
        Handsontable.renderers.TextRenderer.apply(this, arguments);
        td.style.backgroundColor = '#BDD7EE';
        td.style.textAlign = 'right';
    ;

    var changedBackgroundColor = '#cbd9e4';
    var defaultBackgroundColor = 'white';
    var hasChanged = function(instance, td, row, col, prop, value,
        cellProperties) 
        Handsontable.renderers.TextRenderer.apply(this, arguments);
        td.style.backgroundColor = changedBackgroundColor;
    ;
    var noChange = function(instance, td, row, col, prop, value,
        cellProperties) 
        Handsontable.renderers.TextRenderer.apply(this, arguments);
        td.style.backgroundColor = defaultBackgroundColor;
    ;

    var data = [
            ["1", "Hear us from heaven", "New Life Worship",
                "Anderson, Jared", "something"
            ],
            ["2", "Spirit Break Out", "Kim Walker", "Walker, Kim",
                "Still Believe"
            ]
        ],
        dataCopy = [
            ["1", "Hear us from heaven", "New Life Worship",
                "Anderson, Jared", "something"
            ],
            ["2", "Spirit Break Out", "Kim Walker", "Walker, Kim",
                "Still Believe"
            ]
        ],
        container = document.getElementById('example1'),
        hot1;


    //Table Row and Col Options
    hot1 = new Handsontable(container, 
        data: data,
        fixedColumnsLeft: 1,
        columnSorting: true,
        colHeaders: ["id", "title", "artist", "author", "album"],
        columns: [
            type: "text"
        , 
            type: "text"
        , 
            type: "text"
        , 
            type: "text"
        , 
            type: "text"
        ]
    );

    hot1.addHook('afterChange', afterChange);

    function afterChange(changes, source) 
        if (source == 'edit' || source == 'autofill') 
            $.each(changes, function(index, element) 
                var change = element;
                var rowIndex = change[0];
                var columnIndex = change[1];
                var oldValue = change[2];
                var newValue = change[3];
                var cellChange = 
                    'rowIndex': rowIndex,
                    'columnIndex': columnIndex
                ;
                if (oldValue != newValue) 
                    var cellProperties = hot1.getCellMeta(
                        rowIndex, columnIndex);
                    if (newValue != dataCopy[rowIndex][
                            columnIndex
                        ]) 
                        cellProperties.renderer = hasChanged;
                     else  //data changed back to original value.
                        cellProperties.renderer = noChange;
                    
                    hot1.render();
                
            );
        
    
);


// noSideScroll class added to fix some containers while side scrolling the table
$(window).scroll(function() 
    $('.noSideScroll').css(
        'left': $(this).scrollLeft()
    );
);

但是,当使用对象数组时,我无法让它工作。 (见小提琴:http://jsfiddle.net/chiman24/24mpavga/)。

var data = [
        "id": 1,
        "title": "First Loved Me",
        "artist": "Israel and New Breed",
        "author": "Houghton, Israel",
        "album": "Covered:  Alive In Asia"
    , 
        "id": 2,
        "title": "One Thing Remains",
        "artist": "Israel and New Breed",
        "author": "Houghton, Israel",
        "album": "Covered:  Alive In Asia"
    ],
    dataCopy = [
        "id": 1,
        "title": "First Loved Me",
        "artist": "Israel and New Breed",
        "author": "Houghton, Israel",
        "album": "Covered:  Alive In Asia"
    , 
        "id": 2,
        "title": "One Thing Remains",
        "artist": "Israel and New Breed",
        "author": "Houghton, Israel",
        "album": "Covered:  Alive In Asia"
    ],
    container = document.getElementById('example1'),
    hot1;


//Table Row and Col Options
hot1 = new Handsontable(container, 
    data: data,
    fixedColumnsLeft: 1,
    columnSorting: true,
    colHeaders: ["id", "title", "artist", "author", "album"],
    columns: [
        data: "id"
    , 
        data: "title"
    , 
        data: "artist"
    , 
        data: "author"
    , 
        data: "album"
    ]
);

hot1.addHook('afterChange', afterChange);

function afterChange(changes, source) 
    if (source == 'edit' || source == 'autofill') 
        $.each(changes, function(index, element) 
            var change = element;
            var rowIndex = change[0];
            var columnIndex = change[1];
            var oldValue = change[2];
            var newValue = change[3];
            var cellChange = 
                'rowIndex': rowIndex,
                'columnIndex': columnIndex
            ;
            if (oldValue != newValue) 
                var cellProperties = hot1.getCellMeta(
                    rowIndex, columnIndex);
                if (newValue != dataCopy[rowIndex][
                        columnIndex
                    ]) 
                    cellProperties.renderer = hasChanged;
                 else  //data changed back to original value.
                    cellProperties.renderer = noChange;
                
                hot1.render();
            
        );
    

有没有办法做到这一点?我想让它使用一组对象来工作,因为我来自服务器的数据将采用 JSON 格式。我已经搜索了几天的handsontable文档无济于事。任何帮助都感激不尽。谢谢。

【问题讨论】:

非常有趣的问题。您缺少的一件事是您应该在自定义渲染器上返回 td。不幸的是不会改变结果。 作为一种解决方法,您可以保留所有已更改单元格的地图,并使用通用渲染器检查当前单元格是否在此地图中。如果是,设置一种颜色,否则使用默认颜色。 @ZekeDroid 感谢您的调查。我注意到使用 data: "id"、data: "title 等会导致从 "getCellMeta" 返回的 cellProperties 对象出现问题。如图所示使用 "data" 属性时,cellProperties.renderer 为 "未定义”。这可能是一个可操作的错误。 好吧,你应该使用setCellMetaObject 设置它,否则它不会做任何事情。但即使有那一套,有些东西也不起作用。可以发到github问题页面上,可能是bug 【参考方案1】:

我从可动手做的 github 论坛获得了一些帮助。

显然,如果数据源是一个对象数组,那么在调用“getCellMeta”时,您必须将列索引作为属性传入,而不是传入数字列索引,如下所示:

hot.getCellMeta(2, hot.propToCol(columnIndex));

这是更新后的demo

【讨论】:

【参考方案2】:

改变单元格背景颜色的其他方法是使用单元格选项

...
if (oldValue != newValue)

    aCell.push(
         row: rowIndex, 
          col: hot.propToCol(columnIndex), 
          className: "cssWithBackgroundColor" );

    hot.updateSettings( cell: aCell );

如果用户撤消更改,您可以

if ( source == 'UndoRedo.undo')
    aCell.pop();
    hot.updateSettings( cell: aCell );

【讨论】:

以上是关于Handsontable:在运行时更新单元格渲染器的主要内容,如果未能解决你的问题,请参考以下文章

Handsontable:删除行后更新渲染器

自定义单元格渲染器操作未在 handsontable 中触发

渲染器使单元格相对于其他单元格值只读后的 JQuery handsontable - 不起作用

自定义渲染器功能在 Handsontable 插件中不起作用

创建handsontable后添加自定义单元格

自定义渲染器未应用于 Table 渲染 handsontable