diff --git a/api-reference/10 UI Components/GridBase/1 Configuration/onAdaptiveDetailRowPreparing.md b/api-reference/10 UI Components/GridBase/1 Configuration/onAdaptiveDetailRowPreparing.md
new file mode 100644
index 0000000000..83ac7e53e9
--- /dev/null
+++ b/api-reference/10 UI Components/GridBase/1 Configuration/onAdaptiveDetailRowPreparing.md
@@ -0,0 +1,164 @@
+---
+id: GridBase.Options.onAdaptiveDetailRowPreparing
+type: function(e)
+default: null
+---
+---
+##### shortDescription
+A function that is executed before an adaptive detail row is rendered.
+
+##### param(e): Object
+Information about the event that caused the function's execution.
+
+##### field(e.component): {WidgetName}
+The UI component's instance.
+
+##### field(e.element): DxElement
+#include common-ref-elementparam with { element: "UI component" }
+
+##### field(e.formOptions): Object
+The properties of the [Form](/api-reference/10%20UI%20Components/dxForm/1%20Configuration '/Documentation/ApiReference/UI_Components/dxForm/Configuration/') UI component.
+
+##### field(e.model): any
+Model data. Available only if you use Knockout.
+
+---
+Adaptive detail rows display information from columns that were hidden when the UI component adapted to the screen or container size. Each adaptive detail row contains the [Form](/api-reference/10%20UI%20Components/dxForm '/Documentation/ApiReference/UI_Components/dxForm/') UI component that you can customize within the **onAdaptiveDetailRowPreparing** function using the **formOptions** object. Refer to the [Form Configuration](/api-reference/10%20UI%20Components/dxForm/1%20Configuration '/Documentation/ApiReference/UI_Components/dxForm/Configuration/') section for details on properties of the Form UI component.
+
+[note]
+
+The following Form properties cannot be specified using **formOptions**:
+
+- [template](/api-reference/10%20UI%20Components/dxForm/5%20Item%20Types/SimpleItem/template.md '/Documentation/ApiReference/UI_Components/dxForm/Item_Types/SimpleItem/#template')
+- [editorType](/api-reference/10%20UI%20Components/dxForm/5%20Item%20Types/SimpleItem/editorType.md '/Documentation/ApiReference/UI_Components/dxForm/Item_Types/SimpleItem/#editorType')
+- any [event](/api-reference/10%20UI%20Components/dxForm/4%20Events '/Documentation/ApiReference/UI_Components/dxForm/Events/') handler ([properties](/api-reference/10%20UI%20Components/Widget/1%20Configuration/onContentReady.md '/Documentation/ApiReference/UI_Components/dxForm/Configuration/#onContentReady') whose name starts with *"on..."*)
+
+[/note]
+
+---
+##### jQuery
+
+
+ $(function() {
+ $("#{widgetName}Container").dx{WidgetName}({
+ // ...
+ onAdaptiveDetailRowPreparing: function(e) {
+ e.formOptions.colCount = 2;
+ e.formOptions.colCountByScreen = {
+ xs: 2
+ }
+ e.formOptions.labelLocation = 'left';
+ }
+ })
+ })
+
+##### Angular
+
+
+ import { Dx{WidgetName}Module } from "devextreme-angular";
+ // ...
+ export class AppComponent {
+ onAdaptiveDetailRowPreparing(e) {
+ e.formOptions.colCount = 2;
+ e.formOptions.colCountByScreen = {
+ xs: 2
+ }
+ e.formOptions.labelLocation = 'left';
+ }
+ }
+ @NgModule({
+ imports: [
+ // ...
+ Dx{WidgetName}Module
+ ],
+ // ...
+ })
+
+
+
+
+
+##### Vue
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+##### React
+
+
+ import { useCallback } from 'react';
+
+ import 'devextreme/dist/css/dx.light.css';
+
+ import {WidgetName} from 'devextreme-react/{widget-name}';
+
+ export default function App() {
+ const onAdaptiveDetailRowPreparing = useCallback((e) => {
+ e.formOptions.colCount = 2;
+ e.formOptions.colCountByScreen = {
+ xs: 2
+ }
+ e.formOptions.labelLocation = 'left';
+ }, []);
+
+ return (
+ <{WidgetName}
+ onAdaptiveDetailRowPreparing={onAdaptiveDetailRowPreparing}
+ />
+ );
+ }
+
+---
+
+#####See Also#####
+- [columnHidingEnabled](/api-reference/10%20UI%20Components/GridBase/1%20Configuration/columnHidingEnabled.md '{basewidgetpath}/Configuration/#columnHidingEnabled')
+- **columns[]**.[hidingPriority](/api-reference/_hidden/GridBaseColumn/hidingPriority.md '{basewidgetpath}/Configuration/columns/#hidingPriority')
+- [Adaptability](/concepts/05%20UI%20Components/DataGrid/15%20Columns/50%20Adaptability '/Documentation/Guide/UI_Components/{WidgetName}/Columns/Adaptability/')
+- [Customize Adaptive Detail Row](/concepts/05%20UI%20Components/DataGrid/15%20Columns/50%20Adaptability/15%20Customize%20Adaptive%20Detail%20Row.md '/Documentation/Guide/UI_Components/DataGrid/Columns/Adaptability/#Customize_Adaptive_Detail_Row')
\ No newline at end of file
diff --git a/api-reference/10 UI Components/GridBase/1 Configuration/onDataErrorOccurred.md b/api-reference/10 UI Components/GridBase/1 Configuration/onDataErrorOccurred.md
new file mode 100644
index 0000000000..a462130149
--- /dev/null
+++ b/api-reference/10 UI Components/GridBase/1 Configuration/onDataErrorOccurred.md
@@ -0,0 +1,26 @@
+---
+id: GridBase.Options.onDataErrorOccurred
+type: function(e)
+default: null
+---
+---
+##### shortDescription
+A function that is executed when an error occurs in the data source.
+
+##### param(e): Object
+Information on the occurred error.
+
+##### field(e.component): {WidgetName}
+The UI component's instance.
+
+##### field(e.element): DxElement
+#include common-ref-elementparam with { element: "UI component" }
+
+##### field(e.error): Error
+The standard Error object that defines the error.
+
+##### field(e.model): any
+Model data. Available only if you use Knockout.
+
+---
+Handles errors that might occur in the data source. To obtain a human-readable description of the error in the function, use the **error.message** field.
\ No newline at end of file
diff --git a/api-reference/10 UI Components/GridBase/1 Configuration/onEditCanceled.md b/api-reference/10 UI Components/GridBase/1 Configuration/onEditCanceled.md
new file mode 100644
index 0000000000..7daa828610
--- /dev/null
+++ b/api-reference/10 UI Components/GridBase/1 Configuration/onEditCanceled.md
@@ -0,0 +1,28 @@
+---
+id: GridBase.Options.onEditCanceled
+type: function(e)
+default: null
+---
+---
+##### shortDescription
+A function that is executed after row changes are discarded.
+
+##### param(e): Object
+Information about the event that caused the function's execution.
+
+##### field(e.changes): Array
+Discarded row changes.
+
+##### field(e.component): {WidgetName}
+The UI component's instance.
+
+##### field(e.element): DxElement
+#include common-ref-elementparam with { element: "UI component" }
+
+##### field(e.model): any
+Model data. Available only if Knockout is used.
+
+---
+#include btn-open-demo with {
+ href: "https://js.devexpress.com/Demos/WidgetsGallery/Demo/DataGrid/RowEditingAndEditingEvents/"
+}
\ No newline at end of file
diff --git a/api-reference/10 UI Components/GridBase/1 Configuration/onEditCanceling.md b/api-reference/10 UI Components/GridBase/1 Configuration/onEditCanceling.md
new file mode 100644
index 0000000000..9c34fef68d
--- /dev/null
+++ b/api-reference/10 UI Components/GridBase/1 Configuration/onEditCanceling.md
@@ -0,0 +1,33 @@
+---
+id: GridBase.Options.onEditCanceling
+type: function(e)
+default: null
+---
+---
+##### shortDescription
+A function that is executed when the edit operation is canceled, but row changes are not yet discarded.
+
+##### param(e): Object
+Information about the event that caused the function's execution.
+
+##### field(e.cancel): Boolean
+Set this field to **true** if the row changes should not be discarded.
+
+##### field(e.changes): Array
+Row changes to be discarded.
+
+##### field(e.component): {WidgetName}
+The UI component's instance.
+
+##### field(e.element): DxElement
+#include common-ref-elementparam with { element: "UI component" }
+
+##### field(e.model): any
+Model data. Available only if Knockout is used.
+
+---
+An edit operation can be canceled from the UI (with the Cancel button) or programatically (with the [cancelEditData()](/api-reference/10%20UI%20Components/GridBase/3%20Methods/cancelEditData().md '{basewidgetpath}/Methods/#cancelEditData') method).
+
+#include btn-open-demo with {
+ href: "https://js.devexpress.com/Demos/WidgetsGallery/Demo/DataGrid/RowEditingAndEditingEvents/"
+}
diff --git a/api-reference/10 UI Components/GridBase/1 Configuration/onInitNewRow.md b/api-reference/10 UI Components/GridBase/1 Configuration/onInitNewRow.md
new file mode 100644
index 0000000000..e38e861d4a
--- /dev/null
+++ b/api-reference/10 UI Components/GridBase/1 Configuration/onInitNewRow.md
@@ -0,0 +1,287 @@
+---
+id: GridBase.Options.onInitNewRow
+type: function(e)
+default: null
+---
+---
+##### shortDescription
+A function that is executed before a new row is added to the UI component.
+
+##### param(e): Object
+Information about the event that caused the function's execution.
+
+##### field(e.component): {WidgetName}
+The UI component's instance.
+
+##### field(e.data): Object
+The data of the inserted row; initially empty.
+
+##### field(e.element): DxElement
+#include common-ref-elementparam with { element: "UI component" }
+
+##### field(e.model): any
+Model data. Available only if you use Knockout.
+
+##### field(e.promise): Promise
+Assign a Promise to this field to perform an asynchronous operation, such as a request to a server.
+
+---
+You can use this function to populate a new row with data. Add fields to the **data** object that correspond to the [data source](/api-reference/10%20UI%20Components/GridBase/1%20Configuration/dataSource.md '{basewidgetpath}/Configuration/#dataSource') object's fields. Note that the **data** object can omit some fields from the data source object. Add only those fields that should initialize specific cells of a new row.
+
+#include common-demobutton-named with {
+ url: "https://js.devexpress.com/Demos/WidgetsGallery/Demo/DataGrid/RowEditingAndEditingEvents/",
+ name: "DataGrid"
+}
+#include common-demobutton-named with {
+ url: "https://js.devexpress.com/Demos/WidgetsGallery/Demo/TreeList/RowEditing/",
+ name: "TreeList"
+}
+
+In the following code, the **onInitNewRow** function is used to provide default values for the new row's `ID`, `hireDate`, and `position` cells. The **promise** parameter is used to obtain values for the `ID` and `position` cell values asynchronously:
+
+---
+##### jQuery
+
+
+ $(function() {
+ $("#{widgetName}Container").dx{WidgetName}({
+ dataSource: [{
+ ID: 1,
+ hireDate: 1491821760000,
+ position: "CTO"
+ }, // ...
+ ],
+ columns: [ "ID", {
+ dataField: "hireDate",
+ dataType: "date"
+ }, "position" ],
+ onInitNewRow: function(e) {
+ e.data.hireDate = new Date();
+ e.promise = getDefaultData().done(function(data) {
+ e.data.ID = data.ID;
+ e.data.position = data.Position;
+ });
+ }
+ });
+ function getDefaultData() {
+ var promise = $.ajax({
+ // The URL returns { ID: 100, Position: "Programmer" }
+ url: "https://www.mywebsite.com/api/getDefaultData",
+ dataType: "json"
+ });
+ return promise;
+ }
+ })
+
+##### Angular
+
+
+
+
+
+
+
+
+
+ import { Component } from '@angular/core';
+
+ @Component({
+ selector: 'app-root',
+ templateUrl: './app.component.html',
+ styleUrls: ['./app.component.css']
+ })
+ export class AppComponent {
+ employees = [{
+ ID: 1,
+ hireDate: 1491821760000,
+ position: "CTO"
+ }, // ...
+ ];
+ onInitNewRow(e) {
+ e.data.hireDate = new Date();
+ e.promise = this.getDefaultData().then((data: any) => {
+ e.data.ID = data.ID;
+ e.data.position = data.Position;
+ });
+ }
+ getDefaultData() {
+ return this.httpClient.get("https://www.mywebsite.com/api/getDefaultData")
+ .toPromise()
+ .then(data => {
+ // "data" is { ID: 100, Position: "Programmer" }
+ return data;
+ })
+ .catch(error => { throw 'Data Loading Error' });
+ }
+ }
+
+
+ import { BrowserModule } from '@angular/platform-browser';
+ import { NgModule } from '@angular/core';
+ import { AppComponent } from './app.component';
+
+ import { Dx{WidgetName}Module } from 'devextreme-angular';
+
+ @NgModule({
+ declarations: [
+ AppComponent
+ ],
+ imports: [
+ BrowserModule,
+ Dx{WidgetName}Module
+ ],
+ providers: [ ],
+ bootstrap: [AppComponent]
+ })
+ export class AppModule { }
+
+##### Vue
+
+
+
+
+
+
+
+
+
+
+
+##### React
+
+
+ import React from 'react';
+
+ import 'devextreme/dist/css/dx.light.css';
+
+ import { {WidgetName}, Column } from 'devextreme-react/{widget-name}';
+ import 'whatwg-fetch';
+
+ const employees = [{
+ ID: 1,
+ hireDate: 1491821760000,
+ position: "CTO"
+ }, // ...
+ ];
+
+ class App extends React.Component {
+ constructor(props) {
+ super(props);
+ this.onInitNewRow = this.onInitNewRow.bind(this);
+ this.getDefaultData = this.getDefaultData.bind(this);
+ }
+
+ onInitNewRow(e) {
+ e.promise = this.getDefaultData().then(data => {
+ e.data.ID = data.ID;
+ e.data.position = data.Position;
+ });
+ e.data.hireDate = new Date();
+ }
+
+ getDefaultData() {
+ return fetch("https://www.mywebsite.com/api/getDefaultData")
+ .then(response => response.json())
+ .then((data) => {
+ // "data" is { ID: 100, Position: "Programmer" }
+ return data;
+ })
+ .catch(() => { throw 'Data Loading Error' });
+ }
+
+ render() {
+ return (
+ <{WidgetName} ...
+ dataSource={employees}
+ onInitNewRow={this.onInitNewRow}>
+
+
+
+ {WidgetName}>
+ );
+ }
+ }
+ export default App;
+
+##### ASP.NET MVC Controls
+
+
+ @(Html.DevExtreme().{WidgetName}()
+ .DataSource(new JS("employees"))
+ .Columns(c => {
+ c.Add().DataField("ID");
+ c.Add().DataField("hireDate")
+ .DataType(GridColumnDataType.Date);
+ c.Add().DataField("position");
+ })
+ .OnInitNewRow("onInitNewRow")
+ )
+
+
+---
diff --git a/api-reference/10 UI Components/GridBase/1 Configuration/onKeyDown.md b/api-reference/10 UI Components/GridBase/1 Configuration/onKeyDown.md
new file mode 100644
index 0000000000..82e46cf957
--- /dev/null
+++ b/api-reference/10 UI Components/GridBase/1 Configuration/onKeyDown.md
@@ -0,0 +1,144 @@
+---
+id: GridBase.Options.onKeyDown
+type: function(e)
+default: null
+---
+---
+##### shortDescription
+A function that is executed when the UI component is in focus and a key has been pressed down.
+
+##### param(e): Object
+Information about the event that caused the function's execution.
+
+##### field(e.component): {WidgetName}
+The UI component's instance.
+
+##### field(e.element): DxElement
+#include common-ref-elementparam with { element: "UI component" }
+
+##### field(e.event): event
+The event that caused the function to execute. It is a [EventObject](/api-reference/50%20Common/Object%20Structures/EventObject '/Documentation/ApiReference/Common/Object_Structures/EventObject/') or a jQuery.Event when you use jQuery. This event is based on the keydown native event.
+
+##### field(e.handled): Boolean
+Indicates whether the UI component has already handled this event.
+
+##### field(e.model): any
+Model data. Available only if you use Knockout.
+
+---
+
+The following code shows how to handle a key combination:
+
+---
+##### jQuery
+
+
+ $(function() {
+ $("#{widgetName}").dx{WidgetName}({
+ // ...
+ onKeyDown(e) {
+ if (e.event.ctrlKey && e.event.key === "Q") {
+ console.log("Ctrl + Q was pressed");
+ }
+ }
+ });
+ });
+
+##### Angular
+
+
+
+
+
+
+ import { Component } from '@angular/core';
+
+ @Component({
+ selector: 'app-root',
+ templateUrl: './app.component.html',
+ styleUrls: ['./app.component.css']
+ })
+ export class AppComponent {
+ onKeyDown(e) {
+ if (e.event.ctrlKey && e.event.key === "Q") {
+ console.log("Ctrl + Q was pressed");
+ }
+ }
+ }
+
+
+ import { BrowserModule } from '@angular/platform-browser';
+ import { NgModule } from '@angular/core';
+ import { AppComponent } from './app.component';
+
+ import { Dx{WidgetName}Module } from 'devextreme-angular';
+
+ @NgModule({
+ declarations: [
+ AppComponent
+ ],
+ imports: [
+ BrowserModule,
+ Dx{WidgetName}Module
+ ],
+ providers: [ ],
+ bootstrap: [AppComponent]
+ })
+ export class AppModule { }
+
+##### Vue
+
+
+
+
+
+
+
+
+
+##### React
+
+
+ import React from 'react';
+
+ import 'devextreme/dist/css/dx.light.css';
+
+ import {WidgetName} from 'devextreme-react/{widget-name}';
+
+ class App extends React.Component {
+ render() {
+ return (
+ <{WidgetName} ...
+ onKeyDown={this.onKeyDown}>
+ {WidgetName}>
+ );
+ }
+
+ onKeyDown(e) {
+ if (e.event.ctrlKey && e.event.key === "Q") {
+ console.log("Ctrl + Q was pressed");
+ }
+ }
+ }
+ export default App;
+
+---
\ No newline at end of file
diff --git a/api-reference/10 UI Components/GridBase/1 Configuration/onRowCollapsed.md b/api-reference/10 UI Components/GridBase/1 Configuration/onRowCollapsed.md
new file mode 100644
index 0000000000..6c0394d3e4
--- /dev/null
+++ b/api-reference/10 UI Components/GridBase/1 Configuration/onRowCollapsed.md
@@ -0,0 +1,25 @@
+---
+id: GridBase.Options.onRowCollapsed
+type: function(e)
+default: null
+---
+---
+##### shortDescription
+A function that is executed after a row is collapsed.
+
+##### param(e): Object
+Information about the event that caused the function's execution.
+
+##### field(e.component): {WidgetName}
+The UI component's instance.
+
+##### field(e.element): DxElement
+#include common-ref-elementparam with { element: "UI component" }
+
+##### field(e.key): any
+The key of the row.
+
+##### field(e.model): any
+Model data. Available only if you use Knockout.
+
+---
diff --git a/api-reference/10 UI Components/GridBase/1 Configuration/onRowCollapsing.md b/api-reference/10 UI Components/GridBase/1 Configuration/onRowCollapsing.md
new file mode 100644
index 0000000000..5768e729e3
--- /dev/null
+++ b/api-reference/10 UI Components/GridBase/1 Configuration/onRowCollapsing.md
@@ -0,0 +1,29 @@
+---
+id: GridBase.Options.onRowCollapsing
+type: function(e)
+default: null
+---
+---
+##### shortDescription
+A function that is executed before a row is collapsed.
+
+##### param(e): Object
+Information about the event that caused the function's execution.
+
+##### field(e.cancel): Boolean
+Allows you to cancel row collapsing.
+
+##### field(e.component): {WidgetName}
+The UI component's instance.
+
+##### field(e.element): DxElement
+#include common-ref-elementparam with { element: "UI component" }
+
+##### field(e.key): any
+The key of the row.
+
+##### field(e.model): any
+Model data. Available only if you use Knockout.
+
+---
+To cancel row collapsing, assign **true** to the **cancel** field of the function parameter.
\ No newline at end of file
diff --git a/api-reference/10 UI Components/GridBase/1 Configuration/onRowExpanded.md b/api-reference/10 UI Components/GridBase/1 Configuration/onRowExpanded.md
new file mode 100644
index 0000000000..355c271f3f
--- /dev/null
+++ b/api-reference/10 UI Components/GridBase/1 Configuration/onRowExpanded.md
@@ -0,0 +1,25 @@
+---
+id: GridBase.Options.onRowExpanded
+type: function(e)
+default: null
+---
+---
+##### shortDescription
+A function that is executed after a row is expanded.
+
+##### param(e): Object
+Information about the event that caused the function's execution.
+
+##### field(e.component): {WidgetName}
+The UI component's instance.
+
+##### field(e.element): DxElement
+#include common-ref-elementparam with { element: "UI component" }
+
+##### field(e.key): any
+The key of the row.
+
+##### field(e.model): any
+Model data. Available only if you use Knockout.
+
+---
diff --git a/api-reference/10 UI Components/GridBase/1 Configuration/onRowExpanding.md b/api-reference/10 UI Components/GridBase/1 Configuration/onRowExpanding.md
new file mode 100644
index 0000000000..e8a27bb95f
--- /dev/null
+++ b/api-reference/10 UI Components/GridBase/1 Configuration/onRowExpanding.md
@@ -0,0 +1,29 @@
+---
+id: GridBase.Options.onRowExpanding
+type: function(e)
+default: null
+---
+---
+##### shortDescription
+A function that is executed before a row is expanded.
+
+##### param(e): Object
+Information about the event that caused the function's execution.
+
+##### field(e.cancel): Boolean
+Allows you to cancel row expansion.
+
+##### field(e.component): {WidgetName}
+The UI component's instance.
+
+##### field(e.element): DxElement
+#include common-ref-elementparam with { element: "UI component" }
+
+##### field(e.key): any
+The key of the group or master row.
+
+##### field(e.model): any
+Model data. Available only if you use Knockout.
+
+---
+To cancel row expansion, assign **true** to the **cancel** field of the function parameter.
\ No newline at end of file
diff --git a/api-reference/10 UI Components/GridBase/1 Configuration/onRowInserted.md b/api-reference/10 UI Components/GridBase/1 Configuration/onRowInserted.md
new file mode 100644
index 0000000000..a5bf988238
--- /dev/null
+++ b/api-reference/10 UI Components/GridBase/1 Configuration/onRowInserted.md
@@ -0,0 +1,36 @@
+---
+id: GridBase.Options.onRowInserted
+type: function(e)
+default: null
+---
+---
+##### shortDescription
+A function that is executed after a new row has been inserted into the data source.
+
+##### param(e): Object
+Information about the event that caused the function's execution.
+
+##### field(e.component): {WidgetName}
+The UI component's instance.
+
+##### field(e.data): Object
+The data of the row.
+
+##### field(e.element): DxElement
+#include common-ref-elementparam with { element: "UI component" }
+
+##### field(e.error): Error
+The standard Error object defining an error that may occur during insertion.
+
+##### field(e.key): any
+The key of the row. If a field providing keys is not specified in the data source, the whole data object is considered the key.
+
+##### field(e.model): any
+Model data. Available only if you use Knockout.
+
+---
+#include btn-open-demo with {
+ href: "https://js.devexpress.com/Demos/WidgetsGallery/Demo/DataGrid/RowEditingAndEditingEvents/"
+}
+
+[note] In batch [editing mode](/api-reference/10%20UI%20Components/GridBase/1%20Configuration/editing/mode.md '{basewidgetpath}/Configuration/editing/#mode'), if several rows have been inserted, this function will be executed for each row individually.
\ No newline at end of file
diff --git a/api-reference/10 UI Components/GridBase/1 Configuration/onRowInserting.md b/api-reference/10 UI Components/GridBase/1 Configuration/onRowInserting.md
new file mode 100644
index 0000000000..7cad719afd
--- /dev/null
+++ b/api-reference/10 UI Components/GridBase/1 Configuration/onRowInserting.md
@@ -0,0 +1,45 @@
+---
+id: GridBase.Options.onRowInserting
+type: function(e)
+default: null
+---
+---
+##### shortDescription
+A function that is executed before a new row is inserted into the data source.
+
+##### param(e): Object
+Information about the event that caused the function's execution.
+
+##### field(e.cancel): Boolean | Promise
+**true**, a Promise resolved with **true**, or a rejected Promise stops row insertion.
+**false** or a Promise resolved with **false** or **undefined** continues row insertion.
+
+##### field(e.component): {WidgetName}
+The UI component's instance.
+
+##### field(e.data): Object
+The data of the row that should be inserted.
+
+##### field(e.element): DxElement
+#include common-ref-elementparam with { element: "UI component" }
+
+##### field(e.model): any
+Model data. Available only if you use Knockout.
+
+---
+
+This function allows you to intercept row insertion and perform additional actions. The following code shows how to use the function parameter's **cancel** field to prevent or continue row insertion. In this code, a Promise is assigned to this field. Row insertion continues if a user confirms it and row data validation on the server succeeds (the Promise is resolved); otherwise, row insertion is prevented (the Promise is rejected):
+
+#include datagrid-ref-confirm-action-and-validate-data with {
+ apiMember: "onRowInserting",
+ functionName: "insertRow",
+ vueAttribute: "row-inserting"
+}
+
+[note]
+
+- Do not use this function to insert data. If you need a custom insert logic, implement [CustomStore](/api-reference/30%20Data%20Layer/CustomStore '/Documentation/ApiReference/Data_Layer/CustomStore/')'s [insert](/api-reference/30%20Data%20Layer/CustomStore/1%20Configuration/update.md 'Documentation/ApiReference/Data_Layer/CustomStore/Configuration/#update') function.
+
+- In batch [editing mode](/api-reference/10%20UI%20Components/GridBase/1%20Configuration/editing/mode.md '{basewidgetpath}/Configuration/editing/#mode'), this function is executed for each row individually if several rows should be inserted.
+
+[/note]
\ No newline at end of file
diff --git a/api-reference/10 UI Components/GridBase/1 Configuration/onRowRemoved.md b/api-reference/10 UI Components/GridBase/1 Configuration/onRowRemoved.md
new file mode 100644
index 0000000000..0313211d93
--- /dev/null
+++ b/api-reference/10 UI Components/GridBase/1 Configuration/onRowRemoved.md
@@ -0,0 +1,36 @@
+---
+id: GridBase.Options.onRowRemoved
+type: function(e)
+default: null
+---
+---
+##### shortDescription
+A function that is executed after a row has been removed from the data source.
+
+##### param(e): Object
+Information about the event that caused the function's execution.
+
+##### field(e.component): {WidgetName}
+The UI component's instance.
+
+##### field(e.data): Object
+The data of the row.
+
+##### field(e.element): DxElement
+#include common-ref-elementparam with { element: "UI component" }
+
+##### field(e.error): Error
+The standard Error object defining an error that may occur during removal.
+
+##### field(e.key): any
+The key of the row. If a field providing keys is not specified in the data source, the whole data object is considered the key.
+
+##### field(e.model): any
+Model data. Available only if you use Knockout.
+
+---
+#include btn-open-demo with {
+ href: "https://js.devexpress.com/Demos/WidgetsGallery/Demo/DataGrid/RowEditingAndEditingEvents/"
+}
+
+[note] In batch [editing mode](/api-reference/10%20UI%20Components/GridBase/1%20Configuration/editing/mode.md '{basewidgetpath}/Configuration/editing/#mode'), if several rows have been removed, this function will be executed for each row individually.
\ No newline at end of file
diff --git a/api-reference/10 UI Components/GridBase/1 Configuration/onRowRemoving.md b/api-reference/10 UI Components/GridBase/1 Configuration/onRowRemoving.md
new file mode 100644
index 0000000000..acfb7c0611
--- /dev/null
+++ b/api-reference/10 UI Components/GridBase/1 Configuration/onRowRemoving.md
@@ -0,0 +1,178 @@
+---
+id: GridBase.Options.onRowRemoving
+type: function(e)
+default: null
+---
+---
+##### shortDescription
+A function that is executed before a row is removed from the data source.
+
+##### param(e): Object
+Information about the event that caused the function's execution.
+
+##### field(e.cancel): Boolean | Promise
+**true**, a Promise resolved with **true**, or a rejected Promise stops row removal.
+**false** or a Promise resolved with **false** or **undefined** continues row removal.
+
+##### field(e.component): {WidgetName}
+The UI component's instance.
+
+##### field(e.data): Object
+The data of the row that should be removed.
+
+##### field(e.element): DxElement
+#include common-ref-elementparam with { element: "UI component" }
+
+##### field(e.key): any
+The row's key.
+
+##### field(e.model): any
+Model data. Available only if you use Knockout.
+
+---
+[note] In batch [editing mode](/api-reference/10%20UI%20Components/GridBase/1%20Configuration/editing/mode.md '{basewidgetpath}/Configuration/editing/#mode'), this function is executed for each row individually if several rows should be removed.
+
+This function allows you to intercept row removal and perform additional actions. The following code shows how to use the function parameter's **cancel** field to prevent or continue removal. In this code, a Promise is assigned to this field. Removal continues if a user confirms it and row validation on the server succeeds (the Promise is resolved); otherwise, removal is prevented (the Promise is rejected):
+
+---
+#####jQuery
+
+
+ $(function(){
+ $("#{widgetName}Container").dx{WidgetName}({
+ // ...
+ onRowRemoving: function(e) {
+ var deferred = $.Deferred();
+ $.ajax({
+ url: `https://url/to/your/validation/service/${e.key}`,
+ success: function(validationResult) {
+ if (validationResult.errorText) {
+ deferred.reject(validationResult.errorText);
+ } else {
+ deferred.resolve(false);
+ }
+ },
+ error: function() {
+ deferred.reject("Data Loading Error");
+ },
+ timeout: 5000
+ });
+ e.cancel = deferred.promise();
+ },
+ })
+ })
+
+#####Angular
+
+
+ import { Dx{WidgetName}Module } from "devextreme-angular";
+ import { HttpClient, HttpClientModule, HttpParams } from "@angular/common/http";
+ // ...
+ export class AppComponent {
+ constructor(private httpClient: HttpClient) { /*...*/}
+ validateRemove(e) {
+ const isCanceled = new Promise((resolve, reject) => {
+ this.httpClient
+ .get(`https://url/to/your/validation/service/${e.key}`)
+ .toPromise()
+ .then((validationResult) => {
+ if (validationResult.errorText) {
+ reject(validationResult.errorText);
+ } else {
+ resolve(false);
+ }
+ });
+ });
+ e.cancel = isCanceled;
+ }
+ }
+
+
+
+
+
+
+ // ...
+ import { Dx{WidgetName}Module } from 'devextreme-angular';
+ import { HttpClientModule } from "@angular/common/http";
+
+ @NgModule({
+ imports: [
+ // ...
+ Dx{WidgetName}Module,
+ HttpClientModule
+ ],
+ // ...
+ })
+
+##### Vue
+
+
+
+
+
+
+
+
+##### React
+
+
+ import React from 'react';
+ import 'devextreme/dist/css/dx.light.css';
+
+ import {WidgetName}, { ... } from 'devextreme-react/{widget-name}';
+
+ function validateRemove(e) {
+ const isCanceled = new Promise((resolve, reject) => {
+ fetch(`https://url/to/your/validation/service/${e.key}`)
+ .then((validationResult) => {
+ if (validationResult.errorText) {
+ reject(validationResult.errorText);
+ } else {
+ resolve(false);
+ }
+ });
+ });
+ e.cancel = isCanceled;
+ }
+
+ function App() {
+ return (
+ <{WidgetName} ...
+ onRowRemoving={validateRemove}>
+ // ...
+ {WidgetName}>
+ );
+ }
+
+ export default App;
+
+---
\ No newline at end of file
diff --git a/api-reference/10 UI Components/GridBase/1 Configuration/onRowUpdated.md b/api-reference/10 UI Components/GridBase/1 Configuration/onRowUpdated.md
new file mode 100644
index 0000000000..27b636b5fe
--- /dev/null
+++ b/api-reference/10 UI Components/GridBase/1 Configuration/onRowUpdated.md
@@ -0,0 +1,36 @@
+---
+id: GridBase.Options.onRowUpdated
+type: function(e)
+default: null
+---
+---
+##### shortDescription
+A function that is executed after a row has been updated in the data source.
+
+##### param(e): Object
+Information about the event that caused the function's execution.
+
+##### field(e.component): {WidgetName}
+The UI component's instance.
+
+##### field(e.data): Object
+The updated data of the row.
+
+##### field(e.element): DxElement
+#include common-ref-elementparam with { element: "UI component" }
+
+##### field(e.error): Error
+The standard Error object defining an error that may occur during updating.
+
+##### field(e.key): any
+The key of the row. If a field providing keys is not specified in the data source, the whole data object is considered the key.
+
+##### field(e.model): any
+Model data. Available only if you use Knockout.
+
+---
+#include btn-open-demo with {
+ href: "https://js.devexpress.com/Demos/WidgetsGallery/Demo/DataGrid/RowEditingAndEditingEvents/"
+}
+
+[note] In batch [editing mode](/api-reference/10%20UI%20Components/GridBase/1%20Configuration/editing/mode.md '{basewidgetpath}/Configuration/editing/#mode'), if several rows have been updated, this function will be executed for each row individually.
\ No newline at end of file
diff --git a/api-reference/10 UI Components/GridBase/1 Configuration/onRowUpdating.md b/api-reference/10 UI Components/GridBase/1 Configuration/onRowUpdating.md
new file mode 100644
index 0000000000..39d9fc5d20
--- /dev/null
+++ b/api-reference/10 UI Components/GridBase/1 Configuration/onRowUpdating.md
@@ -0,0 +1,55 @@
+---
+id: GridBase.Options.onRowUpdating
+type: function(e)
+default: null
+---
+---
+##### shortDescription
+A function that is executed before a row is updated in the data source.
+
+##### param(e): Object
+Information about the event that caused the function's execution.
+
+##### field(e.cancel): Boolean | Promise
+**true**, a Promise resolved with **true**, or a rejected Promise stops row updating.
+**false** or a Promise resolved with **false** or **undefined** continues row updating.
+
+##### field(e.component): {WidgetName}
+The UI component's instance.
+
+##### field(e.element): DxElement
+#include common-ref-elementparam with { element: "UI component" }
+
+##### field(e.key): any
+The row's key.
+
+##### field(e.model): any
+Model data. Available only if you use Knockout.
+
+##### field(e.newData): Object
+The row's updated data.
+
+##### field(e.oldData): Object
+The row's old data.
+
+---
+
+This function allows you to intercept row update and perform additional actions. The following code shows how to use the function parameter's **cancel** field to prevent or continue row update. In this code, a Promise is assigned to this field. Row update continues if a user confirms it and row data validation on the server succeeds (the Promise is resolved); otherwise, row update is prevented (the Promise is rejected).
+
+#include datagrid-ref-confirm-action-and-validate-data with {
+ apiMember: "onRowUpdating",
+ functionName: "updateRow",
+ vueAttribute: "row-updating"
+}
+
+#include btn-open-github with {
+ href: "https://github.com/DevExpress-Examples/devextreme-pivotgrid-edit-data-using-datagrid"
+}
+
+[note]
+
+- You can use this function to change `e.newData` values, but do not use it to implement custom update logic. For this purpose, you can implement the [onSaving](/api-reference/10%20UI%20Components/GridBase/1%20Configuration/onSaving.md '{basewidgetpath}/Configuration/#onSaving') or [CustomStore](/api-reference/30%20Data%20Layer/CustomStore '/Documentation/ApiReference/Data_Layer/CustomStore/')'s [update](/api-reference/30%20Data%20Layer/CustomStore/1%20Configuration/update.md '/Documentation/ApiReference/Data_Layer/CustomStore/Configuration/#update') function.
+
+- In batch [editing mode](/api-reference/10%20UI%20Components/GridBase/1%20Configuration/editing/mode.md '{basewidgetpath}/Configuration/editing/#mode'), this function is executed for each row individually if several rows should be updated.
+
+[/note]
diff --git a/api-reference/10 UI Components/GridBase/1 Configuration/onRowValidating.md b/api-reference/10 UI Components/GridBase/1 Configuration/onRowValidating.md
new file mode 100644
index 0000000000..f43fd51046
--- /dev/null
+++ b/api-reference/10 UI Components/GridBase/1 Configuration/onRowValidating.md
@@ -0,0 +1,247 @@
+---
+id: GridBase.Options.onRowValidating
+type: function(e)
+default: null
+---
+---
+##### shortDescription
+A function that is executed after cells in a row are validated against [validation rules](/api-reference/_hidden/GridBaseColumn/validationRules.md '{basewidgetpath}/Configuration/columns/#validationRules').
+
+##### param(e): Object
+Information about the event that caused the function's execution.
+
+##### field(e.brokenRules): Array
+An array of broken rules. The structure of rule objects is described in the [Validation Rules](/api-reference/10%20UI%20Components/dxValidator/8%20Validation%20Rules '/Documentation/ApiReference/UI_Components/dxValidator/Validation_Rules/') section.
+
+##### field(e.component): {WidgetName}
+The UI component's instance.
+
+##### field(e.element): DxElement
+#include common-ref-elementparam with { element: "UI component" }
+
+##### field(e.errorText): String
+An error message to be displayed.
+
+##### field(e.isValid): Boolean
+Indicates whether data in all row cells satisfies the validation rules.
+
+##### field(e.key): any
+The key of the row. If a field providing keys is not specified in the data source, the whole data object is considered the key.
+
+##### field(e.model): any
+Model data. Available only if you use Knockout.
+
+##### field(e.newData): Object
+The data of the validated row after changes.
+
+##### field(e.oldData): Object
+The data of the validated row before changes.
+
+##### field(e.promise): Promise
+Assign a Promise to this field to perform an asynchronous operation, such as a request to a server.
+
+---
+Use this function to perform operations before messages about failed validation are shown. For instance, you can run additional checks and change the **isValid** function parameter to change the validation result. You can also change the **errorText** parameter to correct the error message.
+
+
+The following code illustrates how to validate an email address on the server and display an error row with a custom error text if the validation fails:
+
+---
+##### jQuery
+
+
+ $(function() {
+ $("#{widgetName}Container").dx{WidgetName}({
+ // ...
+ onRowValidating: function(e) {
+ if(e.newData.Email) {
+ e.promise = checkEmail(e.newData.Email)
+ .done(function(result) {
+ e.errorText = result.errorText;
+ e.isValid = result.isValid;
+ });
+ }
+ }
+ });
+ });
+ function checkEmail(email) {
+ return $.ajax({
+ // The url returns { errorText: "The Email address you entered already exists.", isValid: false }
+ url: "https://www.mywebsite.com/api/checkEmail",
+ dataType: "json",
+ data: { email: email }
+ });
+ }
+
+##### Angular
+
+
+
+
+
+
+ import { Component } from '@angular/core';
+ import { HttpClient, HttpParams } from '@angular/common/http';
+
+ @Component({
+ selector: 'app-root',
+ templateUrl: './app.component.html',
+ styleUrls: ['./app.component.css']
+ })
+ export class AppComponent {
+ constructor(@Inject(HttpClient) http: HttpClient) {
+ this.checkEmail = this.checkEmail.bind(this);
+ }
+ onRowValidating(e) {
+ if(e.newData.Email) {
+ e.promise = this.checkEmail(e.newData.Email)
+ .then((result: any) => {
+ // "result" is { errorText: "The Email address you entered already exists.", isValid: false }
+ e.errorText = result.errorText;
+ e.isValid = result.isValid;
+ });
+ }
+ }
+ checkEmail(email) {
+ const params = new HttpParams().set("email", email);
+ return this.http.get("https://www.mywebsite.com/api/checkEmail", { params })
+ .toPromise();
+ }
+ }
+
+
+ import { BrowserModule } from '@angular/platform-browser';
+ import { NgModule, Component } from '@angular/core';
+ import { HttpClientModule } from '@angular/common/http';
+ import { AppComponent } from './app.component';
+
+ import { Dx{WidgetName}Module } from 'devextreme-angular';
+
+ @NgModule({
+ declarations: [
+ AppComponent
+ ],
+ imports: [
+ BrowserModule,
+ HttpClientModule,
+ Dx{WidgetName}Module
+ ],
+ providers: [],
+ bootstrap: [AppComponent]
+ })
+ export class AppModule { }
+
+##### Vue
+
+
+
+
+
+
+
+
+
+##### React
+
+
+ import React from 'react';
+
+ import 'devextreme/dist/css/dx.light.css';
+
+ import {WidgetName} from 'devextreme-react/{widget-name}';
+ import 'whatwg-fetch';
+
+ class App extends React.Component {
+ constructor(props) {
+ super(props);
+ this.onRowValidating = this.onRowValidating.bind(this);
+ }
+
+ onRowValidating(e) {
+ if(e.newData.Email) {
+ e.promise = this.checkEmail(e.newData.Email)
+ .then((result: any) => {
+ // "result" is { errorText: "The Email address you entered already exists.", isValid: false }
+ e.errorText = result.errorText;
+ e.isValid = result.isValid;
+ });
+ }
+ }
+ checkEmail(email) {
+ let params = '?' + 'email=' + email;
+ return fetch("https://www.mywebsite.com/api/checkEmail${params}")
+ .toPromise();
+ }
+
+ render() {
+ return (
+ <{WidgetName} ...
+ onRowValidating={this.onRowValidating}>
+ {WidgetName}>
+ );
+ }
+ }
+ export default App;
+
+##### ASP.NET MVC Controls
+
+
+ @(Html.DevExtreme().{WidgetName}()
+ // ...
+ .OnRowValidating("onRowValidating")
+ )
+
+
+
+---
+
+[note] In batch [editing mode](/api-reference/10%20UI%20Components/GridBase/1%20Configuration/editing/mode.md '{basewidgetpath}/Configuration/editing/#mode'), if changes in several rows are committed simultaneously, this function is executed for each row.
diff --git a/api-reference/10 UI Components/GridBase/1 Configuration/onSaved.md b/api-reference/10 UI Components/GridBase/1 Configuration/onSaved.md
new file mode 100644
index 0000000000..73924bb5bc
--- /dev/null
+++ b/api-reference/10 UI Components/GridBase/1 Configuration/onSaved.md
@@ -0,0 +1,28 @@
+---
+id: GridBase.Options.onSaved
+type: function(e)
+default: null
+---
+---
+##### shortDescription
+A function that is executed after row changes are saved.
+
+##### param(e): Object
+Information about the event that caused the function's execution.
+
+##### field(e.changes): Array
+Saved changes.
+
+##### field(e.component): {WidgetName}
+The UI component's instance.
+
+##### field(e.element): DxElement
+#include common-ref-elementparam with { element: "UI component" }
+
+##### field(e.model): any
+Model data. Available only if Knockout is used.
+
+---
+#include btn-open-demo with {
+ href: "https://js.devexpress.com/Demos/WidgetsGallery/Demo/DataGrid/RowEditingAndEditingEvents/"
+}
\ No newline at end of file
diff --git a/api-reference/10 UI Components/GridBase/1 Configuration/onSaving.md b/api-reference/10 UI Components/GridBase/1 Configuration/onSaving.md
new file mode 100644
index 0000000000..55e2b00f0c
--- /dev/null
+++ b/api-reference/10 UI Components/GridBase/1 Configuration/onSaving.md
@@ -0,0 +1,37 @@
+---
+id: GridBase.Options.onSaving
+type: function(e)
+default: null
+---
+---
+##### shortDescription
+A function that is executed before pending row changes are saved.
+
+##### param(e): Object
+Information about the event that caused the function's execution.
+
+##### field(e.cancel): Boolean
+Set this field to **true** if the default saving logic should be disabled.
+
+##### field(e.changes): Array
+Pending row changes; a copy of the **editing**.[changes](/api-reference/10%20UI%20Components/GridBase/1%20Configuration/editing/changes.md '{basewidgetpath}/Configuration/editing/changes/') array.
+
+##### field(e.component): {WidgetName}
+The UI component's instance.
+
+##### field(e.element): DxElement
+#include common-ref-elementparam with { element: "UI component" }
+
+##### field(e.model): any
+Model data. Available only if Knockout is used.
+
+##### field(e.promise): Promise
+Assign a Promise to this field to perform an asynchronous operation, such as a request to a server.
+
+---
+
+A save operation can be initiated from the UI (with the Save button) or programatically (with the [saveEditData()](/api-reference/10%20UI%20Components/GridBase/3%20Methods/saveEditData().md '{basewidgetpath}/Methods/#saveEditData') method).
+
+#include btn-open-demo with {
+ href: "https://js.devexpress.com/Demos/WidgetsGallery/Demo/DataGrid/EditStateManagement/"
+}
diff --git a/api-reference/10 UI Components/GridBase/1 Configuration/onSelectionChanged.md b/api-reference/10 UI Components/GridBase/1 Configuration/onSelectionChanged.md
new file mode 100644
index 0000000000..4d832d48ad
--- /dev/null
+++ b/api-reference/10 UI Components/GridBase/1 Configuration/onSelectionChanged.md
@@ -0,0 +1,46 @@
+---
+id: GridBase.Options.onSelectionChanged
+type: function(e)
+default: null
+---
+---
+##### shortDescription
+A function that is executed after selecting a row or clearing its selection.
+
+##### param(e): Object
+Information about the event that caused the function's execution.
+
+##### field(e.component): {WidgetName}
+The UI component's instance.
+
+##### field(e.currentDeselectedRowKeys): Array
+The keys of the rows whose selection has been cleared.
+
+##### field(e.currentSelectedRowKeys): Array
+The keys of the rows that have been selected.
+
+##### field(e.element): DxElement
+#include common-ref-elementparam with { element: "UI component" }
+
+##### field(e.model): any
+Model data. Available only if you use Knockout.
+
+##### field(e.selectedRowKeys): Array
+The keys of all selected rows.
+
+##### field(e.selectedRowsData): Array