如何防止在 ag-grid-react cellEditor 组件中按下“Enter”键的事件传播?
Posted
技术标签:
【中文标题】如何防止在 ag-grid-react cellEditor 组件中按下“Enter”键的事件传播?【英文标题】:How to prevent event propagation for "Enter" key press in ag-grid-react cellEditor component? 【发布时间】:2017-04-08 02:34:11 【问题描述】:我的问题主要围绕文档 w.r.t 中的 this statement。反应组件:
cellEditor 参数
onKeyDown 回调告诉网格一个键被按下 - 有用传递 控制键事件(选项卡、箭头等)回到网格 - 但是你没有 需要调用它,因为网格已经在监听事件 他们传播。仅当您要阻止事件时才需要这样做 传播。
我知道 cellEditor 参数作为传递给组件的反应版本的道具而存在,但我似乎无法找到如何附加到文档中指定的 onKeyDown 。在我的 cellEditor 的构造函数中,存在 onKeyDown 函数并匹配列定义中 cellEditorParams
中指定的 onKeyDown
(如果存在)。
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 键时选择下一个单元格,而不仅仅是选项卡。我已经有能力从this.props.api.rowRenderer
的rowRenderer 中提取我需要的rowIndex
和column
属性,然后我可以像这样使用:
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') />
【问题讨论】:
【参考方案1】:@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();
:
路易斯
【讨论】:
在 6.0.1 和 7.0.0 上测试,在 6.0.1 和 7.0.0 上工作,但在 7.0.0 中导航感觉坏了。我认为这无关。我坚持使用 6.0.1。【参考方案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
【讨论】:
【参考方案3】:不幸的是,尽管停止事件传播、立即传播和阻止默认设置,但所提供的答案实际上都无法阻止原生 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;
【讨论】:
【参考方案4】:从v13.2.0
开始,ag-grid 有一个suppressKeyboardEvent
回调,可以添加到列定义中以自定义默认键盘导航。您可以找到文档和示例here in the official docs
【讨论】:
我一直在为此苦苦挣扎,由于某种原因 stopPropagation 阻止了我的编辑器正常执行其功能。所以我需要使用suppressKeyboardEvent,但它只在导航时被调用,params.editing 永远不会是真的。我不知道为什么。也许你能帮帮我?【参考方案5】:我从 ag-grid 的文档中发现“grid-api”是由 React 组件的 onGridRead() 回调提供的。 下面的api函数可以帮你注册keyPress的事件。
addEventListener(eventType, listener)
尝试类似:
onGridReady = (api)=>
api.addEventListener('keyPress', this.keyPressEventHandlerCallback);
keyPressEventHandlerCallback=(e)=>
...handler code here
【讨论】:
这不起作用,grid.api.addEventListener("keydown", (ev: any) => )
不会在按键按下时触发;而grid.api.addGlobalListener
对这种情况没有帮助。 @Luis Palacios 建议有效。【参考方案6】:
目的是您在 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 发生了不同的事情,那我不知道 :(
【讨论】:
我相信进入的媒体正在被捕获并重定向到链上更高的某个地方。它永远不会击中这个听众。【参考方案7】:我最终要做的是更改 afterGuiAttached 中的一行(例如 LargeTextCellEditor.prototype.afterGuiAttached),以便从超时调用 this.textarea.focus。 (我还没有进一步寻找问题的根源,但这对我现在有用)
LargeTextCellEditor.prototype.afterGuiAttached = function ()
if (this.focusAfterAttached)
// this.textarea.focus();
setTimeout(()=>this.textarea.focus());
;
【讨论】:
以上是关于如何防止在 ag-grid-react cellEditor 组件中按下“Enter”键的事件传播?的主要内容,如果未能解决你的问题,请参考以下文章
如何为每一行添加单独的滚动,我想在 ag-grid-react 的嵌套级别排序
Rayon 如何防止线程之间使用 RefCell<T>、Cell<T> 和 Rc<T>?