我们正在实现用户偏好,以(立即)在网格上显示“更多”或“更少”数据。 “更多”应增加行高(每行具有相同的增加的高度)。

当用户切换时,我们将更新DataView,并使用更新的rowHeight值在网格上调用setOptions。然后,我们调用invalidate()和render()。

但是行高没有被更新。 :(

有人可以提出解决方案吗?我们应该直接通过CSS更改高度吗?如果是这样,那么有什么提示吗?

最佳答案

实际上,可以基于用户交互来动态更新行高。 Slickgrid API提供了我们所需的一切。

因为:

  • 我们可以动态添加/删除行;
  • 我们可以在行和单元格级别动态应用自定义css

  • 这是一个入门的简单演示:

    ////////////////////////////////////////////////////////////////////////////////
    //example codez re trying to create a grid with rows of dynamic height to
    //cater for folks that wanna bung loads of stuff in a field & see it all...
    //by [email protected] ~ visit: www.violet313.org/slickgrids
    //have all the fun with it  ;) vxx.
    ////////////////////////////////////////////////////////////////////////////////
    modSlickgridSimple=(
    function()
    {
        var _dataView=null;
        var _grid=null;
        var _data=[];
    
    
        //////////////////////////////////////////////////////////////
        //////////////////////////////////////////////////////////////
        var getPaddingItem=function(parent , offset)
        {
            var item={};
    
            for (var prop in _data[0]) item[prop]=null;
            item.id=parent.id+"."+offset;
    
            //additional hidden padding metadata fields
            item._collapsed=     true;
            item._isPadding=     true;
    
            return item;
        }
    
        //////////////////////////////////////////////////////////////
        //this just builds our expand collapse button
        //////////////////////////////////////////////////////////////
        var onRenderIDCell=function(row, cell, value, columnDef, item)
        {
            if (item._isPadding==true); //render nothing
            else if (item._collapsed) return "<div class='toggle expand'></div>";
            else
            {
                var html=[];
                var rowHeight=_grid.getOptions().rowHeight;
    
                //V313HAX:
                //putting in an extra closing div after the closing toggle div and ommiting a
                //final closing div for the detail ctr div causes the slickgrid renderer to
                //insert our detail div as a new column ;) ~since it wraps whatever we provide
                //in a generic div column container. so our detail becomes a child directly of
                //the row not the cell. nice =)  ~no need to apply a css change to the parent
                //slick-cell to escape the cell overflow clipping.
    
                //sneaky extra </div> inserted here-----------------v
                html.push("<div class='toggle collapse'></div></div>");
    
                html.push("<div class='dynamic-cell-detail' ");   //apply custom css to detail
                html.push("style='height:", item._height, "px;"); //set total height of padding
                html.push("top:", rowHeight, "px'>");             //shift detail below 1st row
                html.push("<div>",item._detailContent,"</div>");  //sub ctr for custom styling
                //&omit a final closing detail container </div> that would come next
    
                return html.join("");
            }
        }
    
        //////////////////////////////////////////////////////////////
        //////////////////////////////////////////////////////////////
        var onRowClick=function(e, args)
        {
            _dataView.beginUpdate();
    
            if ($(e.target).hasClass("toggle"))
            {
                var item=_dataView.getItem(args.row);
    
                if (item)
                {
                    if (!item._collapsed)
                    {
                        item._collapsed=true;
                        for (var idx=1; idx<=item._sizePadding; idx++)
                            _dataView.deleteItem(item.id+"."+idx);
                        item._sizePadding=0;
                    }
                    else
                    {
                        item._collapsed=false;
                        kookupDynamicContent(item);
                        var idxParent=_dataView.getIdxById(item.id);
                        for (var idx=1; idx<=item._sizePadding; idx++)
                            _dataView.insertItem(idxParent+idx, getPaddingItem(item,idx));
                    }
                    _dataView.updateItem(item.id, item);
                }
                e.stopImmediatePropagation();
            }
    
            _dataView.endUpdate();
        }
    
        //////////////////////////////////////////////////////////////
        var gridOptions={ enableColumnReorder:  true };
    
        //////////////////////////////////////////////////////////////
        var _gridColumns=
        [
            {
                id:         "id",
                name:       "",
                field:      "id",
                resizable:  false,
                width:      20,
                formatter:  onRenderIDCell,
            },
            {id: "title",        name: "Title",         field: "title",        resizable: true},
            {id: "duration",     name: "Duration",      field: "duration",     resizable: true},
            {id: "pcComplete",   name: "% Complete",    field: "pcComplete",   resizable: true},
            {id: "start",        name: "Start",         field: "start",        resizable: true},
            {id: "finish",       name: "Finish",        field: "finish",       resizable: true},
            {id: "effortDriven", name: "Effort Driven", field: "effortDriven", resizable: true},
        ];
    
        //////////////////////////////////////////////////////////////
        //////////////////////////////////////////////////////////////
        var kookupTestData=(function()
        {
            for (var i = 0; i < 100; i++)
                _data[i] =
                {
                    id:               i,
                    title:            "Task " + i,
                    duration:         "5 days",
                    pcComplete:       Math.round(Math.random() * 100),
                    start:            "01/01/2009",
                    finish:           "01/05/2009",
                    effortDriven:     (i % 5 == 0),
    
                    //additional hidden metadata fields
                    _collapsed:       true,
                    _sizePadding:     0,     //the required number of pading rows
                    _height:          0,     //the actual height in pixels of the detail field
                    _isPadding:       false,
                };
        })();
    
        //////////////////////////////////////////////////////////////
        //create the detail ctr node. this belongs to the dev & can be custom-styled as per
        //////////////////////////////////////////////////////////////
        var kookupDynamicContent=function(item)
        {
            //add some random oooks as fake detail content
            var oookContent=[];
            var oookCount=Math.round(Math.random() * 12)+1;
            for (var next=0; next<oookCount; next++)
                oookContent.push("<div><span>oook</span></div>");
            item._detailContent=oookContent.join("");
    
            //calculate padding requirements based on detail-content..
            //ie. worst-case: create an invisible dom node now &find it's height.
            var lineHeight=13; //we know cuz we wrote the custom css innit ;)
            item._sizePadding=Math.ceil((oookCount*lineHeight) / _grid.getOptions().rowHeight);
            item._height=(item._sizePadding * _grid.getOptions().rowHeight);
        }
    
        //////////////////////////////////////////////////////////////
        //jquery onDocumentLoad
        //////////////////////////////////////////////////////////////
        $(function()
        {
            //initialise the data-model
            _dataView=new Slick.Data.DataView();
            _dataView.beginUpdate();
            _dataView.setItems(_data);
            _dataView.endUpdate();
    
            //initialise the grid
            _grid=new Slick.Grid("#grid-simple", _dataView, _gridColumns);
            _grid.onClick.subscribe(onRowClick);
    
            //wire up model events to drive the grid per DataView requirements
            _dataView.onRowCountChanged.subscribe
                (function(){ _grid.updateRowCount();_grid.render(); });
    
            _dataView.onRowsChanged.subscribe
                (function(e, a){ _grid.invalidateRows(a.rows);_grid.render(); });
    
            $(window).resize(function() {_grid.resizeCanvas()});
        });
    }
    )();
    //////////////////////////////////////////////////////////////
    //done ;)
    ::-webkit-scrollbar
    {
        width:              12px;
        background-color:   #B9BACC;
    }
    ::-webkit-scrollbar-track
    {
        color:              #fff;
        -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
        border-radius:      10px;
    }
    ::-webkit-scrollbar-thumb
    {
        color:              #96A9BB;
        border-radius:      10px;
        -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.5);
    }
    
    body
    {
        font-family:        Arial, Helvetica, sans-serif;
        background-color:   #131313;
        position:           absolute;
        top:                5px;
        bottom:             5px;
        left:               5px;
        right:              5px;
    }
    
    #grid-simple
    {
        position:         absolute;
        top:              0px;
        left:             0px;
        right:            0px;
        bottom:           0px;
        margin:           auto;
        font-size:        12px;
        background-color: #ECEEE9;
    }
    
    .toggle
    {
        height:           16px;
        width:            16px;
        display:          inline-block;
    }
    .toggle.expand
    {
        background: url(https://violet313.github.io/assets/expand.gif) no-repeat center center;
    }
    
    .toggle.collapse
    {
        background: url(https://violet313.github.io/assets/collapse.gif) no-repeat center center;
    }
    
    
    /*--- generic slickgrid padding pollyfill  ----------------------*/
    
    .dynamic-cell-detail
    {
        z-index:            10000;
        position:           absolute;
        background-color:   #F4DFFA;
        margin:             0;
        padding:            0;
        width:              100%;
        display:            table;
    }
    
    .dynamic-cell-detail > :first-child
    {
        display:            table-cell;
        vertical-align:     middle;
        text-align:         center;
        font-size:          12px;
        line-height:        13px;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <script type="text/javascript" src="http://code.jquery.com/ui/1.9.2/jquery-ui.js"></script>
    <script type="text/javascript" src="https://cdn.rawgit.com/Celebio/SlickGrid/master/lib/jquery.event.drag-2.2.js"></script>
    <script type="text/javascript" src="https://cdn.rawgit.com/Celebio/SlickGrid/master/slick.core.js"></script>
    <script type="text/javascript" src="https://cdn.rawgit.com/Celebio/SlickGrid/master/slick.grid.js"></script>
    <script type="text/javascript" src="https://cdn.rawgit.com/Celebio/SlickGrid/master/slick.dataview.js"></script>
    <link rel="stylesheet" type="text/css" href="https://cdn.rawgit.com/Celebio/SlickGrid/master/slick.grid.css">
    <link rel="stylesheet" type="text/css" href="https://cdn.rawgit.com/Celebio/SlickGrid/master/slick-default-theme.css">
    <link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.9.2/themes/base/jquery-ui.css">
    
    
    <div id="grid-simple"></div>


    少于200行代码。
    fiddle with it!

    顺便说一句,这也是一种出色的Datatables(几乎)通过其API native 提供的方法。 &imo这是正确的模式;以及我如何选择使用Slickgrid实现自己的东西。但这涉及到轻微的破解,并且在任何情况下*都不完全符合OP要求;我声称这是可能的。

    要对每个单元执行动态行高,我们采用了类似的技巧,但我们还必须处理一些副作用:〜

    造型行分隔

    我们必须:
  • 跳过每单元溢出剪辑
  • 删除不必要的行样式错误
  • 删除行边界
  • Slickgrid API通过Grid.getItemMetadata回调接口(interface)提供基于行的样式。在第107行的下一个 fiddle 中,请参见此接口(interface)的onRenderRow实现:
    fiddle with it!

    还要注意第148-150行,我调用Slickgrid Grid.setCellCssStyles API添加一个自定义的dynamic-cell css类,该类将overflow设置为visible,以设置每单元溢出剪辑的样式。

    列大小调整

    如果详细信息内容是静态的,则列大小调整将是一个gimme。

    响应列宽变化(流文本或wotnot)的详细内容需要一些工作。填充行需要相应地动态添加和删除。参见(从第66行开始)下一个 fiddle 中的addPaddingtrimPadding函数:
    fiddle with it!

    排序

    这里也有一些工作要做。我们需要确保无论我们是向上排序还是向下排序,填充都连续地保留在父级下面。在下面的 fiddle 中查看第136行的comparer:
    fiddle with it!

    过滤

    几乎是单线的:如果是填充,则将比较委托(delegate)给父级。任务完成。在下一个 fiddle 中查看第192行的pcFilter:
    fiddle with it!

    耶!可以在500行以下清晰易懂,经过广泛评论的自定义javascript中进行大小调整,排序和过滤。.实际上,我已经看到某些花哨的input-range-slider pollyfills带有更多行代码;)
    acu

    注意事项

    我只介绍了基础知识。 Slickgrid有整个可选择/可编辑的方面,这超出了我目前的要求(对)。
    还:
  • 仅用于示例代码;还没准备好生产。 您已被警告
    =)
  • 示例似乎可以在大多数现代浏览器中使用;我已经/没有/尝试过IE; > = 11的版本可能没问题..


  • 更多信息

    尽管没有引用政策的指导方针,但对此还有很多要说的,而不是可以合理地压缩为SO答案。任何想对所有这些东西有更多了解的人都可以here where i go into a fair bit more detail

    最后一个例子

    这是最后一个有趣的例子。它使用了上述所有功能,但是可以看出,我放弃了expando行,并且有两个动态内容字段。另外,此示例使用MutationObservers来生成onPostRender事件,以替代Slickgrid native asyncPostRender column option回调:
    fiddle with it!

    我们终于得到它了。 -通往DataView-like Slickgrid extension-mod的一些方法;和所有功能,而无需在可爱的Slickgrid代码上诉诸恐怖。 yippee;)

    喔!这个职位已有几年历史了;我现在看到当前未维护的原始项目有几个分支。 IE:
    https://github.com/6pac/SlickGrid

    关于slickgrid - SlickGrid的行高可以动态更改吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/10535164/

    10-12 15:40