The Ignite UI for Web Components Cell Editing feature in Web Components Hierarchical Grid provides an easy way to perform data manipulation operations like creating, updating, and deleting records. The IgcHierarchicalGridComponent provides you with a powerful public API which allows you to customize the way these operations are performed. The data manipulation phases are:
The editable property enables you to specify the following options:
false - the editing for the corresponding column will be disabled. This is the default value.
true - the editing for the corresponding column will be enabled.
Keep in mind that if the column is not editable, you can still modify its value through the public API exposed by the IgcHierarchicalGridComponent.
The rowEditable property enables you to specify the following options:
false - the row editing in the corresponding grid will be disabled. This is the default value.
true - the row editing in the corresponding grid will be enabled.
In the IgcHierarchicalGridComponent, if you set rowEditable property to true, and the editable property is not explicitly defined for any column, the editing will be enabled for all the columns except the primary key.
Cell and Batch Editing - in this scenario every singe modification of each cell is preserved separately and undo/ redo operations are available on cell level;
Row and Batch Editing - in this scenario the modifications are preserved on row level so undo/ redo operations will not be working for each cell that is modified but for the bunch of cell from each row.
Editing Templates
If you want to use a data type specific edit templates, you should specify the column's dataType property. So let's now see what are the default templates for each type:
For number data type, default template is using IgcInputComponent type="number", so if you try to update cell to a value which can not be parsed to a number your change is going to be discarded, and the value in the cell will be set to 0.
For dateTime data type, default template is using DateTimeEditor. This editor will give you a mask directions for the input elements part of the DateTime object.
For time - data type, default template is using TimePicker.
For currency data type, default template is using InputGroup with prefix/suffix configuration based on application or grid locale settings.
For percent data type, default template is using InputGroup with suffix element that shows a preview of the edited value in percents.
All available column data types could be found in the official Column types topic.
Event Arguments and Sequence
The grid exposes a wide array of events that provide greater control over the editing experience. These events are fired during the Row Editing and Cell Editing lifecycle - when starting, committing or canceling the editing action.
Event
Description
Arguments
Cancellable
RowEditEnter
If RowEditing is enabled, fires when a row enters edit mode
RowEditEnter - Neither Row nor Cell will enter edit mode.
CellEditEnter - Prevents entering cell edit. If rowEditable is enabled, row edit will be triggered, although cell edit will remain forbidden.
CellEdit - Allowed Cell and/or Row edit, hitting Done button or Enter won't commit the value or row transaction. Cell editing and Row editing won't be closed until Cancel button is clicked.
RowEdit - Committing cell is possible, but not the whole row. The row will stay in edit mode and the row transaction will be considered open. Hitting Done does not commit or close the row. Cancel button closes the editing process and the transaction without committing the changes.
The following sample demonstrates the editing execution sequence in action:
EXAMPLE
TS
HTML
CSS
import'igniteui-webcomponents-grids/grids/combined';
import { IgcHierarchicalGridComponent, IgcRowIslandComponent } from'igniteui-webcomponents-grids/grids';
import SingersData from'./SingersData.json';
import { IgcRowSelectionEventArgs, IgcGridEditEventArgs, IgcGridEditDoneEventArgs } from'igniteui-webcomponents-grids/grids';
import"igniteui-webcomponents-grids/grids/themes/light/bootstrap.css";
import"./index.css";
exportclassSample{
private hierarchicalGrid: IgcHierarchicalGridComponent
private rowIsland: IgcRowIslandComponent
private _bind: () =>void;
constructor() {
var hierarchicalGrid = this.hierarchicalGrid = document.getElementById('hierarchicalGrid') as IgcHierarchicalGridComponent;
this.webHierarchicalGridRendered = this.webHierarchicalGridRendered.bind(this);
this.webHierarchicalGridRowEditEnter = this.webHierarchicalGridRowEditEnter.bind(this);
this.webHierarchicalGridRowEdit = this.webHierarchicalGridRowEdit.bind(this);
this.webHierarchicalGridRowEditDone = this.webHierarchicalGridRowEditDone.bind(this);
this.webHierarchicalGridRowEditExit = this.webHierarchicalGridRowEditExit.bind(this);
this.webHierarchicalGridCellEditEnter = this.webHierarchicalGridCellEditEnter.bind(this);
this.webHierarchicalGridCellEdit = this.webHierarchicalGridCellEdit.bind(this);
this.webHierarchicalGridCellEditExit = this.webHierarchicalGridCellEditExit.bind(this);
var rowIsland = this.rowIsland = document.getElementById('rowIsland') as IgcRowIslandComponent;
this.webRowIslandGridRowEditEnter = this.webRowIslandGridRowEditEnter.bind(this);
this.webRowIslandGridRowEdit = this.webRowIslandGridRowEdit.bind(this);
this.webRowIslandGridRowEditDone = this.webRowIslandGridRowEditDone.bind(this);
this.webRowIslandGridRowEditExit = this.webRowIslandGridRowEditExit.bind(this);
this.webRowIslandGridCellEditEnter = this.webRowIslandGridCellEditEnter.bind(this);
this.webRowIslandGridCellEdit = this.webRowIslandGridCellEdit.bind(this);
this.webRowIslandGridCellEditExit = this.webRowIslandGridCellEditExit.bind(this);
this._bind = () => {
hierarchicalGrid.data = this.singersData;
hierarchicalGrid.addEventListener("rendered", this.webHierarchicalGridRendered);
hierarchicalGrid.addEventListener("rowEditEnter", this.webHierarchicalGridRowEditEnter);
hierarchicalGrid.addEventListener("rowEdit", this.webHierarchicalGridRowEdit);
hierarchicalGrid.addEventListener("rowEditDone", this.webHierarchicalGridRowEditDone);
hierarchicalGrid.addEventListener("rowEditExit", this.webHierarchicalGridRowEditExit);
hierarchicalGrid.addEventListener("cellEditEnter", this.webHierarchicalGridCellEditEnter);
hierarchicalGrid.addEventListener("cellEdit", this.webHierarchicalGridCellEdit);
hierarchicalGrid.addEventListener("cellEditExit", this.webHierarchicalGridCellEditExit);
rowIsland.addEventListener("rowEditEnter", this.webRowIslandGridRowEditEnter);
rowIsland.addEventListener("rowEdit", this.webRowIslandGridRowEdit);
rowIsland.addEventListener("rowEditDone", this.webRowIslandGridRowEditDone);
rowIsland.addEventListener("rowEditExit", this.webRowIslandGridRowEditExit);
rowIsland.addEventListener("cellEditEnter", this.webRowIslandGridCellEditEnter);
rowIsland.addEventListener("cellEdit", this.webRowIslandGridCellEdit);
rowIsland.addEventListener("cellEditExit", this.webRowIslandGridCellEditExit);
}
this._bind();
}
private _singersData: any[] = SingersData;
publicgetsingersData(): any[] {
returnthis._singersData;
}
public webHierarchicalGridRendered(args:any): void {
const hierarchicalGrid = document.getElementById("hierarchicalGrid");
hierarchicalGrid.parentElement.style.display = "flex";
const container = document.createElement("div");
container.id = "container";
container.style.height = "80vh";
container.style.width = "100%";
container.style.overflow = "auto";
hierarchicalGrid.parentElement.appendChild(container);
const title = document.createElement("span");
title.textContent = "Events execution sequence:";
container.appendChild(title);
}
public webHierarchicalGridRowEditEnter(args: CustomEvent<IgcGridEditEventArgs>): void {
let container = document.getElementById("container");
const message = document.createElement("p");
message.textContent = `Hierarchical Grid => 'rowEditEnter' with 'RowID':` + args.detail.rowID;
container.appendChild(message);
}
public webHierarchicalGridRowEdit(args: CustomEvent<IgcGridEditEventArgs>): void {
let container = document.getElementById("container");
const message = document.createElement("p");
message.textContent = `Hierarchical Grid => 'rowEdit'`;
container.appendChild(message);
}
public webHierarchicalGridRowEditDone(args: CustomEvent<IgcGridEditDoneEventArgs>): void {
let container = document.getElementById("container");
const message = document.createElement("p");
message.textContent = `Hierarchical Grid => 'rowEditDone'`;
container.appendChild(message);
}
public webHierarchicalGridRowEditExit(args: CustomEvent<IgcGridEditDoneEventArgs>): void {
let container = document.getElementById("container");
const message = document.createElement("p");
message.textContent = `Hierarchical Grid => 'rowEditExit' << End of cycle >>`;
container.appendChild(message);
}
public webHierarchicalGridCellEditEnter(args: CustomEvent<IgcGridEditEventArgs>): void {
let container = document.getElementById("container");
const message = document.createElement("p");
message.textContent = `Hierarchical Grid => 'cellEditEnter' with 'value':` + args.detail.oldValue, args.detail.cancel;
container.appendChild(message);
}
public webHierarchicalGridCellEdit(args: CustomEvent<IgcGridEditEventArgs>): void {
let container = document.getElementById("container");
const message = document.createElement("p");
message.textContent = `Hierarchical Grid => 'cellEdit' with 'newValue':` + args.detail.newValue, args.detail.cancel;
container.appendChild(message);
}
public webHierarchicalGridCellEditExit(args: CustomEvent<IgcGridEditDoneEventArgs>): void {
let container = document.getElementById("container");
const message = document.createElement("p");
message.textContent = `Hierarchical Grid => 'cellEditExit'`;
container.appendChild(message);
}
public webRowIslandGridRowEditEnter(args: CustomEvent<IgcGridEditEventArgs>): void {
let container = document.getElementById("container");
const message = document.createElement("p");
message.textContent = `Row Island => 'rowEditEnter' with 'RowID':` + args.detail.rowID;
container.appendChild(message);
}
public webRowIslandGridRowEdit(args: CustomEvent<IgcGridEditEventArgs>): void {
let container = document.getElementById("container");
const message = document.createElement("p");
message.textContent = `Row Island => 'rowEdit'`;
container.appendChild(message);
}
public webRowIslandGridRowEditDone(args: CustomEvent<IgcGridEditDoneEventArgs>): void {
let container = document.getElementById("container");
const message = document.createElement("p");
message.textContent = `Row Island => 'rowEditDone'`;
container.appendChild(message);
}
public webRowIslandGridRowEditExit(args: CustomEvent<IgcGridEditDoneEventArgs>): void {
let container = document.getElementById("container");
const message = document.createElement("p");
message.textContent = `Row Island => 'rowEditExit' << End of cycle >>`;
container.appendChild(message);
}
public webRowIslandGridCellEditEnter(args: CustomEvent<IgcGridEditEventArgs>): void {
let container = document.getElementById("container");
const message = document.createElement("p");
message.textContent = `Row Island => 'cellEditEnter' with 'value':` + args.detail.oldValue, args.detail.cancel;
container.appendChild(message);
}
public webRowIslandGridCellEdit(args: CustomEvent<IgcGridEditEventArgs>): void {
let container = document.getElementById("container");
const message = document.createElement("p");
message.textContent = `Row Island => 'cellEdit' with 'newValue':` + args.detail.newValue, args.detail.cancel;
container.appendChild(message);
}
public webRowIslandGridCellEditExit(args: CustomEvent<IgcGridEditDoneEventArgs>): void {
let container = document.getElementById("container");
const message = document.createElement("p");
message.textContent = `Row Island => 'cellEditExit'`;
container.appendChild(message);
}
}
new Sample();
ts
<!DOCTYPE html><html><head><title>Sample | Ignite UI | Web Components | infragistics</title><metacharset="UTF-8" /><linkrel="shortcut icon"href="https://static.infragistics.com/xplatform/images/browsers/wc.png" ><linkrel="stylesheet"href="https://fonts.googleapis.com/icon?family=Material+Icons" /><linkrel="stylesheet"href="https://fonts.googleapis.com/css?family=Kanit&display=swap" /><linkrel="stylesheet"href="https://fonts.googleapis.com/css?family=Titillium Web" /><linkrel="stylesheet"href="https://static.infragistics.com/xplatform/css/samples/shared.v8.css" /><linkrel="stylesheet"href="/src/index.css"type="text/css" /></head><body><divid="root"><divclass="container sample ig-typography"><divclass="container fill"><igc-hierarchical-gridauto-generate="false"primary-key="ID"id="hierarchicalGrid"name="hierarchicalGrid"id="hierarchicalGrid"row-editable="true"><igc-columnfield="Artist"header="Artist"data-type="string"></igc-column><igc-columnfield="HasGrammyAward"header="Has Grammy Award"data-type="boolean"></igc-column><igc-columnfield="Debut"header="Debut"data-type="number"></igc-column><igc-columnfield="GrammyNominations"header="Grammy Nominations"data-type="number"></igc-column><igc-columnfield="GrammyAwards"header="Grammy Awards"data-type="number"></igc-column><igc-row-islandchild-data-key="Albums"auto-generate="false"name="rowIsland"id="rowIsland"primary-key="Album"row-editable="true"><igc-columnfield="Album"header="Album"data-type="string"></igc-column><igc-columnfield="LaunchDate"header="Launch Date"data-type="date"></igc-column><igc-columnfield="BillboardReview"header="Billboard Review"data-type="string"></igc-column><igc-columnfield="USBillboard200"header="US Billboard 200"data-type="string"></igc-column></igc-row-island></igc-hierarchical-grid></div></div></div><!-- This script is needed only for parcel and it will be excluded for webpack -->
<% if (false) { %><scriptsrc="src/index.ts"></script><% } %>
</body></html>html
/* shared styles are loaded from: *//* https://static.infragistics.com/xplatform/css/samples */css
Like this sample? Get access to our complete Ignite UI for Web Components toolkit and start building your own apps in minutes. Download it for free.
Features integration
While a cell/row is in edit mode, a user may interact with the grid in many ways. The following table specifies how a certain interaction affects the current editing:
Hierarchical Grid
Filtering
Sorting
Paging
Moving
Pinning
Hiding
GroupBy
Resizing
Escape
Enter
F2
Tab
Cell Click
Add new row/Delete/Edit
Keep edit mode
✔
Exit edit mode
✔
✔
✔
✔
✔
✔
✔
✔
✔
✔
✔
✔
✔
Commit
✔
✔
✔
✔
✔
Discard
✔
✔
✔
✔
✔
✔
✔
✔
As seen from the table, all interactions, except resizing a column, will end the editing and will discard the new values. Should the new value be committed, this can be done by the developer in the corresponding feature "-ing" event.
Example how to commit new values, if user tries to sort the column while a cell/row is in edit mode: