9

我的问题主要围绕文档中关于反应组件的这个声明:

单元格编辑器参数

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,除了选项卡之外,我正在尝试在按下 Enter 键时聚焦并选择下一个单元格。我已经有能力从 rowRenderer 中提取我需要的属性,rowIndex然后我会在其中使用,例如:columnthis.props.api.rowRenderer

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

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

下面是我的单元格编辑器和用法。

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')} />
4

7 回答 7

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();
        }
    }
    :

路易斯

于 2016-12-03T09:13:52.573 回答
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
    }
}
于 2016-12-01T20:08:31.833 回答
2

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

使用 react ag-grid 在我未知的区域中的某个地方,导航元素正在劫持一切。我知道这一点,因为我renderedCell.ts在按照该线程中的建议添加侦听器之后在源中添加了一个控制台,并在侦听器的控制台输出之前取出了 renderCell 的控制台。

我最终采用了简单愚蠢的方法,即分叉 ag-grid 并调整 onKeyDown:

case Constants.KEY_ENTER:
  // this.onEnterKeyDown();
  // Whatever makes the clients happy amirite?
  this.onTabKeyDown();
  break;
于 2016-12-02T22:16:22.387 回答
2

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

于 2017-10-24T14:14:08.150 回答
0

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

addEventListener(eventType, listener)

尝试类似:

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

keyPressEventHandlerCallback=(e)=>{
    ...handler code here
}
于 2016-11-30T17:25:08.367 回答
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 发生了不同的事情,那么我不知道 :(

于 2016-12-02T14:45:41.160 回答
0

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

LargeTextCellEditor.prototype.afterGuiAttached = function () {
        if (this.focusAfterAttached) {
            // this.textarea.focus();
            setTimeout(()=>this.textarea.focus());
        }
    };
于 2016-12-16T13:35:52.913 回答