ExtJs - 对列进行排序后使用 CellEditor 的 GridPanel 中的错误

Posted

技术标签:

【中文标题】ExtJs - 对列进行排序后使用 CellEditor 的 GridPanel 中的错误【英文标题】:ExtJs - Errors in GridPanel using CellEditor after sorting a column 【发布时间】:2015-09-14 17:04:23 【问题描述】:

使用 ExtJs 5.1.0、Chrome 44.0+ 看到

我遇到一个间歇性问题,当使用 CellEditor 修改网格面板的内容时,在对其中一列进行排序后尝试编辑单元格时会引发错误。

这是堆栈跟踪:

Uncaught TypeError: Cannot read property 'parentNode' of nullExt.define.onShow @ CellEditor.js?ver=911111541:147
Ext.define.show @ Component.js?ver=911111541:5104
Ext.define.startEdit @ Editor.js?ver=911111541:333
Ext.Base.Base.addMembers.callParent @ Base.js?ver=911111541:1255
Ext.define.startEdit @ CellEditor.js?ver=911111541:132
Ext.define.showEditor @ CellEditing.js?ver=911111541:536
Ext.define.startEdit @ CellEditing.js?ver=911111541:479
Ext.define.onCellClick @ Editing.js?ver=911111541:446
fire @ Event.js?ver=911111541:387
doFireEvent @ Observable.js?ver=911111541:654
prototype.doFireEvent @ EventDomain.js?ver=911111541:293
fireEventArgs @ Observable.js?ver=911111541:587
fireEvent @ Observable.js?ver=911111541:540
Ext.define.processItemEvent @ Table.js?ver=911111541:2445
Ext.define.processUIEvent @ View.js?ver=911111541:619
Ext.define.handleEvent @ View.js?ver=911111541:562
fire @ Event.js?ver=911111541:387
Ext.define.fire @ Dom.js?ver=911111541:367
Ext.define.publish @ Dom.js?ver=911111541:339
Ext.define.doDelegatedEvent @ Dom.js?ver=911111541:398
Ext.define.onDelegatedEvent @ Dom.js?ver=911111541:379
(anonymous function) @ Function.js?ver=911111541:145

CellEditor 的 onShow 方法中的相关代码:

if (me.el.dom.parentNode !== me.renderTo) 
    me.renderTo.appendChild(me.el.dom);

网格本身是空的。它有一个与之关联的工具栏,其中包含允许您添加/复制/删除行的按钮。

这是一个代表此设置的小提琴(但是无法在小提琴中重现):

https://fiddle.sencha.com/#fiddle/top

重现的步骤大致如下:

In Chrome 44.0 (Not seen in other browsers)

1) Add a new row, fill in the fields
2) Sort on field2
3) Add three new rows
4) Add a value to one of the new rows under column for field 2
5) Sort on field2
6) Try to edit a cell in the field2 column

此时,大约有 10% 的时间会出现错误并破坏网格。如果在第 6 步问题没有重现,您可以导航到浏览器中的另一个选项卡,等待几分钟,返回网格并尝试对其进行编辑,问题就会发生。这接近 100% 的繁殖率。

请注意,这些步骤并不准确。例如,您可以改用第一列来尝试此操作。或者添加一些任意数量的行。您使用网格并尝试对其进行排序的时间越长,您看到错误的机会就越高。

如果您看到错误然后尝试再次编辑网格中的任何单元格,您将收到此错误:

Uncaught TypeError: Cannot read property 'style' of nullExt.define.setSize @ CompositeElementLite.js?ver=911111541:1674
Ext.define.setSize @ Component.js?ver=911111541:4922
Ext.define.setWidth @ Component.js?ver=911111541:5033
Ext.define.realign @ CellEditor.js?ver=911111541:282
Ext.define.startEdit @ Editor.js?ver=911111541:334
Ext.Base.Base.addMembers.callParent @ Base.js?ver=911111541:1255
Ext.define.startEdit @ CellEditor.js?ver=911111541:132
Ext.define.showEditor @ CellEditing.js?ver=911111541:536
Ext.define.startEdit @ CellEditing.js?ver=911111541:479
Ext.define.onCellClick @ Editing.js?ver=911111541:446
fire @ Event.js?ver=911111541:387
doFireEvent @ Observable.js?ver=911111541:654
prototype.doFireEvent @ EventDomain.js?ver=911111541:293
fireEventArgs @ Observable.js?ver=911111541:587
fireEvent @ Observable.js?ver=911111541:540
Ext.define.processItemEvent @ Table.js?ver=911111541:2445
Ext.define.processUIEvent @ View.js?ver=911111541:619
Ext.define.handleEvent @ View.js?ver=911111541:562
fire @ Event.js?ver=911111541:387
Ext.define.fire @ Dom.js?ver=911111541:367
Ext.define.publish @ Dom.js?ver=911111541:339
Ext.define.doDelegatedEvent @ Dom.js?ver=911111541:398
Ext.define.onDelegatedEvent @ Dom.js?ver=911111541:379(anonymous function) @ Function.js?ver=911111541:145

这是我的一些代码,可能相关也可能不相关:

在initComponent函数中,我先创建了cellediting插件:

this._cellEditing = Ext.create('Ext.grid.plugin.CellEditing', 
  clicksToEdit: 1,
disabled: this.getDisableEdit()
);

这将在稍后分配给网格本身的插件配置项:

plugins: [
  this._cellEditing
]

这是添加按钮的逻辑:

// Create a record instance through the ModelManager
var newRow = new BidPackageSchedulesGridPanel.Model();
this.getStore().add(newRow);
if (moveToRow) 
  this._cellEditing.startEdit(newRow, 1);

还有模型本身:

Ext.define('BidPackageSchedulesGridPanel.Model', 
  extend: "Ext.data.Model",
fields: [
    FieldIds.FIELD_1,
FieldIds.FIELD_2,
FieldIds.FIELD_3,
// Must specify a default value of "" in order to display null values correctly in IE.

      name: FieldIds.QUANTITY,
type: 'string',
defaultValue: ""


  ],
validators: 
    FIELD_1: [presenceValidator, 'length'],
FIELD_2: 'length',
FIELD_3: 'length',
QUANTITY: presenceValidator
  ,
identifier: 'sequential'
);

以及在网格面板的配置中初始化存储的位置:

store:  
  model: Ext.create("BidPackageSchedulesGridPanel.Model"),
data: []
,

我们使用数据提供者来加载商店数据。

前三个字段的列是使用以下逻辑创建的:

_createColumn: function(label, dataIndex) 
  var column = 
    text: Ext.String.htmlEncode(label),
dataIndex: dataIndex,
sortable: this.isJobSchedule(),
draggable: false,
flex: 1
;

if (this.isJobSchedule() || dataIndex == FieldIds.FIELD_3) 
    Ext.apply(column, 
      editor: 
        xtype: 'textfield'

    );

  return column;
,

如果我可以提供任何其他代码,请告诉我。我怀疑这是 Ext 中的一个错误,我已经向他们提交了错误报告,但如果有必要,现在解决方法就足够了。

谢谢!

【问题讨论】:

【参考方案1】:

我已经解决了这个问题,但是,它可能会产生无法预料的后果。我在 CellEditor.js 的 setGridMethod 中注意到了这条评论:

        // On view refresh, we need to copy our DOM into the detached body to prevent it from being garbage collected.
        view.on(viewListeners);

确实,我在 GarbageCollector 中设置了一个断点,发现单元格编辑器节点被错误地垃圾收集。我将垃圾收集器间隔(在 GarbageCollector.js 中)设置为 10 秒。在将数据添加到网格并排序后,十秒的窗口通过后,问题 100% 的时间是可重现的。它正在被垃圾回收,因为它的父节点为空(参见 Ext.isGarbage 中的 AND 条件)。

在CellEditor.onViewRefresh()函数中,对于被垃圾回收的组件,这个方法是没有给组件一个父节点,然后就被垃圾回收了。

我变了

     else if (!sorting) 
        Ext.getDetachedBody().dom.appendChild(dom);
    

     else 
        Ext.getDetachedBody().dom.appendChild(dom);
    

问题就解决了。我已经测试了网格编辑功能,似乎没有任何问题。

【讨论】:

在 Ext 6.0.1 中为我提供了一个解决方案,但它引导我走上正确的道路,谢谢!

以上是关于ExtJs - 对列进行排序后使用 CellEditor 的 GridPanel 中的错误的主要内容,如果未能解决你的问题,请参考以下文章

我正在使用 MUI-Data-Tables,我想在单击对列进行排序后更改标题文本颜色?

在升序和降序之间切换对列进行排序

kendoGrid中对列设置了sortable:true后,只能对当前页进行排序,怎么实现对全局所有页的数据进行排序呢?

Extjs4-在加载网格后为列提供默认排序

在 jQuery DataTables 中使用锚标记对列进行排序

使用复选框对列进行排序