Reputation: 572
My question primarily revolves around this statement in the docs w.r.t. the react component:
cellEditor Params
onKeyDown Callback to tell grid a key was pressed - useful to pass control key events (tab, arrows etc) back to grid - however you do not need to call this as the grid is already listening for the events as they propagate. This is only required if you are preventing event propagation.
I understand that the cellEditor params exist as the props being passed to the react version of the component but I can't seem to find how to attach to onKeyDown as specified in the docs. In my constructor for my cellEditor the onKeyDown function exists and matches the onKeyDown
specified in cellEditorParams
inside my column definition (if it exists).
constructor(props) {
super(props);
// console.log(typeof props.onKeyDown == 'function') => 'true'
}
But it's never reached if it simply exists in the component
onKeyDown(event) {
console.log('not reached');
}
It does get invoked if I put onKeyDown={this.props.onKeyDown}
inside of a top level wrapping div around my input but it still doesn't catch the "Enter" press.
I tried listening to the cell containing my custom cell editor
this.props.eGridCell.addEventListener('keyup', (event) => {
console.log(event.keyCode === 13)
})
Which does capture the enter press but it seems to unmount when enter is pressed before I can capture the final enter press inside the field? I've seen behavior where this doesn't work too so I'm very confused.
I currently have a simple cell editor MyCellEditor that I am trying to make focus and select the next cell when enter is pressed in addition to just tab. I already have the ability to extract the rowIndex
and column
properties I need from the rowRenderer at this.props.api.rowRenderer
which I then use like:
this.props.api.rowRenderer.moveFocusToNextCell(rowIndex, column, false, false, true);
My issue is where to prevent the event propagation by default from the "Enter" press.
Below is my Cell Editor and the usage.
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;
Column definition:
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')
}
},
...
}
React:
<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')} />
Upvotes: 10
Views: 15233
Reputation: 41
found a solution to use the onKeyDown
param, so basically, we prevent all the key events
cellEditorParams: {
onKeyDown: () => undefined
}
Upvotes: 0
Reputation: 361
From v13.2.0
onwards, ag-grid has a suppressKeyboardEvent
callback that can be added to the column definition to customise the default keyboard navigation. You can find the documentation and an example here in the official docs
Upvotes: 2
Reputation: 46
What I wound up doing is changing a line in afterGuiAttached (example LargeTextCellEditor.prototype.afterGuiAttached) so that this.textarea.focus is called from a timeout. ( I didn't look further for the source of the problem yet, but this works for me for now )
LargeTextCellEditor.prototype.afterGuiAttached = function () {
if (this.focusAfterAttached) {
// this.textarea.focus();
setTimeout(()=>this.textarea.focus());
}
};
Upvotes: 0
Reputation: 405
@buddyp450, had exactly same problem and created an issue under ag-grid gitgub, however found workaround few minutes later, you can change key code to 13 in my example and works perfect :)
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();
}
}
:
Luis
Upvotes: 7
Reputation: 572
Unfortunately none of the provided answers are actually able to prevent the propagation of the native ag-grid navigation events despite stopping event propagation, immediate propagation, and preventing the default.
Somewhere in an unknown area to me with the react ag-grid the navigation elements are hijacking everything. I know this since I added a console out to the renderedCell.ts
in the source after adding the listeners as suggested in this thread and got the renderedCell's console out before the listener's console out.
I eventually went for the simply-stupid approach of forking ag-grid and tweaking the onKeyDown:
case Constants.KEY_ENTER:
// this.onEnterKeyDown();
// Whatever makes the clients happy amirite?
this.onTabKeyDown();
break;
Upvotes: 2
Reputation: 2411
the intention is you capture the 'enter' press in you cellRenderer as follows:
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} />
);
then you would prevent the propagation from the onKeyDownListener. that's how it works in javascript. if something is happening different in React then I don't know :(
Upvotes: 0
Reputation: 116
Add listener to grid containers to capture the key-down.
onGridReady: {(event) =>
event.api.gridPanel.eAllCellContainers.forEach(
function (container) {
container.addEventListener('keydown', keyDownFunc);
});
}
...
Define the listener.
function keyDownFunc(e) {
var key = event.which || event.keyCode;
if (e.keyCode == 13) { // enter = 13
// TODO: Handle event
}
}
Upvotes: 2
Reputation: 1468
I found from the documentation of ag-grid that the "grid-api" is provided by the onGridRead() callback of the React component. The following api function can help you register an event for keyPress.
addEventListener(eventType, listener)
Try something like:
onGridReady = (api)=>{
api.addEventListener('keyPress', this.keyPressEventHandlerCallback);
}
keyPressEventHandlerCallback=(e)=>{
...handler code here
}
Upvotes: 0