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,网格将无法正确跟踪数据集中的条目。数据数组可以很容易地转换为对象数组,每个条目都具有timestampvalue 属性,并且存储可以使用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 的方法,例如 addChildset('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 - 滚动错误的主要内容,如果未能解决你的问题,请参考以下文章

dgrid设置要修复的前几列,并使其他列水平滚动

dojo dgrid 或 slick Grid 中的批量更新支持不可用

OnDemandGrid(Dgrid)不会触发请求

dojo dgrid 中的小部件

如何恢复dojo dgrid中的单个编辑行?

等效于 Jquery/Backbone.js 中的 Dgrid/Store(Dojo 工具包)