如何防止在 ag-grid-react cellEditor 组件中按下“Enter”键的事件传播?

问题描述 投票:0回答:8

我的问题主要围绕this statement in the docs w.r.t.反应成分:

cellEditor 参数

onKeyDown 回调告诉网格一个键被按下 - 有用传递 控制关键事件(制表符、箭头等)返回网格 - 但是你不这样做 需要调用它,因为网格已经在监听事件 他们传播。仅当您要阻止事件时才需要这样做 传播。

我知道 cellEditor 参数作为传递给组件的反应版本的道具存在,但我似乎无法找到如何附加到文档中指定的 onKeyDown。在我的 cellEditor 的构造函数中,onKeyDown 函数存在并匹配我的列定义中

onKeyDown
中指定的
cellEditorParams
(如果存在)。

constructor(props) {
  super(props);
  // console.log(typeof props.onKeyDown == 'function') => 'true'
}

但是如果它只是存在于组件中就永远不会达到

onKeyDown(event) {
  console.log('not reached');
}

如果我将

onKeyDown={this.props.onKeyDown}
放在我的输入周围的顶级包装 div 中,它确实会被调用,但它仍然没有捕捉到“Enter”键。

我试着听包含我的自定义单元格编辑器的单元格

this.props.eGridCell.addEventListener('keyup', (event) => {
  console.log(event.keyCode === 13)
})

哪个确实捕获了回车键,但在我可以捕获字段内的最终回车键之前按下回车键时它似乎卸载了?我看到过这不起作用的行为,所以我很困惑。

我目前有一个简单的单元格编辑器MyCellEditor,我正在尝试聚焦并在按下输入键时选择下一个单元格,而不仅仅是选项卡。我已经能够从

rowIndex
处的 rowRenderer 中提取我需要的
column
this.props.api.rowRenderer
属性,然后我会像这样使用它:

this.props.api.rowRenderer.moveFocusToNextCell(rowIndex, column, false, false, true);

我的问题是默认情况下从“Enter”键阻止事件传播的位置。

下面是我的Cell Editor和使用方法

import React from 'react';
import _ from 'lodash';

class MyCellEditor extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: props.value,
    };
  }

  getValue() {
    return this.state.value;
  }

  isPopup() {
    return false;
  }

  isCancelBeforeStart() {
    return false;
  }

  afterGuiAttached() {
    const eInput = this.input;
    eInput.focus();
    eInput.select();
  }

  onKeyDown(event) {
    // Never invoked!
  }

  onChangeListener = (e) => {
    this.setState({ value: e.target.value });
  }

  render() {
    return (
      <input
        ref={(c) => { this.input = c; }}
        className="ag-cell-edit-input"
        type="text"
        value={this.state.value}
        onChange={this.onChangeListener} />
    );
  }
}
export default MyCellEditor;

列定义:

columnDefs = [{
    headerName: 'CustomColumn',
    field: 'customField',
    editable: true,
    cellClass: 'grid-align ag-grid-shop-order-text',
    sortable: false,
    cellEditorFramework: MyCellEditor,
    // Do I need cellEditorParams?
    cellEditorParams: {
      // onKeyDown: (event) => console.log('does not output')
    }
  },
  ...
}

反应:

<AgGridReact
  columnDefs={columnDefs}
  rowData={this.props.rows}
  enableColResize="false"
  rowSelection="single"
  enableSorting="false"
  singleClickEdit="true"
  suppressMovableColumns="true"
  rowHeight="30"
  // onKeyDown also does nothing here
  onGridReady={this.onGridReady}
  onGridResize={() => console.log('grid resized')}
  onColumnResize={() => console.log('column resized')} />
reactjs ag-grid ag-grid-react
8个回答
6
投票

@buddyp450,有完全相同的问题并在 ag-grid gitgub 下创建了一个问题,但是几分钟后找到了解决方法,您可以在我的示例中将密钥代码更改为 13 并且完美运行:)

https://github.com/ceolter/ag-grid/issues/1300

export default class PATableCellEditor extends Component {
    constructor(props) {
        super(props);
        :
    }
    :
    afterGuiAttached() {
        // get ref from React component
        let eInput = this.refs.textField;
        :
        // Add a listener to 'keydown'
        let self = this;
        eInput.addEventListener('keydown', function (event) {
            self.myOnKeyDown(event)
        });
        :
    }
    :
    // Stop propagating 'left'/'right' keys
    myOnKeyDown(event) {
        let key = event.which || event.keyCode;
        if (key === 37 ||  // left
            key === 39) {  // right
            event.stopPropagation();
        }
    }
    :

路易斯


2
投票

将侦听器添加到网格容器以捕获按键。

onGridReady: {(event) =>  
    event.api.gridPanel.eAllCellContainers.forEach(
        function (container) {
             container.addEventListener('keydown', keyDownFunc);
    });
}
...

定义监听器。

function keyDownFunc(e) {
    var key = event.which || event.keyCode;
    if (e.keyCode == 13) { // enter = 13
       // TODO: Handle event
    }
}

2
投票

不幸的是,尽管停止了事件传播、立即传播并阻止了默认设置,但所提供的答案实际上都无法阻止原生 ag-grid 导航事件的传播。

对我来说,在一个未知区域的某个地方,使用 react ag-grid,导航元素正在劫持一切。我知道这一点,因为我按照此线程中的建议添加了侦听器后,在源代码中的

renderedCell.ts
中添加了一个控制台,并在侦听器的控制台退出之前获得了 renderedCell 的控制台。

我最终选择了分叉 ag-grid 并调整 onKeyDown 的简单愚蠢的方法:

case Constants.KEY_ENTER:
  // this.onEnterKeyDown();
  // Whatever makes the clients happy amirite?
  this.onTabKeyDown();
  break;

2
投票

v13.2.0
开始,ag-grid有一个
suppressKeyboardEvent
回调可以添加到列定义来自定义默认键盘导航。您可以在官方文档中找到文档和示例here


0
投票

我从ag-grid的文档中发现“grid-api”是由React组件的onGridRead()回调提供的。 下面的api函数可以帮你注册一个keyPress事件

addEventListener(eventType, listener)

尝试类似的东西:

onGridReady = (api)=>{
    api.addEventListener('keyPress', this.keyPressEventHandlerCallback);
}

keyPressEventHandlerCallback=(e)=>{
    ...handler code here
}

0
投票

目的是在您的 cellRenderer 中捕获“输入”按键,如下所示:

render() {
 return (
  <input
    ref={(c) => { this.input = c; }}
    className="ag-cell-edit-input"
    type="text"
    value={this.state.value}
    onChange={this.onChangeListener}
    onKeyDown={this.onKeyDownListener} />
);

然后你会阻止来自 onKeyDownListener 的传播。这就是它在 javascript 中的工作方式。如果 React 中发生了不同的事情,那么我不知道 :(


0
投票

我最后做的是更改 afterGuiAttached 中的一行(例如 LargeTextCellEditor.prototype.afterGuiAttached),以便从超时调用 this.textarea.focus。 (我还没有进一步寻找问题的根源,但这对我现在有用)

LargeTextCellEditor.prototype.afterGuiAttached = function () {
        if (this.focusAfterAttached) {
            // this.textarea.focus();
            setTimeout(()=>this.textarea.focus());
        }
    };

0
投票

找到了使用

onKeyDown
参数的解决方案,所以基本上,我们阻止了所有关键事件

cellEditorParams: {
  onKeyDown: () => undefined
}
© www.soinside.com 2019 - 2024. All rights reserved.