Skip to content

Commit

Permalink
Merge pull request #605 from IgniteUI/ttonev/excel-style-editing
Browse files Browse the repository at this point in the history
Ttonev/excel style editing
  • Loading branch information
dkamburov authored Oct 7, 2024
2 parents a64908f + 04a2f3c commit 2f38a58
Showing 1 changed file with 108 additions and 81 deletions.
189 changes: 108 additions & 81 deletions samples/grids/grid/editing-excel-style/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React from 'react';
import React, { useEffect, useRef, useState } from "react";
import ReactDOM from 'react-dom/client';
import './index.css';

import { IgrGridModule } from 'igniteui-react-grids';
import { IgrGridEditDoneEventArgs, IgrGridEditEventArgs, IgrGridModule } from 'igniteui-react-grids';
import { IgrGrid, IgrColumn } from 'igniteui-react-grids';
import { ComponentRenderer, WebGridDescriptionModule } from 'igniteui-react-core';
import { NwindDataItem, NwindDataItem_LocationsItem, NwindData } from './NwindData';
Expand All @@ -17,66 +17,56 @@ const mods: any[] = [
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({});
}
private grid1Ref: React.RefObject<IgrGrid> = React.createRef<IgrGrid>();
private shouldAppendValue: boolean = false;
public cancelNextEnter: boolean = false;

constructor(props: any) {
super(props);

this.grid1Ref = this.grid1Ref.bind(this);
this.webGridEditingExcelStyle = this.webGridEditingExcelStyle.bind(this);
this.handleKeyDown = this.handleKeyDown.bind(this);
this.onActiveNodeChange = this.onActiveNodeChange.bind(this);
this.gridKeyDownHandler = this.gridKeyDownHandler.bind(this);
this.cellEditEnterHandler = this.cellEditEnterHandler.bind(this);
}

componentDidMount() {
const gridElement = this.grid1Ref.current;
if (!gridElement) {
console.error("Grid element is not found.");
}
}

componentWillUnmount() {
// No need for cleanup as React handles it
}

private handleKeyDown(event: React.KeyboardEvent) {
this.webGridEditingExcelStyle(this.grid1Ref.current, event);
}

private onActiveNodeChange = (args: any) => {
this.grid1Ref.current.endEdit(true, args);
var grid = document.querySelector(".igx-grid__tbody-content") as HTMLElement;
if(grid){
grid.focus();
}
}


public render(): JSX.Element {
return (
<div className="container sample ig-typography">

<div className="container fill">
<IgrGrid
autoGenerate="false"
data={this.nwindData}
primaryKey="ProductID"
gridKeydown={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 className="container sample ig-typography">
<div className="container fill">
<IgrGrid autoGenerate="false" data={this.nwindData} primaryKey="ProductID" gridKeydown={this.gridKeyDownHandler} cellEditEnter={this.cellEditEnterHandler} onKeyDown={this.handleKeyDown} cellSelection={"single"} ref={this.grid1Ref} activeNodeChange={this.onActiveNodeChange}>
<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>
</div>
);
}

Expand All @@ -99,50 +89,87 @@ export default class Sample extends React.Component<any, any> {
return this._componentRenderer;
}

public webGridEditingExcelStyle(sender: IgrGrid, args: IgrGridKeydownEventArgs): void {
var key = (args.detail.event as any).keyCode;
var grid = args.detail.target.grid;
var activeElem = grid.navigation.activeNode;

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 (cell && !grid.crudService.cellInEditMode) {
grid.crudService.enterEditMode(cell);
cell.editValue = key;
}
private cellEditEnterHandler(grid: IgrGrid, args: IgrGridEditEventArgs) {
if(this.cancelNextEnter){
args.detail.cancel = true;
this.cancelNextEnter = false;
}
}

if (key == 13) {
var thisRow = activeElem.row;
var column = activeElem.column;
var rowInfo = grid.dataView;
private gridKeyDownHandler(grid: IgrGrid, args: IgrGridKeydownEventArgs) {
var event = args.detail.event;
var activeElem = grid.selectedCells[0];
if (event.code === 'Enter' || event.code === 'NumpadEnter') {
grid.endEdit(true, activeElem);
event.preventDefault();
if(activeElem == null) {
return;
}
this.cancelNextEnter = true;

var nextRow = this.getNextEditableRowIndex(thisRow, rowInfo, (args.detail.event as any).shiftKey);
const nextRowIndex = this.getNextEditableRowIndex(activeElem.row.index, grid.dataView, event.shiftKey);

grid.navigateTo(nextRow, column, (obj: any) => {
obj.target.activate();
grid.navigateTo(nextRowIndex, activeElem.id.columnID -1, (obj: any) => {
grid.clearCellSelection();
obj.target.activate();
});
}
}

public getNextEditableRowIndex(currentRowIndex: number, dataView: any, previous: boolean) {
private webGridEditingExcelStyle(grid: IgrGrid, args: React.KeyboardEvent): void {
var activeElem = grid.selectedCells[0];

if ((args.code >= 'Digit0' && args.code <= 'Digit9') ||
(args.code >= 'KeyA' && args.code <= 'KeyZ') ||
(args.code >= 'Numpad0' && args.code <= 'Numpad9') &&
args.code !== 'Enter' &&
args.code !== 'NumpadEnter' ) {

if (activeElem && activeElem.editMode === false) {
activeElem.editMode = true;
activeElem.editValue = args.key;
this.shouldAppendValue = true;
grid.markForCheck();
} else

if (activeElem && activeElem.editMode && this.shouldAppendValue) {
args.preventDefault();
activeElem.editValue = activeElem.editValue + args.key;
this.shouldAppendValue = false;
}

if (args.code === 'Backspace') {
if(activeElem == null) {
return;
}
const rowIndex = activeElem.row.index;
const columnKey = activeElem.column.field;

grid.data[rowIndex][columnKey] = '';

}
}
}

public getNextEditableRowIndex(currentRowIndex: number, dataView: any[], previous: boolean): number {
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));
if(previous){
for (let index = dataView.length - 1; index >= 0; index--) {
if (index < currentRowIndex && this.isEditableDataRecordAtIndex(index, dataView)) {
return index;
}
}
return -1
}
return dataView.findIndex((rec: any, index: number) => index > currentRowIndex && this.isEditableDataRecordAtIndex(index, dataView));
return dataView.findIndex((rec, index) => index > currentRowIndex && this.isEditableDataRecordAtIndex(index, dataView));
}

public isEditableDataRecordAtIndex(dataViewIndex: number, dataView: any) {
const rec = dataView[dataViewIndex];
return !rec.expression && !rec.summaries && !rec.childGridsData && !rec.detailsData;
private isEditableDataRecordAtIndex(rowIndex: number, dataView: any[]): boolean {
const rec = dataView[rowIndex];
return !rec.expression && !rec.summaries && !rec.childGridsData && !rec.detailsData
}

}

// rendering above component in the React DOM
Expand Down

0 comments on commit 2f38a58

Please sign in to comment.