a suite of UI Components for development of web apps
If you have any questions, don't hesitate to contact us at support@lidorsystems.com
Advanced User Interface Controls and Components
Created: 24 January 2018
In this article, you will learn how to modify the IntegralUI TreeGrid component for Angular, so that you can edit cells in similar way like in Microsoft Excel application. Using keyboard you can navigate between cells and edit each cell individually.
If you have any questions, don't hesitate to contact us at support@lidorsystems.com
Using arrow and other keys you can navigate among the grid cells. Whenever a cell is focused, by pressing the ENTER key a text editor will popup where you can change the cell text. While text editor is still active, pressing arrow keys allows you to move to a next cell while editor is still visible.
At first, you need to enable keyboard navigation into the Grid component. This is determined by the allowFocus property, which whet set to true enables use of the keyboard. Now, you can navigate between the grid cells using the following keys:
<iui-treegrid [appRef]="applicationRef" [columns]="columns" [rows]="rows" [allowFocus]="true" [controlStyle]="gridStyle" [showFooter]="false" [allowDrag]="true" [rowHeight]="19" (beforeEdit)="onBeforeEdit($event)" #treegrid>
<ng-template let-column [iuiTemplate]="{ type: 'header' }">
{{column.headerText}}
</ng-template>
<ng-template let-cell [iuiTemplate]="{ type: 'cell' }">
<div class="treegrid-excedit-cell-content" (mouseup)="cellMouseUp($event, cell)">
<input *ngIf="cell==editCell" type="text" [(ngModel)]="cell.text" (keydown)="editorKeyDown($event)" (focus)="selectContent($event)" (blur)="editorLostFocus()" [iuiFocus]="editorFocused" [ngStyle]="{ width: getCellWidth(cell) + 'px' }" />
<span *ngIf="cell!=editCell">
{{cell.text}}
</span>
</div>
</ng-template>
</iui-treegrid>
When focus is moved to the cell close to the grid border or to a cell that is not present in the current view, the grid view is scrolled. In addition, if the focus is present on a cell that has the expand box, pressing the Left or Right arrow key will at first collapse or expand the grid row, and subsequently move the focus to the next cell.
The keyboard functionality as you can see is built-in the TreeGrid component, but you can also modify or extend it on your side.
Now, we can show an editor when a cell is focused. For this purpose, you can use a simple input element or create your own custom editor.
In this example, by pressing the ENTER key when cell is focused, the cell content is replaced by a text editor. This is based on settings in cell template where you can see a switch between editor and label, depending on whether the cell is in edit mode or not.
// Editing
public editCell: any = null;
public editorFocused: boolean = false;
private editTimeout: any = null;
private isEditActive: boolean = false;
private originalText: string = '';
selectContent(e: any){
if (e.target){
setTimeout(function(){
e.target.setSelectionRange(0, e.target.value.length);
}, 1);
}
}
cellMouseUp(e: any, cell: any){
// Show text editor on mouse up, but only on left mouse button click, when there is no active multi-selection and no menu option clicked
if (e.which == 1 && !e.ctrlKey && !e.shiftKey)
this.showEditor(cell);
}
onBeforeEdit(e: any){
e.cancel = true;
this.showEditor(e.cell, 0);
}
showEditor(cell: any, delay?: number){
if (cell){
let self = this;
self.treegrid.focusedCell = null;
if (self.editTimeout)
clearTimeout(self.editTimeout);
let editorDelay = delay == 0 ? 0 : 500;
if (!self.isEditActive)
self.editTimeout = setTimeout(function(){
self.openTextEditor(cell);
clearTimeout(self.editTimeout);
}, editorDelay);
else
self.openTextEditor(cell);
}
}
openTextEditor(cell: any){
this.originalText = cell.text;
this.isEditActive = true;
this.editCell = cell;
this.editorFocused = true;
}
closeEditor(){
this.editCell = null;
this.originalText = '';
this.editorFocused = false;
}
editorLostFocus(){
this.closeEditor();
}
<iui-treegrid [appRef]="applicationRef" [columns]="columns" [rows]="rows" [allowFocus]="true" [controlStyle]="gridStyle" [showFooter]="false" [allowDrag]="true" [rowHeight]="19" (beforeEdit)="onBeforeEdit($event)" #treegrid>
<ng-template let-column [iuiTemplate]="{ type: 'header' }">
{{column.headerText}}
</ng-template>
<ng-template let-cell [iuiTemplate]="{ type: 'cell' }">
<div class="treegrid-excedit-cell-content" (mouseup)="cellMouseUp($event, cell)">
<input *ngIf="cell==editCell" type="text" [(ngModel)]="cell.text" (keydown)="editorKeyDown($event)" (focus)="selectContent($event)" (blur)="editorLostFocus()" [iuiFocus]="editorFocused" [ngStyle]="{ width: getCellWidth(cell) + 'px' }" />
<span *ngIf="cell!=editCell">
{{cell.text}}
</span>
</div>
</ng-template>
</iui-treegrid>
Note To make sure the editor receives the input focus, you can use the iuiFocus directive. This directive sets the focus to an element to which it is applied, based on simple value: true or false.
At current state, you can edit the grid cell, by pressing the ENTER key the change is confirmed and by pressing the ESCAPE key, editor is closed and change is cancelled. Navigation among cells while editor is displayed is not yet active.
To create functionality like in Microsoft Excel, that is to navigate among cells while text editor is displayed, you need to handle the keydown event and add functionality based on which navigation key is pressed. To make it easier, TreeGrid component provides a public method named moveFocusFromCell that allows you to quickly move the focus to another cell, while keeping the text editor active.
editorKeyDown(e: any){
let self = this;
if (this.editCell){
let focusTimer: any = null;
let newCell: any = null;
switch (e.keyCode){
case 13: // ENTER
this.treegrid.focusedCell = this.editCell;
this.closeEditor();
break;
case 27: // ESCAPE
this.treegrid.focusedCell = this.editCell;
this.editCell.text = this.originalText;
this.closeEditor();
break;
case 33: // PAGE_UP
newCell = this.treegrid.moveFocusFromCell(this.editCell, 'pageup');
break;
case 34: // PAGE_DOWN
newCell = this.treegrid.moveFocusFromCell(this.editCell, 'pagedown');
break;
case 35: // END
newCell = this.treegrid.moveFocusFromCell(this.editCell, 'end');
break;
case 36: // HOME
newCell = this.treegrid.moveFocusFromCell(this.editCell, 'home');
break;
case 37: // LEFT_ARROW
newCell = this.treegrid.moveFocusFromCell(this.editCell, 'left');
break;
case 38: // UP_ARROW
newCell = this.treegrid.moveFocusFromCell(this.editCell, 'up');
break;
case 39: // RIGHT_ARROW
newCell = this.treegrid.moveFocusFromCell(this.editCell, 'right');
break;
case 40: // DOWN_ARROW
newCell = this.treegrid.moveFocusFromCell(this.editCell, 'down');
break;
}
if (newCell)
focusTimer = setTimeout(function(){
self.showEditor(newCell);
clearTimeout(focusTimer);
}, 10);
}
e.stopPropagation();
}
As a result, you have a grid where you can navigate between cells when edit mode is active or not. Switching this mode is simple, pressing the ENTER key shows the text editor while cell is focused, and pressing again the ENTER key, confirms the change and closes the editor.
In cases where you need to edit grid cells, and quickly switch the focus to another cell, is best to implement an Excel like editing. IntegralUI TreeGrid component for Angular comes with built-in functionality and public methods that allows you to implement this kind of a solution.
When keyboard navigation is enabled, you can move from one cell to another using standard keys, and edit the cell that is currently focused. Furthermore, you can use simple or custom text editor and implement your own way to navigate among the grid cells.
The comple sample code and the TreeGrid component are part of IntegralUI Web.