我们正在实现用户偏好设置,用于在网格上“即时”显示“更多”或“更少”数据。 “更多”应增加行高(每行具有相同的增加高度)。
当用户切换时,我们会更新 DataView,并使用更新后的 rowHeight 值调用 grid 上的 setOptions。然后调用 invalidate() 和 render()。
但是,行高并没有更新。 :(
请问是否有解决方案?我们应该直接通过 CSS 修改高度吗?如果可以,请提供如何进行此操作的任何提示?
我们正在实现用户偏好设置,用于在网格上“即时”显示“更多”或“更少”数据。 “更多”应增加行高(每行具有相同的增加高度)。
当用户切换时,我们会更新 DataView,并使用更新后的 rowHeight 值调用 grid 上的 setOptions。然后调用 invalidate() 和 render()。
但是,行高并没有更新。 :(
请问是否有解决方案?我们应该直接通过 CSS 修改高度吗?如果可以,请提供如何进行此操作的任何提示?
的确,根据用户交互动态更新行高是可能的。Slickgrid API提供了我们所需的一切。
因为:
这里有一个简单的演示来开始:
////////////////////////////////////////////////////////////////////////////////
//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 violet313@gmail.com ~ 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行代码。
试试吧!
顺便提一下,同样优秀的Datatables通过其API也可以(几乎)本地化提供这种方法。 &imo 这是正确的模式; &我用Slickgrid
来实现自己的东西。但它涉及一个小技巧,而且在任何情况下都*不完全符合OP要求;我声称这是可能的。
为了实现动态行高度每个单元格,我们采用类似的技巧,但我们还必须处理一些副作用:~
我们必须:
Slickgrid API
通过Grid.getItemMetadata回调接口提供基于行的样式。在下一个小例子中,在第107行,请看这个接口的onRenderRow
实现:
试试吧!
还要注意第148-150行,我调用了Slickgrid
Grid.setCellCssStyles API添加自定义dynamic-cell
css
类,将overflow
设置为visible
,以便去除每个单元格的溢出裁剪样式。
如果详细内容是静态的,则可以轻松地调整列大小。
对于响应列宽度更改(流动文本或其他内容)的详细内容,需要进行一些工作。填充行需要相应地动态添加和删除。在下一个小例子中,请查看(从第66行开始)中的addPadding
和trimPadding
函数:
试试吧!
这里还有一些工作要做。我们需要确保无论是向上还是向下排序,padding都始终连续地位于父元素下面。查看下一个 fiddle
中第136行的 comparer
:
点此体验!
几乎只需一行代码:如果是padding,那么将比较委托给父级。完成了。查看下一个 fiddle
中第192行的 pcFilter
:
点此体验!
太棒了!在不到500行的相当易读的、注释自由的自定义javascript中实现了调整大小、排序和过滤..我事实上看到有些花哨的input-range-slider polyfills的代码行数更多 ;)
<br>acu
我只涵盖了基础知识。还有整个可选/可编辑方面的内容,这超出了我的当前需求(抱歉)。
另外:
关于这个问题还有更多要说的东西,不过不能合理地压缩到一个SO
答案中 -不考虑无引用规则。有兴趣了解所有这些内容的人可以去这里,我在那里详细介绍了更多内容。
以下是一个有趣的最终示例,它利用了上述所有功能,但可以看出,我已经放弃了expando-rows,并且有两个动态内容字段。此外,值得一提的是,此示例利用MutationObservers生成onPostRender
事件作为Slickgrid原生asyncPostRender
列选项回调的替代方法:
试试吧!
这就是我们所拥有的 - 一种类似于DataView的Slickgrid扩展模块
;而且所有这些都不需要对可爱的Slickgrid代码进行可怕的黑客攻击。
这篇文章已经过时几年了;现在我看到原始项目有几个分支。即: https://github.com/6pac/SlickGrid
slick.grid.css
文件,并在其中进行所需更改。.slick-row.ui-widget-content
,
.slick-row.ui-state-active
或者您可以使用 SlickGrid 的 rowHeight
属性。var normalHeight = 25;
var expandedHeight = 100;
var columns = [
{id: "col1", name: "Column 1", field: "col1", expanded: false},
{id: "col2", name: "Column 2", field: "col2"}
];
var options = {
rowHeight: normalHeight
};
var dataView = new Slick.Data.DataView();
var grid = new Slick.Grid(element, dataView, columns, options);
grid.updateOptions = function(expanded){
var columns = grid.getColumns();
if(!expanded){
options['rowHeight'] = normalHeight;
columns[0]['expanded'] = false;
}else{
options['rowHeight'] = expandedHeight;
columns[0]['expanded'] = true;
}
grid.setOptions(options);
grid.setColumns(columns);
grid.invalidate();
grid.render();
}
看起来它工作得很好,希望对某些人有所帮助。
rawgit cdn
即将停用,因此我正在从https://6pac.github.io/SlickGrid/中获取SlickGrid JavaScript文件-如果有任何重大变更,请告诉我,我会从我的github页面提供服务。叹气。 - violet313