ExtJS 6:在单个网格列中使用多个编辑器的问题

mib*_*ork 7 javascript extjs extjs-grid extjs6

笔记

ExtJS版本:6.2.1.167

小提琴:fiddle.sencha.com/#view/editor&fiddle/1tlt

此功能在ExtJS 2.x中有效,并且没有任何问题.


目标

拥有一个网格(带有分组功能和单元格编辑插件),可以在一列中包含多个不同的编辑器(textfieldcombos).

网格颠覆了传统的表格系统,以便垂直显示字段名称和记录值.表头的示例如下所示:

+-------------+-----------------+-----------------+-----------------
- Field Names - Record 1 Values - Record 2 Values - Editable Column
+-------------+-----------------+-----------------+-----------------
Run Code Online (Sandbox Code Playgroud)

我们不能使用传统系统,因为有数百个字段,但只有几个记录可供比较.


这是小提琴

这是允许我使用多个编辑器的主要代码:

Ext.define('MemberCellEditing', {

  extend: 'Ext.grid.plugin.CellEditing',
  xtype: 'membercellediting',
  alias: 'plugin.membercellediting',

  getCachedEditor: function(editorId, record, column) {
    var me = this,
      editors = me.editors,
      dropDownName = record.get('dropDown');

    // If dropdown field, use dropdown name as editor id
    if (dropDownName && dropDownName != 'N') editorId = dropDownName;

    // Attempt to get editor
    var editor = editors.getByKey(editorId);

    if (!editor) {

      if (dropDownName && dropDownName != 'N') {
        // Retrieve combo
        var combo = DropDownManager.getCombo(editorId);

        // Create editor with combo
        editor = Ext.create('Ext.grid.CellEditor', {
          editorId: editorId, // Each dropdown field will have its own combo
          field: combo,
          floating: true
        });
      } else {
        // Use default editor configured for column
        editor = column.getEditor(record);
      }

      if (!editor) {
        return false;
      }

      // Allow them to specify a CellEditor in the Column
      if (!(editor instanceof Ext.grid.CellEditor)) {
        // Apply the field's editorCfg to the CellEditor config.
        // See Editor#createColumnField. A Column's editor config may
        // be used to specify the CellEditor config if it contains a field property.
        editor = new Ext.grid.CellEditor(Ext.apply({
          floating: true,
          editorId: editorId,
          field: editor
        }, editor.editorCfg));
      }

      // Add the Editor as a floating child of the grid
      // Prevent this field from being included in an Ext.form.Basic
      // collection, if the grid happens to be used inside a form
      editor.field.excludeForm = true;

      // If the editor is new to this grid, then add it to the grid, and ensure it tells us about its life cycle.
      if (editor.column !== column) {
        editor.column = column;
        column.on('removed', me.onColumnRemoved, me);
      }
      editors.add(editor);
    }

    // Inject an upward link to its owning grid even though it is not an added child.
    editor.ownerCmp = me.grid.ownerGrid;

    if (column.isTreeColumn) {
      editor.isForTree = column.isTreeColumn;
      editor.addCls(Ext.baseCSSPrefix + 'tree-cell-editor');
    }

    // Set the owning grid.
    // This needs to be kept up to date because in a Lockable assembly, an editor
    // needs to swap sides if the column is moved across.
    editor.setGrid(me.grid);

    // Keep upward pointer correct for each use - editors are shared between locking sides
    editor.editingPlugin = me;
    return editor;
  }
});
Run Code Online (Sandbox Code Playgroud)


问题

虽然我的当前代码将成功允许您在单个列中使用多个编辑器,但它会"随机"抛出错误.我随机说,因为我无法追查错误的实际原因.

错误#1 无法获取style未定义或空引用的属性

截图

在此输入图像描述

错误#2 无法获取parentNode未定义或空引用的属性

截图

在此输入图像描述

这两个错误的原因是因为el它当前引用的编辑器上的属性已被破坏,这意味着没有dom属性.


如何再现

这是我无法解决这个问题的部分原因.我无法找到复制问题的具体方法.不幸的是,我可以获得错误的方法是随机组合单击/跳转到单元格,输入数据,切换到其他单元格,切换组等...我当前通常工作的方法包括输入一些随机数据然后疯狂地点击在两个相邻的细胞之间交替聚焦.大多数情况下,获取错误所需的时间不到30秒.

我目前的理论是,有一个事件被触发,它调用某些函数,无论出于何种原因,它都会破坏编辑器的el属性.我已经尝试查看错误调用堆栈顶部的值,看起来该el属性已经被破坏了.


底线

我正在寻找有关如何追查问题的实际原因的建议.


更新

事实证明,目前有一个关于在单元格编辑器中使用组合的错误.这是另一个有类似问题的人:

https://www.sencha.com/forum/showthread.php?330959-ExtJs-6-2-CellEditing-plugin-editor-el-dom-is-null

这是错误ID:EXTJS-23330

根据Sencha支持,目前没有可用的解决方法,并且该错误仍然存​​在.


更新#2

6.0.2和6.5中存在此错误.

幸运的是,我找到了一种更一致地重现错误的方法:

  1. 将鼠标悬停在A组上5秒钟.展开组A.
  2. 将鼠标悬停在(字段1,值列)上5秒钟.
  3. 单击(字段1,值列).
  4. 等待5秒钟,然后折叠A组.
  5. 等待3秒钟,然后将鼠标悬停在B组标题上.
  6. 等待10秒钟,然后将鼠标悬停在A组标题上.
  7. 等待3秒钟,然后展开A组.
  8. 将鼠标悬停在(字段1,值列)字段上3秒钟.
  9. 将鼠标悬停在(字段1,值2列)上3秒钟.
  10. 单击(字段1,值2列).

如果没有发生错误(似乎在6.5中没有发生):

  1. 等待3秒钟,然后单击(字段1,值列).
  2. 等待1秒钟,然后再次单击(字段1,值列).

它不是100%,但比随机点击更可靠.

Dav*_*lar 0

如果没有代码和调用堆栈中的更多上下文,很难判断,但如果上面的错误 #2 仍然是当前问题的一个很好的示例,那么您应该能够将 !editor.rendered 检查的 else 更改为 read ,对else if (!editor.destroyed)吧在屏幕截图中的断点上方。