ContentPane 中的 dgrid - 滚动错误
Posted
技术标签:
【中文标题】ContentPane 中的 dgrid - 滚动错误【英文标题】:dgrid inside ContentPane - Scroll error 【发布时间】:2015-04-14 13:30:30 【问题描述】:我的 dgrid 有问题...。我有一个 AccordionContainer,在它的每个 ContentPane 中, 我放置了一个 dgrid。 dgrid 的问题是: 1-滚动出错:向下滚动时,在特定时刻滚动“跳过”并跳到最后,无法向上滚动并显示第一条记录。 (我在 Firebug 中看到错误 TypeError: grid._rows is null 当滚动失败时)。 2- 试图改变一个值:听起来好像没有 dgrid-datachange 事件被发出, 编辑值后无法捕获事件。
我认为这些错误与布局中的 dgrid 相关(dgrid 在 ContentPane 中,在 AccordionContainer 中)。我还包括了 DijitRegistry 扩展,但即使有了这个扩展,我也无法获得 摆脱这个错误。 我准备了重现错误的小提琴:
https://jsfiddle.net/9ax3q9jw/5/
代码:
var grid = new (declare([OnDemandGrid, DijitRegistry,Selection, Selector, Editor]))(
collection: tsStore,
selectionMode: 'none',
columns:
[
id: 'timestamp', label:'Timestamp', formatter: function (value,rowIndex)
return value[0];
,
id: 'value', label: 'Value',
get: function(value)
return value[1];
,
editor: "dijit/form/TextBox"
],
showHeader: true
);
grid.startup();
grid.on('dgrid-datachange',function(event)
alert('Change!');
console.log('Change: ' + JSON.stringify(event));
);
//Add Grid and TextArea to AccordionContainer.
var cp = new ContentPane(
title: tsStore.name,
content: grid
,"accordionContainer");
任何帮助将不胜感激, 谢谢, 天使。
【问题讨论】:
【参考方案1】:这个例子有几个问题可能会给您带来问题。
数据
小提琴中使用的存储是使用数组数组创建的,但存储旨在与对象数组一起使用。这是您看到的滚动问题的根源。每个对象中的一个属性应唯一标识该对象(“id”字段)。如果没有条目 ID,网格将无法正确跟踪数据集中的条目。数据数组可以很容易地转换为对象数组,每个条目都具有timestamp
和value
属性,并且存储可以使用timestamp
作为其ID 属性(它用来唯一标识每条记录的属性)。
var records = [];
var data = _globalData[0].data;
var item;
for (var i = 0; i < data.length; i++)
item = data[i];
records.push(
timestamp: item[0],
value: item[1]
);
var tsStore = new declare([Memory, Trackable])(
data: records,
idProperty: 'timestamp',
name: 'Temperature'
);
_t._createTimeSeriesGrids(tsStore);
以这种方式设置存储还可以简化网格列定义。使用字段名称而不是 ID 将允许网格调用 formatter
函数以及每个行对象的相应字段值。
columns: [
field: 'timestamp',
label: 'Timestamp',
formatter: function (value)
return value;
,
field: 'value',
label: 'Value',
formatter: function (value)
return value;
,
editor: "dijit/form/TextBox"
],
加载中
小提琴使用声明性小部件和 Dojo 的自动解析功能来构建页面。在这种情况下,加载器回调在执行之前不会等待解析器完成,因此当回调运行时,小部件可能还没有被实例化。
有两种方法可以处理这个问题:dojo/ready
或显式使用解析器。
parseOnLoad: true,
deps: [
...
dojo/ready,
dojo/domReady!
],
callback: function (..., ready)
ready(function ()
var _t = this;
var _globalData = [];
...
);
或
parseOnLoad: false,
deps: [
...
dojo/parser,
dojo/domReady!
],
callback: function (..., parser)
parser.parse().then(function ()
var _t = this;
var _globalData = [];
...
);
布局
向容器添加小部件时,请使用 Dijit 的方法,例如 addChild
和 set('content', ...)
。这些通常执行的操作不仅仅是向 DOM 添加小部件,例如启动子小部件。
var cp = new ContentPane(
title: tsStore.name,
content: grid
);
registry.byId('accordionContainer').addChild(cp);
而不是
var cp = new ContentPane(
title: tsStore.name,
content: grid
, "accordionContainer");
在示例代码中,甚至不需要 ContentPane,因为 dgrid 继承自 DijitRegistry——它可以直接添加为 AccordionContainer 的子项。 这也会调用网格的启动方法,因此不需要在代码中显式调用。
registry.byId('accordionContainer').addChild(grid);
在最初渲染网格后,通常还需要重新布局网格的容器,以确保其大小合适。
var handle = grid.on('dgrid-refresh-complete', function ()
registry.byId('accordionContainer').resize();
// only need to do this the first time
handle.remove();
);
【讨论】:
嗨,杰森,感谢您的回复。在商店中添加 ID 非常有效。我现在在滚动方面没有问题。但现在更新 dgrid 值的问题仍然存在......我无法“捕捉”dstore/dgrid 上的更新事件......我已经“监听”了 grid.on('dgrid-datachange') 和 tsStore。 on('update') 但似乎编辑器插件没有触发事件....有什么线索吗?提前致谢,grid.on('dgrid-datachange')
应该可以正常工作(原始示例中的侦听器对我来说工作正常)。请注意,它仅在编辑器失去焦点时触发,因此您必须在事件触发之前单击或跳出输入。
要触发商店的更新事件(对于store.on('update', ...)
),您需要为编辑器列启用autoSave
。网格编辑过程有两个部分——更新网格单元格值,并将这些更改实际保存到网格中。默认情况下,更改值只会更新网格,您必须自己调用grid.save()
。在列定义中将 autoSave
设置为 true 将导致网格在值更改时自动将更改保存到存储中。
在小提琴和实际项目中,“dgrid-datachange”对我不起作用。但我找到了解决方案......我必须使用编辑器在列的定义中添加“字段”属性,现在它可以工作了。我必须查看 Editor.js 代码,它需要一个 column.field 属性。
关于商店更新...是的,我尝试过使用 autoSave 属性。我试过用 autoSave 和没有它和 grid.save()以上是关于ContentPane 中的 dgrid - 滚动错误的主要内容,如果未能解决你的问题,请参考以下文章