-
Notifications
You must be signed in to change notification settings - Fork 6
Updated Excel edit style sample to functional component (React v19) #777
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: vnext
Are you sure you want to change the base?
Changes from 5 commits
77182ff
19233d1
d72d325
f1d568c
40f3a83
1ed2196
14cecca
d7dc6f5
e55ebe8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1,146 +1,133 @@ | ||||||||||||||||||
import React from 'react'; | ||||||||||||||||||
import React, { useRef, useEffect } from 'react'; | ||||||||||||||||||
import ReactDOM from 'react-dom/client'; | ||||||||||||||||||
import './index.css'; | ||||||||||||||||||
|
||||||||||||||||||
import { IgrGridModule } from 'igniteui-react-grids'; | ||||||||||||||||||
import { IgrGrid, IgrColumn } from 'igniteui-react-grids'; | ||||||||||||||||||
import { ComponentRenderer, WebGridDescriptionModule } from 'igniteui-react-core'; | ||||||||||||||||||
import { IgrGrid, IgrColumn, IgrActiveNodeChangeEventArgs } from 'igniteui-react-grids'; | ||||||||||||||||||
import NwindData from './NwindData.json'; | ||||||||||||||||||
import { IgrGridKeydownEventArgs } from 'igniteui-react-grids'; | ||||||||||||||||||
|
||||||||||||||||||
import 'igniteui-react-grids/grids/combined'; | ||||||||||||||||||
import 'igniteui-react-grids/grids/themes/light/bootstrap.css'; | ||||||||||||||||||
|
||||||||||||||||||
const mods: any[] = [ | ||||||||||||||||||
IgrGridModule | ||||||||||||||||||
]; | ||||||||||||||||||
mods.forEach((m) => m.register()); | ||||||||||||||||||
|
||||||||||||||||||
export default class Sample extends React.Component<any, any> { | ||||||||||||||||||
private grid1: IgrGrid | ||||||||||||||||||
private grid1Ref(r: IgrGrid) { | ||||||||||||||||||
this.grid1 = r; | ||||||||||||||||||
this.setState({}); | ||||||||||||||||||
} | ||||||||||||||||||
const nwindData = NwindData; | ||||||||||||||||||
|
||||||||||||||||||
constructor(props: any) { | ||||||||||||||||||
super(props); | ||||||||||||||||||
|
||||||||||||||||||
this.grid1Ref = this.grid1Ref.bind(this); | ||||||||||||||||||
this.webGridEditingExcelStyle = this.webGridEditingExcelStyle.bind(this); | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
public render(): JSX.Element { | ||||||||||||||||||
return ( | ||||||||||||||||||
<div className="container sample ig-typography"> | ||||||||||||||||||
|
||||||||||||||||||
<div className="container fill"> | ||||||||||||||||||
<IgrGrid | ||||||||||||||||||
autoGenerate={false} | ||||||||||||||||||
data={this.nwindData} | ||||||||||||||||||
primaryKey="ProductID" | ||||||||||||||||||
onGridKeydown={this.webGridEditingExcelStyle} | ||||||||||||||||||
ref={this.grid1Ref}> | ||||||||||||||||||
<IgrColumn | ||||||||||||||||||
field="ProductID" | ||||||||||||||||||
header="Product ID" | ||||||||||||||||||
editable={true} | ||||||||||||||||||
groupable={true} | ||||||||||||||||||
hidden={true}> | ||||||||||||||||||
</IgrColumn> | ||||||||||||||||||
<IgrColumn | ||||||||||||||||||
field="ProductName" | ||||||||||||||||||
header="Product Name" | ||||||||||||||||||
dataType="string" | ||||||||||||||||||
editable={true}> | ||||||||||||||||||
</IgrColumn> | ||||||||||||||||||
<IgrColumn | ||||||||||||||||||
field="UnitPrice" | ||||||||||||||||||
header="Unit Price" | ||||||||||||||||||
dataType="number" | ||||||||||||||||||
editable={true}> | ||||||||||||||||||
</IgrColumn> | ||||||||||||||||||
<IgrColumn | ||||||||||||||||||
field="QuantityPerUnit" | ||||||||||||||||||
header="Quantity Per Unit" | ||||||||||||||||||
groupable={true} | ||||||||||||||||||
dataType="string" | ||||||||||||||||||
editable={true}> | ||||||||||||||||||
</IgrColumn> | ||||||||||||||||||
<IgrColumn | ||||||||||||||||||
field="ReorderLevel" | ||||||||||||||||||
header="Reorder Level" | ||||||||||||||||||
dataType="number" | ||||||||||||||||||
groupable={true} | ||||||||||||||||||
editable={true}> | ||||||||||||||||||
</IgrColumn> | ||||||||||||||||||
</IgrGrid> | ||||||||||||||||||
</div> | ||||||||||||||||||
</div> | ||||||||||||||||||
); | ||||||||||||||||||
} | ||||||||||||||||||
const Sample = () => { | ||||||||||||||||||
const gridRef = useRef<IgrGrid>(null); | ||||||||||||||||||
const shouldAppendValue = useRef(false); | ||||||||||||||||||
|
||||||||||||||||||
private _nwindData: any[] = NwindData; | ||||||||||||||||||
public get nwindData(): any[] { | ||||||||||||||||||
return this._nwindData; | ||||||||||||||||||
} | ||||||||||||||||||
useEffect(() => { | ||||||||||||||||||
const gridElement = gridRef.current; | ||||||||||||||||||
|
||||||||||||||||||
private _componentRenderer: ComponentRenderer = null; | ||||||||||||||||||
public get renderer(): ComponentRenderer { | ||||||||||||||||||
if (this._componentRenderer == null) { | ||||||||||||||||||
this._componentRenderer = new ComponentRenderer(); | ||||||||||||||||||
var context = this._componentRenderer.context; | ||||||||||||||||||
WebGridDescriptionModule.register(context); | ||||||||||||||||||
if (!gridElement) { | ||||||||||||||||||
return undefined; | ||||||||||||||||||
} | ||||||||||||||||||
return this._componentRenderer; | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
public webGridEditingExcelStyle(args: IgrGridKeydownEventArgs): void { | ||||||||||||||||||
var key = (args.detail.event as any).keyCode; | ||||||||||||||||||
var grid = args.detail.target.grid; | ||||||||||||||||||
var activeElem = grid.navigation.activeNode; | ||||||||||||||||||
const handleKeyDown = (event: KeyboardEvent) => { | ||||||||||||||||||
var code = event.code; | ||||||||||||||||||
var activeElem = gridRef.current.selectedCells[0]; | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. removed |
||||||||||||||||||
|
||||||||||||||||||
if ((event.code >= 'Digit0' && event.code <= 'Digit9') || | ||||||||||||||||||
(event.code >= 'KeyA' && event.code <= 'KeyZ') || | ||||||||||||||||||
(event.code >= 'Numpad0' && event.code <= 'Numpad9') && | ||||||||||||||||||
event.code !== 'Enter' && event.code !== 'NumpadEnter') { | ||||||||||||||||||
|
||||||||||||||||||
if (activeElem && activeElem.editMode === false) { | ||||||||||||||||||
activeElem.editMode = true; | ||||||||||||||||||
activeElem.editValue = event.key; | ||||||||||||||||||
shouldAppendValue.current = true; | ||||||||||||||||||
gridRef.current.markForCheck(); | ||||||||||||||||||
} else | ||||||||||||||||||
|
||||||||||||||||||
if (activeElem && activeElem.editMode && shouldAppendValue.current) { | ||||||||||||||||||
event.preventDefault(); | ||||||||||||||||||
activeElem.editValue = activeElem.editValue + event.key; | ||||||||||||||||||
shouldAppendValue.current = false; | ||||||||||||||||||
} | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
if ((key >= 48 && key <= 57) || (key >= 65 && key <= 90) || (key >= 97 && key <= 122)) { | ||||||||||||||||||
var columnName = grid.getColumnByVisibleIndex(activeElem.column).field; | ||||||||||||||||||
var cell = grid.getCellByColumn(activeElem.row, columnName); | ||||||||||||||||||
if (code === 'Backspace') { | ||||||||||||||||||
if(activeElem == null) { | ||||||||||||||||||
return; | ||||||||||||||||||
} | ||||||||||||||||||
const rowIndex = activeElem.row.index; | ||||||||||||||||||
const columnKey = activeElem.column.field; | ||||||||||||||||||
|
||||||||||||||||||
gridRef.current.data[rowIndex][columnKey] = ''; | ||||||||||||||||||
gridRef.current.markForCheck(); | ||||||||||||||||||
|
||||||||||||||||||
if (cell && !grid.crudService.cellInEditMode) { | ||||||||||||||||||
grid.crudService.enterEditMode(cell); | ||||||||||||||||||
cell.editValue = key; | ||||||||||||||||||
} | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
if (key == 13) { | ||||||||||||||||||
var thisRow = activeElem.row; | ||||||||||||||||||
var column = activeElem.column; | ||||||||||||||||||
var rowInfo = grid.dataView; | ||||||||||||||||||
if (code === 'Enter' || code === 'NumpadEnter') { | ||||||||||||||||||
|
||||||||||||||||||
if(activeElem == null) { | ||||||||||||||||||
return; | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
const thisRow = activeElem.row.index; | ||||||||||||||||||
const dataView = gridRef.current.dataView; | ||||||||||||||||||
const nextRowIndex = getNextEditableRowIndex(thisRow, dataView, event.shiftKey); | ||||||||||||||||||
|
||||||||||||||||||
gridRef.current.navigateTo(nextRowIndex, activeElem.column.visibleIndex, (obj: any) => { | ||||||||||||||||||
|
||||||||||||||||||
requestAnimationFrame(() => { | ||||||||||||||||||
gridRef.current.endEdit(true, obj); | ||||||||||||||||||
gridRef.current.clearCellSelection(); | ||||||||||||||||||
obj.target.activate(); | ||||||||||||||||||
|
||||||||||||||||||
}); | ||||||||||||||||||
}); | ||||||||||||||||||
|
||||||||||||||||||
var nextRow = this.getNextEditableRowIndex(thisRow, rowInfo, (args.detail.event as any).shiftKey); | ||||||||||||||||||
} | ||||||||||||||||||
}; | ||||||||||||||||||
|
||||||||||||||||||
grid.navigateTo(nextRow, column, (obj: any) => { | ||||||||||||||||||
obj.target.activate(); | ||||||||||||||||||
grid.clearCellSelection(); | ||||||||||||||||||
}); | ||||||||||||||||||
} | ||||||||||||||||||
} | ||||||||||||||||||
gridElement.addEventListener("keydown", handleKeyDown); | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Multiple points:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. afaik onGridKeyDown does not trigger when using any key, just the ones that are in navigation and have grid functions. Have this changed in 19? Initially I had it with onGridkeyDown but I remember having issues with this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh cool, just noticed that in https://www.infragistics.com/products/ignite-ui-angular/angular/components/grid/cell-editing#angular-grid-excel-style-editing-sample Fine const grid = event.currentTarget; And that's both typed correctly and can replace the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. assigned keydown and added handler outside of useEffect |
||||||||||||||||||
|
||||||||||||||||||
return () => { | ||||||||||||||||||
gridElement.removeEventListener("keydown", handleKeyDown); | ||||||||||||||||||
}; | ||||||||||||||||||
}, []); | ||||||||||||||||||
|
||||||||||||||||||
public getNextEditableRowIndex(currentRowIndex: number, dataView: any, previous: boolean) { | ||||||||||||||||||
|
||||||||||||||||||
const getNextEditableRowIndex = (currentRowIndex: number, dataView: any, previous: boolean) => { | ||||||||||||||||||
if (currentRowIndex < 0 || (currentRowIndex === 0 && previous) || (currentRowIndex >= dataView.length - 1 && !previous)) { | ||||||||||||||||||
return currentRowIndex; | ||||||||||||||||||
} | ||||||||||||||||||
if (previous) { | ||||||||||||||||||
return dataView.findLastIndex((rec: any, index: number) => index < currentRowIndex && this.isEditableDataRecordAtIndex(index, dataView)); | ||||||||||||||||||
return dataView.findLastIndex((rec: any, index: number) => index < currentRowIndex && isEditableDataRecordAtIndex(index, dataView)); | ||||||||||||||||||
} | ||||||||||||||||||
return dataView.findIndex((rec: any, index: number) => index > currentRowIndex && this.isEditableDataRecordAtIndex(index, dataView)); | ||||||||||||||||||
} | ||||||||||||||||||
return dataView.findIndex((rec: any, index: number) => index > currentRowIndex && isEditableDataRecordAtIndex(index, dataView)); | ||||||||||||||||||
}; | ||||||||||||||||||
|
||||||||||||||||||
public isEditableDataRecordAtIndex(dataViewIndex: number, dataView: any) { | ||||||||||||||||||
const isEditableDataRecordAtIndex = (dataViewIndex: number, dataView: any) => { | ||||||||||||||||||
const rec = dataView[dataViewIndex]; | ||||||||||||||||||
return !rec.expression && !rec.summaries && !rec.childGridsData && !rec.detailsData; | ||||||||||||||||||
}; | ||||||||||||||||||
|
||||||||||||||||||
function gridEndEdit(event: IgrActiveNodeChangeEventArgs): void { | ||||||||||||||||||
gridRef.current.endEdit(true, event.detail); | ||||||||||||||||||
} | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not really sure how to proceed with this one, advise please |
||||||||||||||||||
|
||||||||||||||||||
} | ||||||||||||||||||
return ( | ||||||||||||||||||
<div className="container sample ig-typography"> | ||||||||||||||||||
<div className="container fill"> | ||||||||||||||||||
<IgrGrid | ||||||||||||||||||
autoGenerate={false} | ||||||||||||||||||
data={nwindData} | ||||||||||||||||||
primaryKey="ProductID" | ||||||||||||||||||
ref={gridRef} | ||||||||||||||||||
onActiveNodeChange={gridEndEdit} | ||||||||||||||||||
> | ||||||||||||||||||
<IgrColumn field="ProductID" header="Product ID" editable={true} groupable={true} hidden={true} /> | ||||||||||||||||||
<IgrColumn field="ProductName" header="Product Name" dataType="string" editable={true} /> | ||||||||||||||||||
<IgrColumn field="UnitPrice" header="Unit Price" dataType="number" editable={true} /> | ||||||||||||||||||
<IgrColumn field="QuantityPerUnit" header="Quantity Per Unit" groupable={true} dataType="string" editable={true} /> | ||||||||||||||||||
<IgrColumn field="ReorderLevel" header="Reorder Level" dataType="number" groupable={true} editable={true} /> | ||||||||||||||||||
</IgrGrid> | ||||||||||||||||||
</div> | ||||||||||||||||||
</div> | ||||||||||||||||||
); | ||||||||||||||||||
}; | ||||||||||||||||||
|
||||||||||||||||||
export default Sample; | ||||||||||||||||||
|
||||||||||||||||||
// rendering above component in the React DOM | ||||||||||||||||||
// Render the component | ||||||||||||||||||
const root = ReactDOM.createRoot(document.getElementById('root')); | ||||||||||||||||||
root.render(<Sample/>); | ||||||||||||||||||
root.render(<Sample />); |
Uh oh!
There was an error while loading. Please reload this page.