diff --git a/browser/public/index.html b/browser/public/index.html
index c808bc6d0e..d185bec069 100644
--- a/browser/public/index.html
+++ b/browser/public/index.html
@@ -483,6 +483,7 @@
─Action Strip
─Advanced Filtering Options
─Advanced Filtering Style
+ ─Batch Editing
─Binding Composite Data
─Binding Crud Data
─Binding Nested Data1
@@ -667,6 +668,7 @@
─Excel Style Filtering Style
─Filtering Options
─Filtering Style
+ ─Grid Batch Editing
─Layout Display Density
─Multi Column Headers Export
─Multi Column Headers Overview
@@ -781,6 +783,7 @@
─Filtering Options
─Filtering Style
─Finjs
+ ─Grid Batch Editing
─Keyboard Custom Navigation
─Keyboard Navigation Guide
─Layout Display Density
diff --git a/samples/grids/grid/grid-batch-editing/.prettierrc b/samples/grids/grid/grid-batch-editing/.prettierrc
new file mode 100644
index 0000000000..15a7c7c6cf
--- /dev/null
+++ b/samples/grids/grid/grid-batch-editing/.prettierrc
@@ -0,0 +1,11 @@
+{
+ "printWidth": 250,
+ "tabWidth": 4,
+ "useTabs": false,
+ "semi": true,
+ "singleQuote": false,
+ "trailingComma": "none",
+ "bracketSpacing": true,
+ "jsxBracketSameLine": false,
+ "fluid": false
+}
\ No newline at end of file
diff --git a/samples/grids/grid/grid-batch-editing/ReadMe.md b/samples/grids/grid/grid-batch-editing/ReadMe.md
new file mode 100644
index 0000000000..94d190b64b
--- /dev/null
+++ b/samples/grids/grid/grid-batch-editing/ReadMe.md
@@ -0,0 +1,56 @@
+
+
+
+This folder contains implementation of Web Components application with example of Batch Editing feature using [Grid](https://infragistics.com/webcomponentssite/components/general-getting-started.html) component.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Branches
+
+> **_NOTE:_** You should use [master](https://github.com/IgniteUI/igniteui-angular-examples/tree/master) branch of this repository if you want to run samples on your computer. Use the [vnext](https://github.com/IgniteUI/igniteui-angular-examples/tree/vnext) branch only when you want to contribute new samples to this repository.
+
+## Instructions
+
+To set up this project locally, execute these commands:
+
+```
+git clone https://github.com/IgniteUI/igniteui-wc-examples.git
+git checkout master
+cd ./igniteui-wc-examples
+cd ./samples/grids/grid/grid-batch-editing
+```
+
+open above folder in VS Code or type:
+```
+code .
+```
+
+In terminal window, run:
+
+```
+npm install
+npm run start
+```
+
+Then open http://localhost:4200/ in your browser
+
+
+## Learn More
+
+To learn more about **Ignite UI for Web Components**, check out the [Web Components documentation](https://infragistics.com/webcomponentssite/components/general-getting-started.html).
diff --git a/samples/grids/grid/grid-batch-editing/index.html b/samples/grids/grid/grid-batch-editing/index.html
new file mode 100644
index 0000000000..e09839ac19
--- /dev/null
+++ b/samples/grids/grid/grid-batch-editing/index.html
@@ -0,0 +1,145 @@
+
+
+
+ Grid Batch Editing | Ignite UI | Web Components | infragistics
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Commit
+ Discard
+ Cancel
+
+
+
+
+
+
+ <% if (false) { %><% } %>
+
+
diff --git a/samples/grids/grid/grid-batch-editing/package.json b/samples/grids/grid/grid-batch-editing/package.json
new file mode 100644
index 0000000000..8c50536621
--- /dev/null
+++ b/samples/grids/grid/grid-batch-editing/package.json
@@ -0,0 +1,61 @@
+{
+ "name": "example-ignite-ui-web-components",
+ "description": "This project provides example of using Ignite UI for Web Components",
+ "author": "Infragistics",
+ "version": "1.0.0",
+ "license": "",
+ "private": true,
+ "homepage": ".",
+ "main": "src/index.ts",
+ "scripts": {
+ "build": "npm run build:prod",
+ "build:dev": "webpack --mode development --config ./webpack.config.js --progress --color --display-error-details",
+ "build:prod": "webpack --env.NODE_ENV=production --mode production --config ./webpack.config.js --progress --color --display-error-details --bail",
+ "serve:dev": "node --max-old-space-size=8192 node_modules/webpack-dev-server/bin/webpack-dev-server.js --mode development --config ./webpack.config.js --hot --progress --open",
+ "serve:prod": "webpack-dev-server --env.NODE_ENV=production --mode production --config ./webpack.config.js --port 3000 --host 0.0.0.0 --hot --progress --open --content-base dist/",
+ "start": "npm run serve:dev",
+ "build:legacy": "npm run build:prod:legacy",
+ "build:dev:legacy": "webpack --env.legacy=true --mode development --config ./webpack.config.js --progress --color --display-error-details",
+ "build:prod:legacy": "webpack --env.NODE_ENV=production --env.legacy=true --mode production --config ./webpack.config.js --progress --color --display-error-details --bail",
+ "serve:dev:legacy": "node --max-old-space-size=8192 node_modules/webpack-dev-server/bin/webpack-dev-server.js --env.legacy=true --mode development --config ./webpack.config.js --hot --progress --open",
+ "serve:prod:legacy": "webpack-dev-server --env.NODE_ENV=production --env.legacy=true --mode production --config ./webpack.config.js --port 3000 --host 0.0.0.0 --hot --progress --open --content-base dist/",
+ "start:legacy": "npm run serve:dev:legacy"
+ },
+ "dependencies": {
+ "babel-runtime": "^6.26.0",
+ "igniteui-webcomponents": "^6.3.6",
+ "igniteui-webcomponents-core": "6.3.1",
+ "igniteui-webcomponents-grids": "6.3.0-alpha.1",
+ "igniteui-webcomponents-inputs": "6.3.1",
+ "igniteui-webcomponents-layouts": "6.3.1",
+ "lit-html": "^3.3.1",
+ "tslib": "^2.8.1"
+ },
+ "devDependencies": {
+ "@babel/cli": "^7.28.3",
+ "@babel/core": "^7.28.4",
+ "@babel/plugin-transform-class-properties": "^7.27.1",
+ "@babel/plugin-transform-class-static-block": "^7.28.3",
+ "@babel/plugin-transform-runtime": "^7.28.3",
+ "@babel/preset-env": "^7.28.3",
+ "@babel/preset-typescript": "^7.27.1",
+ "@types/source-map": "^0.5.7",
+ "babel-loader": "^10.0.0",
+ "babel-plugin-transform-custom-element-classes": "^0.1.0",
+ "css-loader": "^7.1.2",
+ "csv-loader": "^3.0.5",
+ "file-loader": "^6.2.0",
+ "fork-ts-checker-webpack-plugin": "^9.1.0",
+ "html-webpack-plugin": "^5.6.4",
+ "parcel-bundler": "^1.12.5",
+ "source-map": "^0.7.6",
+ "style-loader": "^4.0.0",
+ "tsconfig-paths-webpack-plugin": "^4.2.0",
+ "typescript": "^5.9.2",
+ "webpack": "^5.101.3",
+ "webpack-cli": "^6.0.1",
+ "webpack-dev-server": "^5.2.2",
+ "worker-loader": "^3.0.8",
+ "xml-loader": "^1.2.1"
+ }
+}
diff --git a/samples/grids/grid/grid-batch-editing/sandbox.config.json b/samples/grids/grid/grid-batch-editing/sandbox.config.json
new file mode 100644
index 0000000000..52c7875103
--- /dev/null
+++ b/samples/grids/grid/grid-batch-editing/sandbox.config.json
@@ -0,0 +1,6 @@
+{
+ "infiniteLoopProtection": false,
+ "hardReloadOnChange": false,
+ "view": "browser",
+ "template": "parcel"
+}
\ No newline at end of file
diff --git a/samples/grids/grid/grid-batch-editing/src/NwindData.json b/samples/grids/grid/grid-batch-editing/src/NwindData.json
new file mode 100644
index 0000000000..c00b03ec8d
--- /dev/null
+++ b/samples/grids/grid/grid-batch-editing/src/NwindData.json
@@ -0,0 +1,458 @@
+[
+ {
+ "ProductID": 1,
+ "ProductName": "Chai",
+ "SupplierID": 1,
+ "CategoryID": 1,
+ "QuantityPerUnit": "10 boxes x 20 bags",
+ "UnitPrice": 18,
+ "UnitsInStock": 39,
+ "UnitsOnOrder": 30,
+ "ReorderLevel": 10,
+ "Discontinued": false,
+ "OrderDate": "2012-02-12",
+ "Rating": 5,
+ "Locations": [
+ {
+ "Shop": "Fun-Tasty Co.",
+ "LastInventory": "2018-06-12"
+ },
+ {
+ "Shop": "Farmer Market",
+ "LastInventory": "2018-04-04"
+ }
+ ]
+ },
+ {
+ "ProductID": 2,
+ "ProductName": "Chang",
+ "SupplierID": 1,
+ "CategoryID": 1,
+ "QuantityPerUnit": "24 - 12 oz bottles",
+ "UnitPrice": 19,
+ "UnitsInStock": 17,
+ "UnitsOnOrder": 40,
+ "ReorderLevel": 25,
+ "Discontinued": true,
+ "OrderDate": "2003-03-17",
+ "Rating": 5,
+ "Locations": [
+ {
+ "Shop": "Super Market",
+ "LastInventory": "2018-09-09"
+ }
+ ]
+ },
+ {
+ "ProductID": 3,
+ "ProductName": "Aniseed Syrup",
+ "SupplierID": 1,
+ "CategoryID": 2,
+ "QuantityPerUnit": "12 - 550 ml bottles",
+ "UnitPrice": 10,
+ "UnitsInStock": 13,
+ "UnitsOnOrder": 70,
+ "ReorderLevel": 25,
+ "Discontinued": false,
+ "OrderDate": "2006-03-17",
+ "Rating": 3,
+ "Locations": [
+ {
+ "Shop": "Farmer Market",
+ "LastInventory": "2018-04-04"
+ },
+ {
+ "Shop": "Street Market",
+ "LastInventory": "2018-12-12"
+ },
+ {
+ "Shop": "24/7 Market",
+ "LastInventory": "2018-11-11"
+ }
+ ]
+ },
+ {
+ "ProductID": 4,
+ "ProductName": "Chef Antons Cajun Seasoning",
+ "SupplierID": 2,
+ "CategoryID": 2,
+ "QuantityPerUnit": "48 - 6 oz jars",
+ "UnitPrice": 22,
+ "UnitsInStock": 53,
+ "UnitsOnOrder": 30,
+ "ReorderLevel": 0,
+ "Discontinued": false,
+ "OrderDate": "2016-03-17",
+ "Rating": 3,
+ "Locations": [
+ {
+ "Shop": "Fun-Tasty Co.",
+ "LastInventory": "2018-06-12"
+ },
+ {
+ "Shop": "Farmer Market",
+ "LastInventory": "2018-04-04"
+ },
+ {
+ "Shop": "Street Market",
+ "LastInventory": "2018-12-12"
+ }
+ ]
+ },
+ {
+ "ProductID": 5,
+ "ProductName": "Chef Antons Gumbo Mix",
+ "SupplierID": 2,
+ "CategoryID": 2,
+ "QuantityPerUnit": "36 boxes",
+ "UnitPrice": 21.35,
+ "UnitsInStock": 0,
+ "UnitsOnOrder": 30,
+ "ReorderLevel": 0,
+ "Discontinued": true,
+ "OrderDate": "2011-11-11",
+ "Rating": 5,
+ "Locations": [
+ {
+ "Shop": "Super Market",
+ "LastInventory": "2018-09-09"
+ }
+ ]
+ },
+ {
+ "ProductID": 6,
+ "ProductName": "Grandmas Boysenberry Spread",
+ "SupplierID": 3,
+ "CategoryID": 2,
+ "QuantityPerUnit": "12 - 8 oz jars",
+ "UnitPrice": 25,
+ "UnitsInStock": 0,
+ "UnitsOnOrder": 30,
+ "ReorderLevel": 25,
+ "Discontinued": false,
+ "OrderDate": "2017-12-17",
+ "Rating": 4,
+ "Locations": [
+ {
+ "Shop": "Super Market",
+ "LastInventory": "2018-09-09"
+ }
+ ]
+ },
+ {
+ "ProductID": 7,
+ "ProductName": "Uncle Bobs Organic Dried Pears",
+ "SupplierID": 3,
+ "CategoryID": 7,
+ "QuantityPerUnit": "12 - 1 lb pkgs.",
+ "UnitPrice": 30,
+ "UnitsInStock": 150,
+ "UnitsOnOrder": 30,
+ "ReorderLevel": 10,
+ "Discontinued": false,
+ "OrderDate": "2016-07-17",
+ "Rating": 5,
+ "Locations": [
+ {
+ "Shop": "Fun-Tasty Co.",
+ "LastInventory": "2018-06-12"
+ },
+ {
+ "Shop": "Farmer Market",
+ "LastInventory": "2018-04-04"
+ },
+ {
+ "Shop": "Street Market",
+ "LastInventory": "2018-12-12"
+ }
+ ]
+ },
+ {
+ "ProductID": 8,
+ "ProductName": "Northwoods Cranberry Sauce",
+ "SupplierID": 3,
+ "CategoryID": 2,
+ "QuantityPerUnit": "12 - 12 oz jars",
+ "UnitPrice": 40,
+ "UnitsInStock": 6,
+ "UnitsOnOrder": 30,
+ "ReorderLevel": 0,
+ "Discontinued": false,
+ "OrderDate": "2018-01-17",
+ "Rating": 4,
+ "Locations": [
+ {
+ "Shop": "Fun-Tasty Co.",
+ "LastInventory": "2018-06-12"
+ },
+ {
+ "Shop": "Farmer Market",
+ "LastInventory": "2018-04-04"
+ }
+ ]
+ },
+ {
+ "ProductID": 9,
+ "ProductName": "Mishi Kobe Niku",
+ "SupplierID": 4,
+ "CategoryID": 6,
+ "QuantityPerUnit": "18 - 500 g pkgs.",
+ "UnitPrice": 97,
+ "UnitsInStock": 29,
+ "UnitsOnOrder": 30,
+ "ReorderLevel": 0,
+ "Discontinued": true,
+ "OrderDate": "2010-02-17",
+ "Rating": 4,
+ "Locations": [
+ {
+ "Shop": "Farmer Market",
+ "LastInventory": "2018-04-04"
+ }
+ ]
+ },
+ {
+ "ProductID": 10,
+ "ProductName": "Ikura",
+ "SupplierID": 4,
+ "CategoryID": 8,
+ "QuantityPerUnit": "12 - 200 ml jars",
+ "UnitPrice": 31,
+ "UnitsInStock": 31,
+ "UnitsOnOrder": 30,
+ "ReorderLevel": 0,
+ "Discontinued": false,
+ "OrderDate": "2008-05-17",
+ "Rating": 3,
+ "Locations": [
+ {
+ "Shop": "Wall Market",
+ "LastInventory": "2018-12-06"
+ }
+ ]
+ },
+ {
+ "ProductID": 11,
+ "ProductName": "Queso Cabrales",
+ "SupplierID": 5,
+ "CategoryID": 4,
+ "QuantityPerUnit": "1 kg pkg.",
+ "UnitPrice": 21,
+ "UnitsInStock": 22,
+ "UnitsOnOrder": 30,
+ "ReorderLevel": 30,
+ "Discontinued": false,
+ "OrderDate": "2009-01-17",
+ "Rating": 5,
+ "Locations": [
+ {
+ "Shop": "Fun-Tasty Co.",
+ "LastInventory": "2018-06-12"
+ },
+ {
+ "Shop": "Farmer Market",
+ "LastInventory": "2018-04-04"
+ }
+ ]
+ },
+ {
+ "ProductID": 12,
+ "ProductName": "Queso Manchego La Pastora",
+ "SupplierID": 5,
+ "CategoryID": 4,
+ "QuantityPerUnit": "10 - 500 g pkgs.",
+ "UnitPrice": 38,
+ "UnitsInStock": 86,
+ "UnitsOnOrder": 30,
+ "ReorderLevel": 0,
+ "Discontinued": false,
+ "OrderDate": "2015-11-17",
+ "Rating": 3,
+ "Locations": [
+ {
+ "Shop": "Farmer Market",
+ "LastInventory": "2018-04-04"
+ }
+ ]
+ },
+ {
+ "ProductID": 13,
+ "ProductName": "Konbu",
+ "SupplierID": 6,
+ "CategoryID": 8,
+ "QuantityPerUnit": "2 kg box",
+ "UnitPrice": 6,
+ "UnitsInStock": 24,
+ "UnitsOnOrder": 30,
+ "ReorderLevel": 5,
+ "Discontinued": false,
+ "OrderDate": "2015-03-17",
+ "Rating": 2,
+ "Locations": [
+ {
+ "Shop": "Super Market",
+ "LastInventory": "2018-09-09"
+ }
+ ]
+ },
+ {
+ "ProductID": 14,
+ "ProductName": "Tofu",
+ "SupplierID": 6,
+ "CategoryID": 7,
+ "QuantityPerUnit": "40 - 100 g pkgs.",
+ "UnitPrice": 23.25,
+ "UnitsInStock": 35,
+ "UnitsOnOrder": 30,
+ "ReorderLevel": 0,
+ "Discontinued": false,
+ "OrderDate": "2017-06-17",
+ "Rating": 4,
+ "Locations": [
+ {
+ "Shop": "Farmer Market",
+ "LastInventory": "2018-04-04"
+ },
+ {
+ "Shop": "Street Market",
+ "LastInventory": "2018-12-12"
+ }
+ ]
+ },
+ {
+ "ProductID": 15,
+ "ProductName": "Genen Shouyu",
+ "SupplierID": 6,
+ "CategoryID": 2,
+ "QuantityPerUnit": "24 - 250 ml bottles",
+ "UnitPrice": 15.5,
+ "UnitsInStock": 39,
+ "UnitsOnOrder": 30,
+ "ReorderLevel": 5,
+ "Discontinued": false,
+ "OrderDate": "2014-03-17",
+ "Rating": 4,
+ "Locations": [
+ {
+ "Shop": "Local Market",
+ "LastInventory": "2018-07-03"
+ },
+ {
+ "Shop": "Wall Market",
+ "LastInventory": "2018-12-06"
+ }
+ ]
+ },
+ {
+ "ProductID": 16,
+ "ProductName": "Pavlova",
+ "SupplierID": 7,
+ "CategoryID": 3,
+ "QuantityPerUnit": "32 - 500 g boxes",
+ "UnitPrice": 17.45,
+ "UnitsInStock": 29,
+ "UnitsOnOrder": 30,
+ "ReorderLevel": 10,
+ "Discontinued": false,
+ "OrderDate": "2018-03-28",
+ "Rating": 2,
+ "Locations": [
+ {
+ "Shop": "Farmer Market",
+ "LastInventory": "2018-04-04"
+ },
+ {
+ "Shop": "Street Market",
+ "LastInventory": "2018-12-12"
+ },
+ {
+ "Shop": "24/7 Market",
+ "LastInventory": "2018-11-11"
+ }
+ ]
+ },
+ {
+ "ProductID": 17,
+ "ProductName": "Alice Mutton",
+ "SupplierID": 7,
+ "CategoryID": 6,
+ "QuantityPerUnit": "20 - 1 kg tins",
+ "UnitPrice": 39,
+ "UnitsInStock": 0,
+ "UnitsOnOrder": 30,
+ "ReorderLevel": 0,
+ "Discontinued": true,
+ "OrderDate": "2015-08-17",
+ "Rating": 2,
+ "Locations": [
+ {
+ "Shop": "Farmer Market",
+ "LastInventory": "2018-04-04"
+ }
+ ]
+ },
+ {
+ "ProductID": 18,
+ "ProductName": "Carnarvon Tigers",
+ "SupplierID": 7,
+ "CategoryID": 8,
+ "QuantityPerUnit": "16 kg pkg.",
+ "UnitPrice": 62.5,
+ "UnitsInStock": 42,
+ "UnitsOnOrder": 30,
+ "ReorderLevel": 0,
+ "Discontinued": false,
+ "OrderDate": "2005-09-27",
+ "Rating": 2,
+ "Locations": [
+ {
+ "Shop": "24/7 Market",
+ "LastInventory": "2018-11-11"
+ },
+ {
+ "Shop": "Super Market",
+ "LastInventory": "2018-09-09"
+ }
+ ]
+ },
+ {
+ "ProductID": 19,
+ "ProductName": "Teatime Chocolate Biscuits",
+ "SupplierID": 8,
+ "CategoryID": 3,
+ "QuantityPerUnit": "",
+ "UnitPrice": 9.2,
+ "UnitsInStock": 25,
+ "UnitsOnOrder": 30,
+ "ReorderLevel": 5,
+ "Discontinued": false,
+ "OrderDate": "2001-03-17",
+ "Rating": 2,
+ "Locations": [
+ {
+ "Shop": "Local Market",
+ "LastInventory": "2018-07-03"
+ }
+ ]
+ },
+ {
+ "ProductID": 20,
+ "ProductName": "Sir Rodneys Marmalade",
+ "SupplierID": 8,
+ "CategoryID": 3,
+ "QuantityPerUnit": "4 - 100 ml jars",
+ "UnitPrice": 4.5,
+ "UnitsInStock": 40,
+ "UnitsOnOrder": 30,
+ "ReorderLevel": 0,
+ "Discontinued": false,
+ "OrderDate": "2005-03-17",
+ "Rating": 5,
+ "Locations": [
+ {
+ "Shop": "Super Market",
+ "LastInventory": "2018-09-09"
+ }
+ ]
+ }
+]
\ No newline at end of file
diff --git a/samples/grids/grid/grid-batch-editing/src/index.css b/samples/grids/grid/grid-batch-editing/src/index.css
new file mode 100644
index 0000000000..94f5e82799
--- /dev/null
+++ b/samples/grids/grid/grid-batch-editing/src/index.css
@@ -0,0 +1,39 @@
+/* shared styles are loaded from: */
+/* https://dl.infragistics.com/x/css/samples/shared.v8.css */
+
+#grid {
+ --ig-size: var(--ig-size-medium);
+}
+
+.buttons-wrapper {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ padding: 10px 0;
+}
+
+.buttons-right {
+ display: flex;
+ gap: 8px;
+}
+
+.dialog-buttons {
+ display: flex;
+ gap: 8px;
+ justify-content: flex-end;
+}
+
+.transaction--add {
+ color: #6b3;
+ font-weight: 600;
+}
+
+.transaction--update {
+ color: #4a71b9;
+ font-weight: 600;
+}
+
+.transaction--delete {
+ color: #ee4920;
+ font-weight: 600;
+}
diff --git a/samples/grids/grid/grid-batch-editing/src/index.ts b/samples/grids/grid/grid-batch-editing/src/index.ts
new file mode 100644
index 0000000000..f1631812d0
--- /dev/null
+++ b/samples/grids/grid/grid-batch-editing/src/index.ts
@@ -0,0 +1,142 @@
+import 'igniteui-webcomponents-grids/grids/combined';
+import { IgcGridComponent, IgcColumnComponent } from 'igniteui-webcomponents-grids/grids';
+import NwindData from './NwindData.json';
+import { IgcCellTemplateContext } from 'igniteui-webcomponents-grids/grids';
+import { html } from 'lit-html';
+
+import "igniteui-webcomponents-grids/grids/themes/light/bootstrap.css";
+import 'igniteui-webcomponents/themes/light/bootstrap.css';
+import { defineAllComponents, IgcButtonComponent, IgcDialogComponent } from 'igniteui-webcomponents';
+defineAllComponents();
+
+import "./index.css";
+
+export class GridBatchEditingSample {
+
+ private grid: IgcGridComponent;
+ private deleteRowColumn: IgcColumnComponent;
+ private addRowBtn: IgcButtonComponent;
+ private undoBtn: IgcButtonComponent;
+ private redoBtn: IgcButtonComponent;
+ private commitBtn: IgcButtonComponent;
+ private discardBtn: IgcButtonComponent;
+ private dialog: IgcDialogComponent;
+ private transactionGrid: IgcGridComponent;
+ private typeColumn: IgcColumnComponent;
+ private valueColumn: IgcColumnComponent;
+ private addProductId: number = 1000;
+
+ constructor() {
+ this.grid = document.getElementById('grid') as IgcGridComponent;
+ this.deleteRowColumn = document.getElementById('actionsColumn') as IgcColumnComponent;
+ this.addRowBtn = document.getElementById('addRowBtn') as IgcButtonComponent;
+ this.undoBtn = document.getElementById('undoBtn') as IgcButtonComponent;
+ this.redoBtn = document.getElementById('redoBtn') as IgcButtonComponent;
+ this.commitBtn = document.getElementById('commitBtn') as IgcButtonComponent;
+ this.discardBtn = document.getElementById('discardBtn') as IgcButtonComponent;
+ this.dialog = document.getElementById('dialog') as IgcDialogComponent;
+ this.transactionGrid = document.getElementById('transactionGrid') as IgcGridComponent;
+ this.typeColumn = document.getElementById('typeColumn') as IgcColumnComponent;
+ this.valueColumn = document.getElementById('valueColumn') as IgcColumnComponent;
+
+ this.grid.batchEditing = true;
+ this.grid.data = this.nwindData;
+ this.deleteRowColumn.bodyTemplate = this.deleteRowColumnTemplate;
+ this.typeColumn.bodyTemplate = this.typeColumnTemplate;
+ this.valueColumn.bodyTemplate = this.valueColumnTemplate;
+
+ this.addRowBtn.addEventListener('click', this.onAddRowClick);
+ this.undoBtn.addEventListener('click', this.onUndoClick);
+ this.redoBtn.addEventListener('click', this.onRedoClick);
+ this.commitBtn.addEventListener('click', this.onOpenCommitDialog);
+ this.discardBtn.addEventListener('click', this.onDiscardClick);
+
+ document.getElementById('dialogCommitBtn')!.addEventListener('click', this.onCommitClick);
+ document.getElementById('dialogDiscardBtn')!.addEventListener('click', this.onDiscardClick);
+ document.getElementById('dialogCancelBtn')!.addEventListener('click', this.onCancelClick);
+
+ this.grid.transactions.onStateUpdate.subscribe(() => {
+ this.undoBtn.disabled = !this.grid.transactions.canUndo;
+ this.redoBtn.disabled = !this.grid.transactions.canRedo;
+ const hasChanges = this.grid.transactions.getAggregatedChanges(false).length > 0;
+ this.commitBtn.disabled = !hasChanges;
+ this.discardBtn.disabled = !hasChanges;
+ });
+ }
+
+ private _nwindData: any[] = NwindData;
+ public get nwindData(): any[] {
+ return this._nwindData;
+ }
+
+ public deleteRowColumnTemplate = (ctx: IgcCellTemplateContext) => {
+ return html` this.onDeleteRowClick(ctx.cell.id.rowID)}>Delete `;
+ }
+
+ public typeColumnTemplate = (ctx: IgcCellTemplateContext) => {
+ const type = ctx.cell.value as string;
+ return html`${type.toUpperCase()} `;
+ }
+
+ public valueColumnTemplate = (ctx: IgcCellTemplateContext) => {
+ return html`${JSON.stringify(ctx.cell.value)} `;
+ }
+
+ public onAddRowClick = () => {
+ this.grid.addRow({
+ CategoryID: this.randomInt(1, 10),
+ Discontinued: this.randomInt(1, 10) % 2 === 0,
+ OrderDate: new Date(this.randomInt(2000, 2050),
+ this.randomInt(0, 11), this.randomInt(1, 25))
+ .toISOString().slice(0, 10),
+ ProductID: this.addProductId++,
+ ProductName: 'Product with index ' + this.randomInt(0, 20),
+ QuantityPerUnit: (this.randomInt(1, 10) * 10).toString() + ' pcs.',
+ ReorderLevel: this.randomInt(10, 20),
+ SupplierID: this.randomInt(1, 20),
+ UnitPrice: this.randomInt(10, 1000),
+ UnitsInStock: this.randomInt(1, 100),
+ UnitsOnOrder: this.randomInt(1, 20)
+ });
+ }
+
+ private randomInt(min: number, max: number): number {
+ return Math.floor(Math.random() * (max - min + 1)) + min;
+ }
+
+ public onUndoClick = () => {
+ this.grid.endEdit(true);
+ this.grid.transactions.undo();
+ }
+
+ public onRedoClick = () => {
+ this.grid.endEdit(true);
+ this.grid.transactions.redo();
+ }
+
+ public onOpenCommitDialog = () => {
+ this.transactionGrid.data = this.grid.transactions.getAggregatedChanges(true);
+ this.dialog.show();
+ }
+
+ public onCommitClick = () => {
+ this.grid.transactions.commit(this.grid.data);
+ this.dialog.hide();
+ }
+
+ public onDiscardClick = () => {
+ this.grid.transactions.clear();
+ this.dialog.hide();
+ }
+
+ public onCancelClick = () => {
+ this.dialog.hide();
+ }
+
+ public onDeleteRowClick = (rowId: any) => {
+ this.grid.deleteRow(rowId);
+ }
+
+}
+
+new GridBatchEditingSample();
diff --git a/samples/grids/grid/grid-batch-editing/tsconfig.json b/samples/grids/grid/grid-batch-editing/tsconfig.json
new file mode 100644
index 0000000000..e7c370def4
--- /dev/null
+++ b/samples/grids/grid/grid-batch-editing/tsconfig.json
@@ -0,0 +1,41 @@
+{
+ "compilerOptions": {
+ "noImplicitReturns": true,
+ "esModuleInterop": true,
+ "resolveJsonModule": true,
+ "noImplicitAny": true,
+ "declarationDir": "dist/types",
+ "moduleResolution": "node",
+ "declaration": true,
+ "target": "es2015",
+ "module": "es2015",
+ "strict": true,
+ "strictNullChecks": false,
+ "baseUrl": ".",
+ "paths": {
+ "igniteui-webcomponents-core": [ "node_modules/igniteui-webcomponents-core", "node_modules/@infragistics/igniteui-webcomponents-core" ],
+ "igniteui-webcomponents-charts": [ "node_modules/igniteui-webcomponents-charts", "node_modules/@infragistics/igniteui-webcomponents-charts" ],
+ "igniteui-webcomponents-gauges": [ "node_modules/igniteui-webcomponents-gauges", "node_modules/@infragistics/igniteui-webcomponents-gauges" ],
+ "igniteui-webcomponents-datasources": [ "node_modules/igniteui-webcomponents-datasources", "node_modules/@infragistics/igniteui-webcomponents-datasources" ],
+ "igniteui-webcomponents-excel": [ "node_modules/igniteui-webcomponents-excel", "node_modules/@infragistics/igniteui-webcomponents-excel" ],
+ "igniteui-webcomponents-inputs": [ "node_modules/igniteui-webcomponents-inputs", "node_modules/@infragistics/igniteui-webcomponents-inputs" ],
+ "igniteui-webcomponents-grids": [ "node_modules/igniteui-webcomponents-grids", "node_modules/@infragistics/igniteui-webcomponents-grids" ],
+ "igniteui-webcomponents-maps": [ "node_modules/igniteui-webcomponents-maps", "node_modules/@infragistics/igniteui-webcomponents-maps" ],
+ "igniteui-webcomponents-spreadsheet": [ "node_modules/igniteui-webcomponents-spreadsheet", "node_modules/@infragistics/igniteui-webcomponents-spreadsheet" ],
+ "igniteui-webcomponents-spreadsheet-chart-adapter": [ "node_modules/igniteui-webcomponents-spreadsheet-chart-adapter", "node_modules/@infragistics/igniteui-webcomponents-spreadsheet-chart-adapter" ],
+ "igniteui-webcomponents-grids/*": [ "node_modules/igniteui-webcomponents-grids/*", "node_modules/@infragistics/igniteui-webcomponents-grids/*" ],
+ "igniteui-webcomponents-grids/grids": [ "node_modules/igniteui-webcomponents-grids/grids", "node_modules/@infragistics/igniteui-webcomponents-grids/grids" ],
+ "igniteui-webcomponents-grids/grids/*": [ "node_modules/igniteui-webcomponents-grids/grids/*", "node_modules/@infragistics/igniteui-webcomponents-grids/grids/*" ],
+ "igniteui-webcomponents-grids/grids/combined": [ "node_modules/igniteui-webcomponents-grids/grids/combined", "node_modules/@infragistics/igniteui-webcomponents-grids/grids/combined" ],
+ "igniteui-webcomponents-layouts": [ "node_modules/igniteui-webcomponents-layouts", "node_modules/@infragistics/igniteui-webcomponents-layouts" ],
+ "igniteui-webcomponents-dashboards": [ "node_modules/igniteui-webcomponents-dashboards", "node_modules/@infragistics/igniteui-webcomponents-dashboards" ]
+ }
+ },
+ "include": [
+ "src/**/*"
+ ],
+ "exclude": [
+ "node_modules",
+ "dist"
+ ]
+}
\ No newline at end of file
diff --git a/samples/grids/grid/grid-batch-editing/tslint.json b/samples/grids/grid/grid-batch-editing/tslint.json
new file mode 100644
index 0000000000..e3b56e93a1
--- /dev/null
+++ b/samples/grids/grid/grid-batch-editing/tslint.json
@@ -0,0 +1,54 @@
+{
+ "extends": ["tslint:recommended", "tslint-react", "tslint-config-prettier"],
+ "linterOptions": {
+ "exclude": [
+ "node_modules/**/*.ts",
+ "**/odatajs-4.0.0.js",
+ "src/images/*.*"
+ ]
+ },
+ "rules": {
+ "curly": [false, "ignore-same-line"],
+ "jsx-no-lambda": false,
+ "jsx-self-close": false,
+ "jsx-wrap-multiline": false,
+ "max-classes-per-file": [true, 10],
+ "member-ordering": false,
+ "no-console": false,
+ "no-string-literal": false,
+ "no-unused-vars": false,
+ "no-useless-constructor": false,
+ "no-trailing-whitespace": false,
+ "no-var": false,
+ "no-var-requires": false,
+ "no-var-keyword": false,
+ "ordered-imports": false,
+ "object-literal-sort-keys": false,
+ "object-literal-shorthand": false,
+ "only-arrow-functions": false,
+ "prefer-const": false,
+ "prefer-for-of": false,
+ "@typescript-eslint/no-unused-vars": "off",
+ "@typescript-eslint/no-useless-constructor": "off",
+ "@typescript-eslint/type-annotation-spacing": "off"
+ },
+ "jsRules": {
+ "curly": [false, "ignore-same-line"],
+ "jsx-no-lambda": false,
+ "jsx-self-close": false,
+ "jsx-wrap-multiline": false,
+ "max-classes-per-file": [true, 10],
+ "no-console": false,
+ "no-unused-vars": false,
+ "no-useless-constructor": false,
+ "no-var-requires": false,
+ "object-literal-sort-keys": false,
+ "object-literal-shorthand": false,
+ "only-arrow-functions": false,
+ "ordered-imports": false,
+ "prefer-const": false,
+ "prefer-for-of": false,
+ "@typescript-eslint/no-unused-vars": "off",
+ "@typescript-eslint/no-useless-constructor": "off"
+ }
+ }
\ No newline at end of file
diff --git a/samples/grids/grid/grid-batch-editing/webpack.config.js b/samples/grids/grid/grid-batch-editing/webpack.config.js
new file mode 100644
index 0000000000..c5c6b9f7e6
--- /dev/null
+++ b/samples/grids/grid/grid-batch-editing/webpack.config.js
@@ -0,0 +1,105 @@
+const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
+const HtmlWebpackPlugin = require('html-webpack-plugin');
+const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
+const path = require('path');
+const webpack = require('webpack');
+
+module.exports = env => {
+ const nodeEnv = process.env.NODE_ENV || 'development';
+ const isProd = nodeEnv === 'production';
+ const isLegacy = !!process.env.legacy && !(process.env.legacy == "false");
+ console.log(">> webpack nodeEnv=" + nodeEnv);
+ console.log(">> webpack isProd=" + isProd);
+ console.log(">> webpack isLegacy=" + isLegacy);
+ const presets = [
+ ["@babel/preset-env", {
+ "useBuiltIns": "usage",
+ "corejs": 3,
+ "targets": {
+ "browsers": isLegacy ? ["defaults"] : [
+ "last 2 Chrome versions",
+ "last 2 Safari versions",
+ "last 2 iOS versions",
+ "last 2 Firefox versions",
+ "last 2 Edge versions"]
+ }
+ }],
+ "@babel/preset-typescript"
+ ];
+
+ return {
+ entry: isLegacy ? [
+ path.resolve(__dirname, 'src')
+ ] : path.resolve(__dirname, 'src'),
+ devtool: isProd ? false : 'source-map',
+ output: {
+ filename: isProd ? '[fullhash].bundle.js' : '[fullhash].bundle.js',
+ globalObject: 'this',
+ path: path.resolve(__dirname, 'dist'),
+ },
+
+ resolve: {
+ mainFields: ['esm2015', 'module', 'main'],
+ extensions: ['.ts', '.js', '.json'],
+ plugins: [new TsconfigPathsPlugin({
+ configFile: './tsconfig.json',
+ extensions: ['.ts', '.js'],
+ mainFields: ['esm2015', 'module', 'main']
+ })]
+ },
+
+ module: {
+ rules: [
+ { test: /\.(png|svg|jpg|gif)$/, use: ['file-loader'] },
+ { test: /\.(csv|tsv)$/, use: ['csv-loader'] },
+ { test: /\.xml$/, use: ['xml-loader'] },
+ { test: /\.css$/, sideEffects: true, use: ['style-loader', 'css-loader'] },
+ {
+ test: /worker\.(ts|js)$/,
+ use: [
+ { loader: 'worker-loader' },
+ {
+ loader: 'babel-loader', options: {
+ "compact": isProd ? true : false,
+ "presets": presets,
+ "plugins": [
+ "@babel/plugin-transform-class-static-block",
+ "@babel/plugin-transform-class-properties",
+ "@babel/plugin-transform-runtime"
+ ]
+ }
+ }
+ ]
+ },
+ {
+ test: /\.(ts|js)$/, loader: 'babel-loader',
+ options: {
+ "compact": isProd ? true : false,
+ "presets": presets,
+ "plugins": [
+ "@babel/plugin-transform-class-static-block",
+ "@babel/plugin-transform-class-properties",
+ "@babel/plugin-transform-runtime"
+ ]
+ },
+ exclude:
+ function (modulePath) {
+ return /node_modules/.test(modulePath) &&
+ !/igniteui-webcomponents/.test(modulePath) &&
+ !/lit-html/.test(modulePath);
+ }
+ }],
+ },
+
+ plugins: [
+ new webpack.DefinePlugin({
+ 'process.env.NODE_ENV': JSON.stringify(nodeEnv)
+ }),
+ new HtmlWebpackPlugin({
+ title: 'Grid Batch Editing',
+ template: 'index.html'
+ }),
+ new ForkTsCheckerWebpackPlugin()
+ ]
+ };
+};
diff --git a/samples/grids/hierarchical-grid/grid-batch-editing/.prettierrc b/samples/grids/hierarchical-grid/grid-batch-editing/.prettierrc
new file mode 100644
index 0000000000..15a7c7c6cf
--- /dev/null
+++ b/samples/grids/hierarchical-grid/grid-batch-editing/.prettierrc
@@ -0,0 +1,11 @@
+{
+ "printWidth": 250,
+ "tabWidth": 4,
+ "useTabs": false,
+ "semi": true,
+ "singleQuote": false,
+ "trailingComma": "none",
+ "bracketSpacing": true,
+ "jsxBracketSameLine": false,
+ "fluid": false
+}
\ No newline at end of file
diff --git a/samples/grids/hierarchical-grid/grid-batch-editing/ReadMe.md b/samples/grids/hierarchical-grid/grid-batch-editing/ReadMe.md
new file mode 100644
index 0000000000..b47226cc7d
--- /dev/null
+++ b/samples/grids/hierarchical-grid/grid-batch-editing/ReadMe.md
@@ -0,0 +1,56 @@
+
+
+
+This folder contains implementation of Web Components application with example of Batch Editing feature using [Hierarchical Grid](https://infragistics.com/webcomponentssite/components/general-getting-started.html) component.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Branches
+
+> **_NOTE:_** You should use [master](https://github.com/IgniteUI/igniteui-angular-examples/tree/master) branch of this repository if you want to run samples on your computer. Use the [vnext](https://github.com/IgniteUI/igniteui-angular-examples/tree/vnext) branch only when you want to contribute new samples to this repository.
+
+## Instructions
+
+To set up this project locally, execute these commands:
+
+```
+git clone https://github.com/IgniteUI/igniteui-wc-examples.git
+git checkout master
+cd ./igniteui-wc-examples
+cd ./samples/grids/hierarchical-grid/grid-batch-editing
+```
+
+open above folder in VS Code or type:
+```
+code .
+```
+
+In terminal window, run:
+
+```
+npm install
+npm run start
+```
+
+Then open http://localhost:4200/ in your browser
+
+
+## Learn More
+
+To learn more about **Ignite UI for Web Components**, check out the [Web Components documentation](https://infragistics.com/webcomponentssite/components/general-getting-started.html).
diff --git a/samples/grids/hierarchical-grid/grid-batch-editing/index.html b/samples/grids/hierarchical-grid/grid-batch-editing/index.html
new file mode 100644
index 0000000000..2b3dee345b
--- /dev/null
+++ b/samples/grids/hierarchical-grid/grid-batch-editing/index.html
@@ -0,0 +1,191 @@
+
+
+
+ Hierarchical Grid Batch Editing | Ignite UI | Web Components | infragistics
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Commit
+ Discard
+ Cancel
+
+
+
+
+
+
+ <% if (false) { %><% } %>
+
+
diff --git a/samples/grids/hierarchical-grid/grid-batch-editing/package.json b/samples/grids/hierarchical-grid/grid-batch-editing/package.json
new file mode 100644
index 0000000000..33206ac0b7
--- /dev/null
+++ b/samples/grids/hierarchical-grid/grid-batch-editing/package.json
@@ -0,0 +1,61 @@
+{
+ "name": "example-ignite-ui-web-components",
+ "description": "This project provides example of using Ignite UI for Web Components",
+ "author": "Infragistics",
+ "version": "1.0.0",
+ "license": "",
+ "private": true,
+ "homepage": ".",
+ "main": "src/index.ts",
+ "scripts": {
+ "build": "npm run build:prod",
+ "build:dev": "webpack --mode development --config ./webpack.config.js --progress --color --display-error-details",
+ "build:prod": "webpack --env.NODE_ENV=production --mode production --config ./webpack.config.js --progress --color --display-error-details --bail",
+ "serve:dev": "node --max-old-space-size=8192 node_modules/webpack-dev-server/bin/webpack-dev-server.js --mode development --config ./webpack.config.js --hot --progress --open",
+ "serve:prod": "webpack-dev-server --env.NODE_ENV=production --mode production --config ./webpack.config.js --port 3000 --host 0.0.0.0 --hot --progress --open --content-base dist/",
+ "start": "npm run serve:dev",
+ "build:legacy": "npm run build:prod:legacy",
+ "build:dev:legacy": "webpack --env.legacy=true --mode development --config ./webpack.config.js --progress --color --display-error-details",
+ "build:prod:legacy": "webpack --env.NODE_ENV=production --env.legacy=true --mode production --config ./webpack.config.js --progress --color --display-error-details --bail",
+ "serve:dev:legacy": "node --max-old-space-size=8192 node_modules/webpack-dev-server/bin/webpack-dev-server.js --env.legacy=true --mode development --config ./webpack.config.js --hot --progress --open",
+ "serve:prod:legacy": "webpack-dev-server --env.NODE_ENV=production --env.legacy=true --mode production --config ./webpack.config.js --port 3000 --host 0.0.0.0 --hot --progress --open --content-base dist/",
+ "start:legacy": "npm run serve:dev:legacy"
+ },
+ "dependencies": {
+ "babel-runtime": "^6.26.0",
+ "igniteui-webcomponents": "^6.5.1",
+ "igniteui-webcomponents-core": "6.3.1",
+ "igniteui-webcomponents-grids": "6.3.0-alpha.1",
+ "igniteui-webcomponents-inputs": "6.3.1",
+ "igniteui-webcomponents-layouts": "6.3.1",
+ "lit-html": "^3.3.1",
+ "tslib": "^2.8.1"
+ },
+ "devDependencies": {
+ "@babel/cli": "^7.28.3",
+ "@babel/core": "^7.28.4",
+ "@babel/plugin-transform-class-properties": "^7.27.1",
+ "@babel/plugin-transform-class-static-block": "^7.28.3",
+ "@babel/plugin-transform-runtime": "^7.28.3",
+ "@babel/preset-env": "^7.28.3",
+ "@babel/preset-typescript": "^7.27.1",
+ "@types/source-map": "^0.5.7",
+ "babel-loader": "^10.0.0",
+ "babel-plugin-transform-custom-element-classes": "^0.1.0",
+ "css-loader": "^7.1.2",
+ "csv-loader": "^3.0.5",
+ "file-loader": "^6.2.0",
+ "fork-ts-checker-webpack-plugin": "^9.1.0",
+ "html-webpack-plugin": "^5.6.4",
+ "parcel-bundler": "^1.12.5",
+ "source-map": "^0.7.6",
+ "style-loader": "^4.0.0",
+ "tsconfig-paths-webpack-plugin": "^4.2.0",
+ "typescript": "^5.9.2",
+ "webpack": "^5.101.3",
+ "webpack-cli": "^6.0.1",
+ "webpack-dev-server": "^5.2.2",
+ "worker-loader": "^3.0.8",
+ "xml-loader": "^1.2.1"
+ }
+}
diff --git a/samples/grids/hierarchical-grid/grid-batch-editing/sandbox.config.json b/samples/grids/hierarchical-grid/grid-batch-editing/sandbox.config.json
new file mode 100644
index 0000000000..52c7875103
--- /dev/null
+++ b/samples/grids/hierarchical-grid/grid-batch-editing/sandbox.config.json
@@ -0,0 +1,6 @@
+{
+ "infiniteLoopProtection": false,
+ "hardReloadOnChange": false,
+ "view": "browser",
+ "template": "parcel"
+}
\ No newline at end of file
diff --git a/samples/grids/hierarchical-grid/grid-batch-editing/src/SingersData.json b/samples/grids/hierarchical-grid/grid-batch-editing/src/SingersData.json
new file mode 100644
index 0000000000..b0c61e1499
--- /dev/null
+++ b/samples/grids/hierarchical-grid/grid-batch-editing/src/SingersData.json
@@ -0,0 +1,2480 @@
+[
+ {
+ "ID": 0,
+ "Artist": "Naomí Yepes",
+ "Photo": "https://dl.infragistics.com/x/img/people/names/naomi.png",
+ "Debut": 2011,
+ "GrammyNominations": 6,
+ "GrammyAwards": 0,
+ "HasGrammyAward": false,
+ "Tours": [
+ {
+ "Tour": "Faithful Tour",
+ "StartedOn": "Sep 12",
+ "Location": "Worldwide",
+ "Headliner": "NO",
+ "TouredBy": "Naomí Yepes"
+ },
+ {
+ "Tour": "City Jam Sessions",
+ "StartedOn": "Aug 13",
+ "Location": "North America",
+ "Headliner": "YES",
+ "TouredBy": "Naomí Yepes"
+ },
+ {
+ "Tour": "Christmas NYC 2013",
+ "StartedOn": "Dec 13",
+ "Location": "United States",
+ "Headliner": "NO",
+ "TouredBy": "Naomí Yepes"
+ },
+ {
+ "Tour": "Christmas NYC 2014",
+ "StartedOn": "Dec 14",
+ "Location": "North America",
+ "Headliner": "NO",
+ "TouredBy": "Naomí Yepes"
+ },
+ {
+ "Tour": "Watermelon Tour",
+ "StartedOn": "Feb 15",
+ "Location": "Worldwide",
+ "Headliner": "YES",
+ "TouredBy": "Naomí Yepes"
+ },
+ {
+ "Tour": "Christmas NYC 2016",
+ "StartedOn": "Dec 16",
+ "Location": "United States",
+ "Headliner": "NO",
+ "TouredBy": "Naomí Yepes"
+ },
+ {
+ "Tour": "The Dragon Tour",
+ "StartedOn": "Feb 17",
+ "Location": "Worldwide",
+ "Headliner": "NO",
+ "TouredBy": "Naomí Yepes"
+ },
+ {
+ "Tour": "Organic Sessions",
+ "StartedOn": "Aug 18",
+ "Location": "United States, England",
+ "Headliner": "YES",
+ "TouredBy": "Naomí Yepes"
+ },
+ {
+ "Tour": "Hope World Tour",
+ "StartedOn": "Mar 19",
+ "Location": "Worldwide",
+ "Headliner": "NO",
+ "TouredBy": "Naomí Yepes"
+ }
+ ],
+ "Albums": [
+ {
+ "Album": "Initiation",
+ "LaunchDate": "2013-09-03",
+ "BillboardReview": 86,
+ "USBillboard200": 1,
+ "Artist": "Naomí Yepes",
+ "Songs": [
+ {
+ "Number": 1,
+ "Title": "Lonely Falling",
+ "Released": "2019-05-01",
+ "Genre": "*",
+ "Album": "Initiation"
+ },
+ {
+ "Number": 2,
+ "Title": "Bright Breaking",
+ "Released": "2019-07-25",
+ "Genre": "Electro house Electropop",
+ "Album": "Initiation"
+ },
+ {
+ "Number": 3,
+ "Title": "River of Whisper",
+ "Released": "2020-01-29",
+ "Genre": "Electro house Electropop",
+ "Album": "Initiation"
+ },
+ {
+ "Number": 4,
+ "Title": "Sky of Storm",
+ "Released": "2019-05-07",
+ "Genre": "Electro house Electropop",
+ "Album": "Initiation"
+ },
+ {
+ "Number": 5,
+ "Title": "Electric River",
+ "Released": "2020-01-20",
+ "Genre": "R&B",
+ "Album": "Initiation"
+ },
+ {
+ "Number": 6,
+ "Title": "Storm of Storm",
+ "Released": "2019-09-01",
+ "Genre": "Crunk reggaeton",
+ "Album": "Initiation"
+ },
+ {
+ "Number": 7,
+ "Title": "Fire of Dream",
+ "Released": "2019-09-12",
+ "Genre": "Electro house Electropop",
+ "Album": "Initiation"
+ },
+ {
+ "Number": 8,
+ "Title": "Burning in the Light",
+ "Released": "2019-04-15",
+ "Genre": "*",
+ "Album": "Initiation"
+ },
+ {
+ "Number": 9,
+ "Title": "Burning in the Storm",
+ "Released": "2019-09-10",
+ "Genre": "Electro house Electropop",
+ "Album": "Initiation"
+ },
+ {
+ "Number": 10,
+ "Title": "Shadow of Whisper",
+ "Released": "2019-01-06",
+ "Genre": "Crunk reggaeton",
+ "Album": "Initiation"
+ }
+ ]
+ },
+ {
+ "Album": "Dream Driven",
+ "LaunchDate": "2014-08-25",
+ "BillboardReview": 81,
+ "USBillboard200": 1,
+ "Artist": "Naomí Yepes",
+ "Songs": [
+ {
+ "Number": 1,
+ "Title": "Intro",
+ "Released": "2019-09-10",
+ "Genre": "*",
+ "Album": "Dream Driven"
+ },
+ {
+ "Number": 2,
+ "Title": "Ferocious",
+ "Released": "2014-04-28",
+ "Genre": "Dance-pop R&B",
+ "Album": "Dream Driven"
+ },
+ {
+ "Number": 3,
+ "Title": "Going crazy",
+ "Released": "2015-02-10",
+ "Genre": "Dance-pop EDM",
+ "Album": "Dream Driven"
+ },
+ {
+ "Number": 4,
+ "Title": "Future past",
+ "Released": "2011-09-20",
+ "Genre": "*",
+ "Album": "Dream Driven"
+ },
+ {
+ "Number": 5,
+ "Title": "Roaming like them",
+ "Released": "2014-07-02",
+ "Genre": "Electro house Electropop",
+ "Album": "Dream Driven"
+ },
+ {
+ "Number": 6,
+ "Title": "Last Wishes",
+ "Released": "2014-08-12",
+ "Genre": "R&B",
+ "Album": "Dream Driven"
+ },
+ {
+ "Number": 7,
+ "Title": "Stay where you are",
+ "Released": "2013-09-14",
+ "Genre": "*",
+ "Album": "Dream Driven"
+ },
+ {
+ "Number": 8,
+ "Title": "Imaginarium",
+ "Released": "2021-09-20",
+ "Genre": "*",
+ "Album": "Dream Driven"
+ },
+ {
+ "Number": 9,
+ "Title": "Tell me",
+ "Released": "2014-09-30",
+ "Genre": "Synth-pop R&B",
+ "Album": "Dream Driven"
+ },
+ {
+ "Number": 10,
+ "Title": "Shredded into pieces",
+ "Released": "2015-09-11",
+ "Genre": "*",
+ "Album": "Dream Driven"
+ },
+ {
+ "Number": 11,
+ "Title": "Capture this moment",
+ "Released": "2016-09-13",
+ "Genre": "*",
+ "Album": "Dream Driven"
+ },
+ {
+ "Number": 12,
+ "Title": "Dream Driven",
+ "Released": "2014-09-14",
+ "Genre": "*",
+ "Album": "Dream Driven"
+ }
+ ]
+ },
+ {
+ "Album": "The dragon journey",
+ "LaunchDate": "2016-05-20",
+ "BillboardReview": 60,
+ "USBillboard200": 2,
+ "Artist": "Naomí Yepes",
+ "Songs": [
+ {
+ "Number": 1,
+ "Title": "Calling in the Storm",
+ "Released": "2019-03-12",
+ "Genre": "Electro house Electropop",
+ "Album": "The dragon journey"
+ },
+ {
+ "Number": 2,
+ "Title": "Hiding in the Dream",
+ "Released": "2019-03-23",
+ "Genre": "R&B",
+ "Album": "The dragon journey"
+ },
+ {
+ "Number": 3,
+ "Title": "Electric Heart",
+ "Released": "2019-03-17",
+ "Genre": "ethno-tunes",
+ "Album": "The dragon journey"
+ },
+ {
+ "Number": 4,
+ "Title": "Shadow of Echo",
+ "Released": "2019-02-20",
+ "Genre": "ethno-tunes",
+ "Album": "The dragon journey"
+ },
+ {
+ "Number": 5,
+ "Title": "Flying in the Storm",
+ "Released": "2019-04-08",
+ "Genre": "R&B",
+ "Album": "The dragon journey"
+ },
+ {
+ "Number": 6,
+ "Title": "Dark Waiting",
+ "Released": "2019-10-20",
+ "Genre": "Synth-pop R&B",
+ "Album": "The dragon journey"
+ },
+ {
+ "Number": 7,
+ "Title": "Fire of River",
+ "Released": "2019-02-20",
+ "Genre": "Synth-pop R&B",
+ "Album": "The dragon journey"
+ },
+ {
+ "Number": 8,
+ "Title": "Wild Crying",
+ "Released": "2019-06-14",
+ "Genre": "R&B",
+ "Album": "The dragon journey"
+ },
+ {
+ "Number": 9,
+ "Title": "Bright Dancing",
+ "Released": "2019-03-14",
+ "Genre": "Electro house Electropop",
+ "Album": "The dragon journey"
+ },
+ {
+ "Number": 10,
+ "Title": "Golden Waiting",
+ "Released": "2019-09-12",
+ "Genre": "Synth-pop R&B",
+ "Album": "The dragon journey"
+ }
+ ]
+ },
+ {
+ "Album": "Organic me",
+ "LaunchDate": "2018-08-17",
+ "BillboardReview": 82,
+ "USBillboard200": 1,
+ "Artist": "Naomí Yepes",
+ "Songs": [
+ {
+ "Number": 1,
+ "Title": "I Love",
+ "Released": "2019-05-11",
+ "Genre": "Crunk reggaeton",
+ "Album": "Organic me"
+ },
+ {
+ "Number": 2,
+ "Title": "Early Morning Compass",
+ "Released": "2020-01-15",
+ "Genre": "mystical parody-bap ",
+ "Album": "Organic me"
+ },
+ {
+ "Number": 3,
+ "Title": "Key Fields Forever",
+ "Released": "2020-01-02",
+ "Genre": "Dance-pop EDM",
+ "Album": "Organic me"
+ },
+ {
+ "Number": 4,
+ "Title": "Stand by Your Goblins",
+ "Released": "2019-11-20",
+ "Genre": "*",
+ "Album": "Organic me"
+ },
+ {
+ "Number": 5,
+ "Title": "Mad to Walk",
+ "Released": "2019-05-12",
+ "Genre": "Electro house Electropop",
+ "Album": "Organic me"
+ },
+ {
+ "Number": 6,
+ "Title": "Alice's Waiting",
+ "Released": "2020-01-28",
+ "Genre": "R&B",
+ "Album": "Organic me"
+ },
+ {
+ "Number": 7,
+ "Title": "We Shall Kiss",
+ "Released": "2019-10-30",
+ "Genre": "*",
+ "Album": "Organic me"
+ },
+ {
+ "Number": 8,
+ "Title": "Behind Single Ants",
+ "Released": "2019-10-02",
+ "Genre": "*",
+ "Album": "Organic me"
+ },
+ {
+ "Number": 9,
+ "Title": "Soap Autopsy",
+ "Released": "2019-08-08",
+ "Genre": "Synth-pop R&B",
+ "Album": "Organic me"
+ },
+ {
+ "Number": 10,
+ "Title": "Have You Met Rich?",
+ "Released": "2019-07-01",
+ "Genre": "ethno-tunes",
+ "Album": "Organic me"
+ },
+ {
+ "Number": 11,
+ "Title": "Livin' on a Banana",
+ "Released": "2019-11-22",
+ "Genre": "Crunk reggaeton",
+ "Album": "Organic me"
+ }
+ ]
+ },
+ {
+ "Album": "Curiosity",
+ "LaunchDate": "2019-12-07",
+ "BillboardReview": 75,
+ "USBillboard200": 12,
+ "Artist": "Naomí Yepes",
+ "Songs": [
+ {
+ "Number": 1,
+ "Title": "Storm of Dream",
+ "Released": "2019-01-05",
+ "Genre": "*",
+ "Album": "Curiosity"
+ },
+ {
+ "Number": 2,
+ "Title": "Echo of Dream",
+ "Released": "2019-01-28",
+ "Genre": "Synth-pop R&B",
+ "Album": "Curiosity"
+ },
+ {
+ "Number": 3,
+ "Title": "Light of Shadow",
+ "Released": "2019-02-07",
+ "Genre": "Synth-pop R&B",
+ "Album": "Curiosity"
+ },
+ {
+ "Number": 4,
+ "Title": "Storm of Heart",
+ "Released": "2020-01-05",
+ "Genre": "Electro house Electropop",
+ "Album": "Curiosity"
+ },
+ {
+ "Number": 5,
+ "Title": "Shadow of River",
+ "Released": "2019-02-27",
+ "Genre": "*",
+ "Album": "Curiosity"
+ },
+ {
+ "Number": 6,
+ "Title": "Wicked Dancing",
+ "Released": "2020-01-17",
+ "Genre": "ethno-tunes",
+ "Album": "Curiosity"
+ },
+ {
+ "Number": 7,
+ "Title": "River of Light",
+ "Released": "2019-02-22",
+ "Genre": "R&B",
+ "Album": "Curiosity"
+ },
+ {
+ "Number": 8,
+ "Title": "Lonely Breaking",
+ "Released": "2019-09-09",
+ "Genre": "ethno-tunes",
+ "Album": "Curiosity"
+ },
+ {
+ "Number": 9,
+ "Title": "Furious Flying",
+ "Released": "2019-06-08",
+ "Genre": "R&B",
+ "Album": "Curiosity"
+ },
+ {
+ "Number": 10,
+ "Title": "Hiding in the Storm",
+ "Released": "2019-05-27",
+ "Genre": "Electro house Electropop",
+ "Album": "Curiosity"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "ID": 1,
+ "Artist": "Babila Ebwélé",
+ "Photo": "https://dl.infragistics.com/x/img/people/names/babila.png",
+ "Debut": 2009,
+ "GrammyNominations": 0,
+ "GrammyAwards": 11,
+ "HasGrammyAward": true,
+ "Tours": [
+ {
+ "Tour": "The last straw",
+ "StartedOn": "May 09",
+ "Location": "Europe, Asia",
+ "Headliner": "NO",
+ "TouredBy": "Babila Ebwélé"
+ },
+ {
+ "Tour": "No foundations",
+ "StartedOn": "Jun 04",
+ "Location": "United States, Europe",
+ "Headliner": "YES",
+ "TouredBy": "Babila Ebwélé"
+ },
+ {
+ "Tour": "Crazy eyes",
+ "StartedOn": "Jun 08",
+ "Location": "North America",
+ "Headliner": "NO",
+ "TouredBy": "Babila Ebwélé"
+ },
+ {
+ "Tour": "Zero gravity",
+ "StartedOn": "Apr 19",
+ "Location": "United States",
+ "Headliner": "NO",
+ "TouredBy": "Babila Ebwélé"
+ },
+ {
+ "Tour": "Battle with myself",
+ "StartedOn": "Mar 08",
+ "Location": "North America",
+ "Headliner": "YES",
+ "TouredBy": "Babila Ebwélé"
+ }
+ ],
+ "Albums": [
+ {
+ "Album": "Pushing up daisies",
+ "LaunchDate": "2000-05-31",
+ "BillboardReview": 86,
+ "USBillboard200": 42,
+ "Artist": "Babila Ebwélé",
+ "Songs": [
+ {
+ "Number": 1,
+ "Title": "Wood Shavings Forever",
+ "Released": "2019-06-09",
+ "Genre": "*",
+ "Album": "Pushing up daisies"
+ },
+ {
+ "Number": 2,
+ "Title": "Early Morning Drive",
+ "Released": "2019-05-20",
+ "Genre": "*",
+ "Album": "Pushing up daisies"
+ },
+ {
+ "Number": 3,
+ "Title": "Don't Natter",
+ "Released": "2019-06-10",
+ "Genre": "adult calypso-industrial",
+ "Album": "Pushing up daisies"
+ },
+ {
+ "Number": 4,
+ "Title": "Stairway to Balloons",
+ "Released": "2019-06-18",
+ "Genre": "calypso and mariachi",
+ "Album": "Pushing up daisies"
+ },
+ {
+ "Number": 5,
+ "Title": "The Number of your Apple",
+ "Released": "2019-10-29",
+ "Genre": "*",
+ "Album": "Pushing up daisies"
+ },
+ {
+ "Number": 6,
+ "Title": "Your Delightful Heart",
+ "Released": "2019-02-24",
+ "Genre": "*",
+ "Album": "Pushing up daisies"
+ },
+ {
+ "Number": 7,
+ "Title": "Nice Weather For Balloons",
+ "Released": "2019-08-01",
+ "Genre": "rap-hop",
+ "Album": "Pushing up daisies"
+ },
+ {
+ "Number": 8,
+ "Title": "The Girl From Cornwall",
+ "Released": "2019-05-04",
+ "Genre": "enigmatic rock-and-roll",
+ "Album": "Pushing up daisies"
+ },
+ {
+ "Number": 9,
+ "Title": "Here Without Jack",
+ "Released": "2019-10-24",
+ "Genre": "*",
+ "Album": "Pushing up daisies"
+ },
+ {
+ "Number": 10,
+ "Title": "Born Rancid",
+ "Released": "2019-03-19",
+ "Genre": "*",
+ "Album": "Pushing up daisies"
+ }
+ ]
+ },
+ {
+ "Album": "Death's dead",
+ "LaunchDate": "2016-06-08",
+ "BillboardReview": 85,
+ "USBillboard200": 95,
+ "Artist": "Babila Ebwélé",
+ "Songs": [
+ {
+ "Number": 1,
+ "Title": "Men Sound Better With You",
+ "Released": "2019-10-20",
+ "Genre": "rap-hop",
+ "Album": "Death's dead"
+ },
+ {
+ "Number": 2,
+ "Title": "Ghost in My Rod",
+ "Released": "2019-10-05",
+ "Genre": "enigmatic rock-and-roll",
+ "Album": "Death's dead"
+ },
+ {
+ "Number": 3,
+ "Title": "Bed of Men",
+ "Released": "2019-11-14",
+ "Genre": "whimsical comedy-grass ",
+ "Album": "Death's dead"
+ },
+ {
+ "Number": 4,
+ "Title": "Don't Push",
+ "Released": "2020-01-02",
+ "Genre": "unblack electronic-trip-hop",
+ "Album": "Death's dead"
+ },
+ {
+ "Number": 5,
+ "Title": "Nice Weather For Men",
+ "Released": "2019-12-18",
+ "Genre": "*",
+ "Album": "Death's dead"
+ },
+ {
+ "Number": 6,
+ "Title": "Rancid Rhapsody",
+ "Released": "2019-03-10",
+ "Genre": "*",
+ "Album": "Death's dead"
+ },
+ {
+ "Number": 7,
+ "Title": "Push, Push, Push!",
+ "Released": "2019-02-21",
+ "Genre": "*",
+ "Album": "Death's dead"
+ },
+ {
+ "Number": 8,
+ "Title": "My Name is Sarah",
+ "Released": "2019-11-15",
+ "Genre": "*",
+ "Album": "Death's dead"
+ },
+ {
+ "Number": 9,
+ "Title": "The Girl From My Hotel",
+ "Released": "2019-11-06",
+ "Genre": "*",
+ "Album": "Death's dead"
+ },
+ {
+ "Number": 10,
+ "Title": "Free Box",
+ "Released": "2019-04-18",
+ "Genre": "splitter-funk",
+ "Album": "Death's dead"
+ },
+ {
+ "Number": 11,
+ "Title": "Hotel Cardiff",
+ "Released": "2019-12-30",
+ "Genre": "guilty pleasure ebm",
+ "Album": "Death's dead"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "ID": 2,
+ "Artist": "Ahmad Nazeri",
+ "Photo": "https://dl.infragistics.com/x/img/people/names/ahmad.png",
+ "Debut": 2004,
+ "GrammyNominations": 3,
+ "GrammyAwards": 1,
+ "HasGrammyAward": true,
+ "Tours": [],
+ "Albums": [
+ {
+ "Album": "Emergency",
+ "LaunchDate": "2004-03-06",
+ "BillboardReview": 98,
+ "USBillboard200": 69,
+ "Artist": "Ahmad Nazeri",
+ "Songs": [
+ {
+ "Number": 1,
+ "Title": "Gentle Falling",
+ "Released": "2019-04-26",
+ "Genre": "Crunk reggaeton",
+ "Album": "Emergency"
+ },
+ {
+ "Number": 2,
+ "Title": "Calling in the Fire",
+ "Released": "2019-09-03",
+ "Genre": "ethno-tunes",
+ "Album": "Emergency"
+ },
+ {
+ "Number": 3,
+ "Title": "Fire of Shadow",
+ "Released": "2019-01-05",
+ "Genre": "ethno-tunes",
+ "Album": "Emergency"
+ },
+ {
+ "Number": 4,
+ "Title": "Dancing in the Dream",
+ "Released": "2019-04-15",
+ "Genre": "R&B",
+ "Album": "Emergency"
+ },
+ {
+ "Number": 5,
+ "Title": "Calling in the Shadow",
+ "Released": "2019-10-09",
+ "Genre": "R&B",
+ "Album": "Emergency"
+ },
+ {
+ "Number": 6,
+ "Title": "Falling in the Sky",
+ "Released": "2019-03-08",
+ "Genre": "ethno-tunes",
+ "Album": "Emergency"
+ },
+ {
+ "Number": 7,
+ "Title": "Calling in the Storm",
+ "Released": "2019-12-05",
+ "Genre": "ethno-tunes",
+ "Album": "Emergency"
+ },
+ {
+ "Number": 8,
+ "Title": "Falling in the River",
+ "Released": "2019-08-19",
+ "Genre": "Electro house Electropop",
+ "Album": "Emergency"
+ },
+ {
+ "Number": 9,
+ "Title": "Electric Fire",
+ "Released": "2019-11-30",
+ "Genre": "Crunk reggaeton",
+ "Album": "Emergency"
+ },
+ {
+ "Number": 10,
+ "Title": "Lonely River",
+ "Released": "2019-11-11",
+ "Genre": "Electro house Electropop",
+ "Album": "Emergency"
+ }
+ ]
+ },
+ {
+ "Album": "Bursting bubbles",
+ "LaunchDate": "2006-04-17",
+ "BillboardReview": 69,
+ "USBillboard200": 39,
+ "Artist": "Ahmad Nazeri",
+ "Songs": [
+ {
+ "Number": 1,
+ "Title": "Lonely Dream",
+ "Released": "2019-12-11",
+ "Genre": "ethno-tunes",
+ "Album": "Bursting bubbles"
+ },
+ {
+ "Number": 2,
+ "Title": "Fire of River",
+ "Released": "2019-08-01",
+ "Genre": "Synth-pop R&B",
+ "Album": "Bursting bubbles"
+ },
+ {
+ "Number": 3,
+ "Title": "Wicked Falling",
+ "Released": "2019-01-25",
+ "Genre": "*",
+ "Album": "Bursting bubbles"
+ },
+ {
+ "Number": 4,
+ "Title": "Crying in the Shadow",
+ "Released": "2019-01-04",
+ "Genre": "Synth-pop R&B",
+ "Album": "Bursting bubbles"
+ },
+ {
+ "Number": 5,
+ "Title": "Wild Burning",
+ "Released": "2019-05-10",
+ "Genre": "ethno-tunes",
+ "Album": "Bursting bubbles"
+ },
+ {
+ "Number": 6,
+ "Title": "Waiting in the Heart",
+ "Released": "2019-08-07",
+ "Genre": "ethno-tunes",
+ "Album": "Bursting bubbles"
+ },
+ {
+ "Number": 7,
+ "Title": "Fire of Fire",
+ "Released": "2019-05-16",
+ "Genre": "Electro house Electropop",
+ "Album": "Bursting bubbles"
+ },
+ {
+ "Number": 8,
+ "Title": "Bright Heart",
+ "Released": "2019-03-14",
+ "Genre": "Synth-pop R&B",
+ "Album": "Bursting bubbles"
+ },
+ {
+ "Number": 9,
+ "Title": "Lonely Fire",
+ "Released": "2019-10-15",
+ "Genre": "R&B",
+ "Album": "Bursting bubbles"
+ },
+ {
+ "Number": 10,
+ "Title": "Sky of Dream",
+ "Released": "2019-06-20",
+ "Genre": "ethno-tunes",
+ "Album": "Bursting bubbles"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "ID": 3,
+ "Artist": "Kimmy McIlmorie",
+ "Photo": "https://dl.infragistics.com/x/img/people/names/kimmy.png",
+ "Debut": 2007,
+ "GrammyNominations": 21,
+ "GrammyAwards": 3,
+ "HasGrammyAward": true,
+ "Tours": [],
+ "Albums": [
+ {
+ "Album": "Here we go again",
+ "LaunchDate": "2017-11-18",
+ "BillboardReview": 68,
+ "USBillboard200": 1,
+ "Artist": "Kimmy McIlmorie",
+ "Songs": [
+ {
+ "Number": 1,
+ "Title": "Storm of Sky",
+ "Released": "2019-03-04",
+ "Genre": "ethno-tunes",
+ "Album": "Here we go again"
+ },
+ {
+ "Number": 2,
+ "Title": "Dream of Shadow",
+ "Released": "2019-01-03",
+ "Genre": "ethno-tunes",
+ "Album": "Here we go again"
+ },
+ {
+ "Number": 3,
+ "Title": "Dream of Shadow",
+ "Released": "2019-12-19",
+ "Genre": "Electro house Electropop",
+ "Album": "Here we go again"
+ },
+ {
+ "Number": 4,
+ "Title": "Golden Fire",
+ "Released": "2019-01-20",
+ "Genre": "R&B",
+ "Album": "Here we go again"
+ },
+ {
+ "Number": 5,
+ "Title": "Running in the Light",
+ "Released": "2020-01-03",
+ "Genre": "Synth-pop R&B",
+ "Album": "Here we go again"
+ },
+ {
+ "Number": 6,
+ "Title": "Flying in the Heart",
+ "Released": "2019-01-17",
+ "Genre": "*",
+ "Album": "Here we go again"
+ },
+ {
+ "Number": 7,
+ "Title": "Fire of Storm",
+ "Released": "2019-01-26",
+ "Genre": "ethno-tunes",
+ "Album": "Here we go again"
+ },
+ {
+ "Number": 8,
+ "Title": "Calling in the Sky",
+ "Released": "2019-10-28",
+ "Genre": "Synth-pop R&B",
+ "Album": "Here we go again"
+ },
+ {
+ "Number": 9,
+ "Title": "Flying in the Shadow",
+ "Released": "2019-03-30",
+ "Genre": "ethno-tunes",
+ "Album": "Here we go again"
+ },
+ {
+ "Number": 10,
+ "Title": "Golden Dancing",
+ "Released": "2019-10-12",
+ "Genre": "ethno-tunes",
+ "Album": "Here we go again"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "ID": 4,
+ "Artist": "Mar Rueda",
+ "Photo": "https://dl.infragistics.com/x/img/people/names/mar.png",
+ "Debut": 1996,
+ "GrammyNominations": 14,
+ "GrammyAwards": 2,
+ "HasGrammyAward": true,
+ "Tours": [],
+ "Albums": []
+ },
+ {
+ "ID": 5,
+ "Artist": "Izabella Tabakova",
+ "Photo": "https://dl.infragistics.com/x/img/people/names/izabella.png",
+ "Debut": 2017,
+ "GrammyNominations": 7,
+ "GrammyAwards": 11,
+ "HasGrammyAward": true,
+ "Tours": [
+ {
+ "Tour": "Final breath",
+ "StartedOn": "Jun 13",
+ "Location": "Europe",
+ "Headliner": "YES",
+ "TouredBy": "Izabella Tabakova"
+ },
+ {
+ "Tour": "Once bitten",
+ "StartedOn": "Dec 18",
+ "Location": "Australia, United States",
+ "Headliner": "NO",
+ "TouredBy": "Izabella Tabakova"
+ },
+ {
+ "Tour": "Code word",
+ "StartedOn": "Sep 19",
+ "Location": "United States, Europe",
+ "Headliner": "NO",
+ "TouredBy": "Izabella Tabakova"
+ },
+ {
+ "Tour": "Final draft",
+ "StartedOn": "Sep 17",
+ "Location": "United States, Europe",
+ "Headliner": "YES",
+ "TouredBy": "Izabella Tabakova"
+ }
+ ],
+ "Albums": [
+ {
+ "Album": "Once bitten",
+ "LaunchDate": "2007-07-16",
+ "BillboardReview": 79,
+ "USBillboard200": 53,
+ "Artist": "Izabella Tabakova",
+ "Songs": [
+ {
+ "Number": 1,
+ "Title": "Whole Lotta Super Cats",
+ "Released": "2019-05-21",
+ "Genre": "*",
+ "Album": "Once bitten"
+ },
+ {
+ "Number": 2,
+ "Title": "Enter Becky",
+ "Released": "2020-01-16",
+ "Genre": "*",
+ "Album": "Once bitten"
+ },
+ {
+ "Number": 3,
+ "Title": "Your Cheatin' Flamingo",
+ "Released": "2020-01-14",
+ "Genre": "*",
+ "Album": "Once bitten"
+ },
+ {
+ "Number": 4,
+ "Title": "Mad to Kiss",
+ "Released": "2019-11-06",
+ "Genre": "Synth-pop R&B",
+ "Album": "Once bitten"
+ },
+ {
+ "Number": 5,
+ "Title": "Hotel Prague",
+ "Released": "2019-10-20",
+ "Genre": "ethno-tunes",
+ "Album": "Once bitten"
+ },
+ {
+ "Number": 6,
+ "Title": "Jail on My Mind",
+ "Released": "2019-05-31",
+ "Genre": "Crunk reggaeton",
+ "Album": "Once bitten"
+ },
+ {
+ "Number": 7,
+ "Title": "Amazing Blues",
+ "Released": "2019-05-29",
+ "Genre": "mystical parody-bap ",
+ "Album": "Once bitten"
+ },
+ {
+ "Number": 8,
+ "Title": "Goody Two Iron Filings",
+ "Released": "2019-07-04",
+ "Genre": "Electro house Electropop",
+ "Album": "Once bitten"
+ },
+ {
+ "Number": 9,
+ "Title": "I Love in Your Arms",
+ "Released": "2019-06-07",
+ "Genre": "R&B",
+ "Album": "Once bitten"
+ },
+ {
+ "Number": 10,
+ "Title": "Truly Madly Amazing",
+ "Released": "2019-09-12",
+ "Genre": "ethno-tunes",
+ "Album": "Once bitten"
+ }
+ ]
+ },
+ {
+ "Album": "Your graciousness",
+ "LaunchDate": "2004-11-17",
+ "BillboardReview": 69,
+ "USBillboard200": 30,
+ "Artist": "Izabella Tabakova",
+ "Songs": [
+ {
+ "Number": 1,
+ "Title": "We Shall Tickle",
+ "Released": "2019-08-31",
+ "Genre": "old emo-garage ",
+ "Album": "Your graciousness"
+ },
+ {
+ "Number": 2,
+ "Title": "Snail Boogie",
+ "Released": "2019-06-14",
+ "Genre": "*",
+ "Album": "Your graciousness"
+ },
+ {
+ "Number": 3,
+ "Title": "Amazing Liz",
+ "Released": "2019-10-15",
+ "Genre": "*",
+ "Album": "Your graciousness"
+ },
+ {
+ "Number": 4,
+ "Title": "When Sexy Aardvarks Cry",
+ "Released": "2019-10-01",
+ "Genre": "whimsical comedy-grass ",
+ "Album": "Your graciousness"
+ },
+ {
+ "Number": 5,
+ "Title": "Stand By Dave",
+ "Released": "2019-08-18",
+ "Genre": "unblack electronic-trip-hop",
+ "Album": "Your graciousness"
+ },
+ {
+ "Number": 6,
+ "Title": "The Golf Course is Your Land",
+ "Released": "2019-04-02",
+ "Genre": "*",
+ "Album": "Your graciousness"
+ },
+ {
+ "Number": 7,
+ "Title": "Where Have All the Men Gone?",
+ "Released": "2019-04-29",
+ "Genre": "*",
+ "Album": "Your graciousness"
+ },
+ {
+ "Number": 8,
+ "Title": "Rhythm of the Leg",
+ "Released": "2019-08-05",
+ "Genre": "ethno-tunes",
+ "Album": "Your graciousness"
+ },
+ {
+ "Number": 9,
+ "Title": "Baby, I Need Your Hats",
+ "Released": "2019-12-05",
+ "Genre": "neuro-tunes",
+ "Album": "Your graciousness"
+ },
+ {
+ "Number": 10,
+ "Title": "Stand by Your Cat",
+ "Released": "2019-07-25",
+ "Genre": "*",
+ "Album": "Your graciousness"
+ }
+ ]
+ },
+ {
+ "Album": "Dark matters",
+ "LaunchDate": "2002-11-03",
+ "BillboardReview": 79,
+ "USBillboard200": 85,
+ "Artist": "Izabella Tabakova",
+ "Songs": [
+ {
+ "Number": 1,
+ "Title": "Hiding in the Light",
+ "Released": "2019-01-24",
+ "Genre": "Synth-pop R&B",
+ "Album": "Dark matters"
+ },
+ {
+ "Number": 2,
+ "Title": "Furious River",
+ "Released": "2020-01-13",
+ "Genre": "Electro house Electropop",
+ "Album": "Dark matters"
+ },
+ {
+ "Number": 3,
+ "Title": "Wild Crying",
+ "Released": "2019-02-27",
+ "Genre": "Electro house Electropop",
+ "Album": "Dark matters"
+ },
+ {
+ "Number": 4,
+ "Title": "Light of Dream",
+ "Released": "2019-06-01",
+ "Genre": "Crunk reggaeton",
+ "Album": "Dark matters"
+ },
+ {
+ "Number": 5,
+ "Title": "Light of Dream",
+ "Released": "2019-08-24",
+ "Genre": "*",
+ "Album": "Dark matters"
+ },
+ {
+ "Number": 6,
+ "Title": "Storm of Light",
+ "Released": "2019-02-26",
+ "Genre": "*",
+ "Album": "Dark matters"
+ },
+ {
+ "Number": 7,
+ "Title": "Dark Storm",
+ "Released": "2020-01-18",
+ "Genre": "R&B",
+ "Album": "Dark matters"
+ },
+ {
+ "Number": 8,
+ "Title": "Dark Calling",
+ "Released": "2019-03-20",
+ "Genre": "Crunk reggaeton",
+ "Album": "Dark matters"
+ },
+ {
+ "Number": 9,
+ "Title": "Sky of Whisper",
+ "Released": "2019-01-30",
+ "Genre": "ethno-tunes",
+ "Album": "Dark matters"
+ },
+ {
+ "Number": 10,
+ "Title": "Dancing in the Light",
+ "Released": "2019-11-28",
+ "Genre": "Synth-pop R&B",
+ "Album": "Dark matters"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "ID": 6,
+ "Artist": "Nguyễn Diệp Chi",
+ "Photo": "https://dl.infragistics.com/x/img/people/names/nguyen.png",
+ "Debut": 1992,
+ "GrammyNominations": 4,
+ "GrammyAwards": 2,
+ "HasGrammyAward": true,
+ "Tours": [],
+ "Albums": [
+ {
+ "Album": "Library of liberty",
+ "LaunchDate": "2003-12-22",
+ "BillboardReview": 93,
+ "USBillboard200": 5,
+ "Artist": "Nguyễn Diệp Chi",
+ "Songs": [
+ {
+ "Number": 1,
+ "Title": "Echo of River",
+ "Released": "2019-03-05",
+ "Genre": "Synth-pop R&B",
+ "Album": "Library of liberty"
+ },
+ {
+ "Number": 2,
+ "Title": "Heart of River",
+ "Released": "2020-01-12",
+ "Genre": "Electro house Electropop",
+ "Album": "Library of liberty"
+ },
+ {
+ "Number": 3,
+ "Title": "Dark Light",
+ "Released": "2019-08-09",
+ "Genre": "Electro house Electropop",
+ "Album": "Library of liberty"
+ },
+ {
+ "Number": 4,
+ "Title": "Dark Fire",
+ "Released": "2019-06-22",
+ "Genre": "R&B",
+ "Album": "Library of liberty"
+ },
+ {
+ "Number": 5,
+ "Title": "Flying in the Fire",
+ "Released": "2019-07-22",
+ "Genre": "*",
+ "Album": "Library of liberty"
+ },
+ {
+ "Number": 6,
+ "Title": "Shadow of Heart",
+ "Released": "2020-01-02",
+ "Genre": "*",
+ "Album": "Library of liberty"
+ },
+ {
+ "Number": 7,
+ "Title": "Fire of Fire",
+ "Released": "2019-01-27",
+ "Genre": "*",
+ "Album": "Library of liberty"
+ },
+ {
+ "Number": 8,
+ "Title": "Falling in the River",
+ "Released": "2019-08-05",
+ "Genre": "Crunk reggaeton",
+ "Album": "Library of liberty"
+ },
+ {
+ "Number": 9,
+ "Title": "Fire of Light",
+ "Released": "2019-12-31",
+ "Genre": "ethno-tunes",
+ "Album": "Library of liberty"
+ },
+ {
+ "Number": 10,
+ "Title": "Bright Flying",
+ "Released": "2019-01-24",
+ "Genre": "*",
+ "Album": "Library of liberty"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "ID": 7,
+ "Artist": "Eva Lee",
+ "Photo": "https://dl.infragistics.com/x/img/people/names/eva.png",
+ "Debut": 2008,
+ "GrammyNominations": 2,
+ "GrammyAwards": 0,
+ "HasGrammyAward": false,
+ "Tours": [],
+ "Albums": [
+ {
+ "Album": "Just a tease",
+ "LaunchDate": "2001-05-03",
+ "BillboardReview": 91,
+ "USBillboard200": 29,
+ "Artist": "Eva Lee",
+ "Songs": [
+ {
+ "Number": 1,
+ "Title": "Dancing in the Shadow",
+ "Released": "2019-08-02",
+ "Genre": "ethno-tunes",
+ "Album": "Just a tease"
+ },
+ {
+ "Number": 2,
+ "Title": "Silent Whisper",
+ "Released": "2019-07-09",
+ "Genre": "*",
+ "Album": "Just a tease"
+ },
+ {
+ "Number": 3,
+ "Title": "Crying in the Whisper",
+ "Released": "2019-05-30",
+ "Genre": "Crunk reggaeton",
+ "Album": "Just a tease"
+ },
+ {
+ "Number": 4,
+ "Title": "River of Light",
+ "Released": "2019-01-10",
+ "Genre": "Electro house Electropop",
+ "Album": "Just a tease"
+ },
+ {
+ "Number": 5,
+ "Title": "Golden River",
+ "Released": "2019-11-15",
+ "Genre": "*",
+ "Album": "Just a tease"
+ },
+ {
+ "Number": 6,
+ "Title": "Burning in the Shadow",
+ "Released": "2019-04-18",
+ "Genre": "Crunk reggaeton",
+ "Album": "Just a tease"
+ },
+ {
+ "Number": 7,
+ "Title": "Shadow of Sky",
+ "Released": "2019-09-06",
+ "Genre": "Crunk reggaeton",
+ "Album": "Just a tease"
+ },
+ {
+ "Number": 8,
+ "Title": "Gentle Waiting",
+ "Released": "2019-12-05",
+ "Genre": "R&B",
+ "Album": "Just a tease"
+ },
+ {
+ "Number": 9,
+ "Title": "Bright River",
+ "Released": "2020-01-27",
+ "Genre": "R&B",
+ "Album": "Just a tease"
+ },
+ {
+ "Number": 10,
+ "Title": "Heart of Storm",
+ "Released": "2019-01-07",
+ "Genre": "Synth-pop R&B",
+ "Album": "Just a tease"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "ID": 8,
+ "Artist": "Siri Jakobsson",
+ "Photo": "https://dl.infragistics.com/x/img/people/names/siri.png",
+ "Debut": 1990,
+ "GrammyNominations": 2,
+ "GrammyAwards": 8,
+ "HasGrammyAward": true,
+ "Tours": [
+ {
+ "Tour": "Basket case",
+ "StartedOn": "Jan 07",
+ "Location": "Europe, Asia",
+ "Headliner": "NO",
+ "TouredBy": "Siri Jakobsson"
+ },
+ {
+ "Tour": "The bigger fish",
+ "StartedOn": "Dec 07",
+ "Location": "United States, Europe",
+ "Headliner": "YES",
+ "TouredBy": "Siri Jakobsson"
+ },
+ {
+ "Tour": "Missed the boat",
+ "StartedOn": "Jun 09",
+ "Location": "Europe, Asia",
+ "Headliner": "NO",
+ "TouredBy": "Siri Jakobsson"
+ },
+ {
+ "Tour": "Equivalent exchange",
+ "StartedOn": "Feb 06",
+ "Location": "United States, Europe",
+ "Headliner": "YES",
+ "TouredBy": "Siri Jakobsson"
+ },
+ {
+ "Tour": "Damage control",
+ "StartedOn": "Oct 11",
+ "Location": "Australia, United States",
+ "Headliner": "NO",
+ "TouredBy": "Siri Jakobsson"
+ }
+ ],
+ "Albums": [
+ {
+ "Album": "Under the bus",
+ "LaunchDate": "2000-05-14",
+ "BillboardReview": 67,
+ "USBillboard200": 67,
+ "Artist": "Siri Jakobsson",
+ "Songs": [
+ {
+ "Number": 1,
+ "Title": "Jack Broke My Heart At Tesco's",
+ "Released": "2020-01-19",
+ "Genre": "*",
+ "Album": "Under the bus"
+ },
+ {
+ "Number": 2,
+ "Title": "Cat Deep, Hats High",
+ "Released": "2019-12-05",
+ "Genre": "*",
+ "Album": "Under the bus"
+ },
+ {
+ "Number": 3,
+ "Title": "In Snail We Trust",
+ "Released": "2019-05-31",
+ "Genre": "hardcore opera",
+ "Album": "Under the bus"
+ },
+ {
+ "Number": 4,
+ "Title": "Liz's Waiting",
+ "Released": "2019-07-22",
+ "Genre": "emotional C-jam ",
+ "Album": "Under the bus"
+ },
+ {
+ "Number": 5,
+ "Title": "Lifeless Blues",
+ "Released": "2019-06-14",
+ "Genre": "*",
+ "Album": "Under the bus"
+ },
+ {
+ "Number": 6,
+ "Title": "I Spin",
+ "Released": "2019-03-26",
+ "Genre": "*",
+ "Album": "Under the bus"
+ },
+ {
+ "Number": 7,
+ "Title": "Ring of Rock",
+ "Released": "2019-12-12",
+ "Genre": "*",
+ "Album": "Under the bus"
+ },
+ {
+ "Number": 8,
+ "Title": "Livin' on a Rock",
+ "Released": "2019-04-17",
+ "Genre": "*",
+ "Album": "Under the bus"
+ },
+ {
+ "Number": 9,
+ "Title": "Your Lifeless Heart",
+ "Released": "2019-09-15",
+ "Genre": "adult calypso-industrial",
+ "Album": "Under the bus"
+ },
+ {
+ "Number": 10,
+ "Title": "The High Street on My Mind",
+ "Released": "2019-11-11",
+ "Genre": "calypso and mariachi",
+ "Album": "Under the bus"
+ },
+ {
+ "Number": 11,
+ "Title": "Behind Ugly Curtains",
+ "Released": "2019-05-08",
+ "Genre": "*",
+ "Album": "Under the bus"
+ },
+ {
+ "Number": 12,
+ "Title": "Where Have All the Curtains Gone?",
+ "Released": "2019-06-28",
+ "Genre": "*",
+ "Album": "Under the bus"
+ },
+ {
+ "Number": 13,
+ "Title": "Ghost in My Apple",
+ "Released": "2019-12-14",
+ "Genre": "*",
+ "Album": "Under the bus"
+ },
+ {
+ "Number": 14,
+ "Title": "I Chatter",
+ "Released": "2019-11-30",
+ "Genre": "*",
+ "Album": "Under the bus"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "ID": 9,
+ "Artist": "Pablo Cambeiro",
+ "Photo": "https://dl.infragistics.com/x/img/people/names/pablo.png",
+ "Debut": 2011,
+ "GrammyNominations": 5,
+ "GrammyAwards": 0,
+ "HasGrammyAward": false,
+ "Tours": [
+ {
+ "Tour": "Beads",
+ "StartedOn": "May 11",
+ "Location": "Worldwide",
+ "Headliner": "NO",
+ "TouredBy": "Pablo Cambeiro"
+ },
+ {
+ "Tour": "Concept art",
+ "StartedOn": "Dec 18",
+ "Location": "United States",
+ "Headliner": "YES",
+ "TouredBy": "Pablo Cambeiro"
+ },
+ {
+ "Tour": "Glass shoe",
+ "StartedOn": "Jan 20",
+ "Location": "Worldwide",
+ "Headliner": "YES",
+ "TouredBy": "Pablo Cambeiro"
+ },
+ {
+ "Tour": "Pushing buttons",
+ "StartedOn": "Feb 15",
+ "Location": "Europe, Asia",
+ "Headliner": "NO",
+ "TouredBy": "Pablo Cambeiro"
+ },
+ {
+ "Tour": "Dark matters",
+ "StartedOn": "Jan 04",
+ "Location": "Australia, United States",
+ "Headliner": "YES",
+ "TouredBy": "Pablo Cambeiro"
+ },
+ {
+ "Tour": "Greener grass",
+ "StartedOn": "Sep 09",
+ "Location": "United States, Europe",
+ "Headliner": "NO",
+ "TouredBy": "Pablo Cambeiro"
+ },
+ {
+ "Tour": "Apparatus",
+ "StartedOn": "Nov 16",
+ "Location": "Europe",
+ "Headliner": "NO",
+ "TouredBy": "Pablo Cambeiro"
+ }
+ ],
+ "Albums": [
+ {
+ "Album": "Fluke",
+ "LaunchDate": "2017-08-04",
+ "BillboardReview": 93,
+ "USBillboard200": 98,
+ "Artist": "Pablo Cambeiro",
+ "Songs": [
+ {
+ "Number": 1,
+ "Title": "Dancing in the Echo",
+ "Released": "2019-10-03",
+ "Genre": "Crunk reggaeton",
+ "Album": "Fluke"
+ },
+ {
+ "Number": 2,
+ "Title": "Dream of Dream",
+ "Released": "2019-03-03",
+ "Genre": "*",
+ "Album": "Fluke"
+ },
+ {
+ "Number": 3,
+ "Title": "Calling in the Echo",
+ "Released": "2019-09-16",
+ "Genre": "*",
+ "Album": "Fluke"
+ },
+ {
+ "Number": 4,
+ "Title": "Light of Light",
+ "Released": "2019-05-25",
+ "Genre": "Electro house Electropop",
+ "Album": "Fluke"
+ },
+ {
+ "Number": 5,
+ "Title": "Bright Light",
+ "Released": "2019-03-21",
+ "Genre": "R&B",
+ "Album": "Fluke"
+ },
+ {
+ "Number": 6,
+ "Title": "Storm of Echo",
+ "Released": "2019-07-17",
+ "Genre": "Synth-pop R&B",
+ "Album": "Fluke"
+ },
+ {
+ "Number": 7,
+ "Title": "Lonely Calling",
+ "Released": "2019-04-10",
+ "Genre": "ethno-tunes",
+ "Album": "Fluke"
+ },
+ {
+ "Number": 8,
+ "Title": "Gentle Falling",
+ "Released": "2019-11-28",
+ "Genre": "Synth-pop R&B",
+ "Album": "Fluke"
+ },
+ {
+ "Number": 9,
+ "Title": "Wild Flying",
+ "Released": "2019-11-26",
+ "Genre": "Crunk reggaeton",
+ "Album": "Fluke"
+ },
+ {
+ "Number": 10,
+ "Title": "Sky of Dream",
+ "Released": "2019-05-29",
+ "Genre": "R&B",
+ "Album": "Fluke"
+ }
+ ]
+ },
+ {
+ "Album": "Crowd control",
+ "LaunchDate": "2003-08-26",
+ "BillboardReview": 68,
+ "USBillboard200": 84,
+ "Artist": "Pablo Cambeiro",
+ "Songs": [
+ {
+ "Number": 1,
+ "Title": "My Bed on My Mind",
+ "Released": "2019-03-25",
+ "Genre": "ethno-tunes",
+ "Album": "Crowd control"
+ },
+ {
+ "Number": 2,
+ "Title": "Bright Blues",
+ "Released": "2019-09-28",
+ "Genre": "neuro-tunes",
+ "Album": "Crowd control"
+ },
+ {
+ "Number": 3,
+ "Title": "Sail, Sail, Sail!",
+ "Released": "2019-03-05",
+ "Genre": "*",
+ "Album": "Crowd control"
+ },
+ {
+ "Number": 4,
+ "Title": "Hotel My Bed",
+ "Released": "2019-03-22",
+ "Genre": "*",
+ "Album": "Crowd control"
+ },
+ {
+ "Number": 5,
+ "Title": "Gonna Make You Mash",
+ "Released": "2019-05-18",
+ "Genre": "*",
+ "Album": "Crowd control"
+ },
+ {
+ "Number": 6,
+ "Title": "Straight Outta America",
+ "Released": "2020-01-16",
+ "Genre": "hardcore opera",
+ "Album": "Crowd control"
+ },
+ {
+ "Number": 7,
+ "Title": "I Drive",
+ "Released": "2019-02-23",
+ "Genre": "emotional C-jam ",
+ "Album": "Crowd control"
+ },
+ {
+ "Number": 8,
+ "Title": "Like a Teddy",
+ "Released": "2019-08-31",
+ "Genre": "*",
+ "Album": "Crowd control"
+ },
+ {
+ "Number": 9,
+ "Title": "Teddy Boogie",
+ "Released": "2019-11-30",
+ "Genre": "*",
+ "Album": "Crowd control"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "ID": 10,
+ "Artist": "Athar Malakooti",
+ "Photo": "https://dl.infragistics.com/x/img/people/names/athar.png",
+ "Debut": 2017,
+ "GrammyNominations": 0,
+ "GrammyAwards": 0,
+ "HasGrammyAward": false,
+ "Tours": [],
+ "Albums": [
+ {
+ "Album": "Pushing up daisies",
+ "LaunchDate": "2016-02-24",
+ "BillboardReview": 74,
+ "USBillboard200": 77,
+ "Artist": "Athar Malakooti",
+ "Songs": [
+ {
+ "Number": 1,
+ "Title": "Hiding in the Whisper",
+ "Released": "2019-04-03",
+ "Genre": "R&B",
+ "Album": "Pushing up daisies"
+ },
+ {
+ "Number": 2,
+ "Title": "Wicked Light",
+ "Released": "2019-08-21",
+ "Genre": "R&B",
+ "Album": "Pushing up daisies"
+ },
+ {
+ "Number": 3,
+ "Title": "Flying in the River",
+ "Released": "2020-02-03",
+ "Genre": "Synth-pop R&B",
+ "Album": "Pushing up daisies"
+ },
+ {
+ "Number": 4,
+ "Title": "Wicked Hiding",
+ "Released": "2019-09-15",
+ "Genre": "Synth-pop R&B",
+ "Album": "Pushing up daisies"
+ },
+ {
+ "Number": 5,
+ "Title": "Lonely Light",
+ "Released": "2019-05-13",
+ "Genre": "Electro house Electropop",
+ "Album": "Pushing up daisies"
+ },
+ {
+ "Number": 6,
+ "Title": "Bright Dancing",
+ "Released": "2019-04-10",
+ "Genre": "Synth-pop R&B",
+ "Album": "Pushing up daisies"
+ },
+ {
+ "Number": 7,
+ "Title": "Gentle Dream",
+ "Released": "2019-05-21",
+ "Genre": "*",
+ "Album": "Pushing up daisies"
+ },
+ {
+ "Number": 8,
+ "Title": "Sky of Echo",
+ "Released": "2019-06-09",
+ "Genre": "Synth-pop R&B",
+ "Album": "Pushing up daisies"
+ },
+ {
+ "Number": 9,
+ "Title": "Breaking in the Sky",
+ "Released": "2019-12-27",
+ "Genre": "Crunk reggaeton",
+ "Album": "Pushing up daisies"
+ },
+ {
+ "Number": 10,
+ "Title": "Whisper of Shadow",
+ "Released": "2019-01-04",
+ "Genre": "ethno-tunes",
+ "Album": "Pushing up daisies"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "ID": 11,
+ "Artist": "Marti Valencia",
+ "Photo": "https://dl.infragistics.com/x/img/people/names/marti.png",
+ "Debut": 2004,
+ "GrammyNominations": 1,
+ "GrammyAwards": 1,
+ "HasGrammyAward": true,
+ "Tours": [
+ {
+ "Tour": "Cat eat cat world",
+ "StartedOn": "Sep 00",
+ "Location": "Worldwide",
+ "Headliner": "YES",
+ "TouredBy": "Marti Valencia"
+ },
+ {
+ "Tour": "Final straw",
+ "StartedOn": "Sep 06",
+ "Location": "United States, Europe",
+ "Headliner": "NO",
+ "TouredBy": "Marti Valencia"
+ }
+ ],
+ "Albums": [
+ {
+ "Album": "Nemesis",
+ "LaunchDate": "2004-06-30",
+ "BillboardReview": 94,
+ "USBillboard200": 9,
+ "Artist": "Marti Valencia",
+ "Songs": [
+ {
+ "Number": 1,
+ "Title": "Hiding in the Sky",
+ "Released": "2019-11-26",
+ "Genre": "Synth-pop R&B",
+ "Album": "Nemesis"
+ },
+ {
+ "Number": 2,
+ "Title": "Waiting in the Echo",
+ "Released": "2019-07-10",
+ "Genre": "ethno-tunes",
+ "Album": "Nemesis"
+ },
+ {
+ "Number": 3,
+ "Title": "Wicked Shadow",
+ "Released": "2019-07-29",
+ "Genre": "Synth-pop R&B",
+ "Album": "Nemesis"
+ },
+ {
+ "Number": 4,
+ "Title": "Crying in the Whisper",
+ "Released": "2019-04-09",
+ "Genre": "*",
+ "Album": "Nemesis"
+ },
+ {
+ "Number": 5,
+ "Title": "Echo of Storm",
+ "Released": "2019-11-19",
+ "Genre": "Crunk reggaeton",
+ "Album": "Nemesis"
+ },
+ {
+ "Number": 6,
+ "Title": "Shadow of Sky",
+ "Released": "2019-07-24",
+ "Genre": "Crunk reggaeton",
+ "Album": "Nemesis"
+ },
+ {
+ "Number": 7,
+ "Title": "Golden Hiding",
+ "Released": "2019-12-12",
+ "Genre": "Electro house Electropop",
+ "Album": "Nemesis"
+ },
+ {
+ "Number": 8,
+ "Title": "Wild Dancing",
+ "Released": "2019-08-17",
+ "Genre": "Synth-pop R&B",
+ "Album": "Nemesis"
+ },
+ {
+ "Number": 9,
+ "Title": "Bright Burning",
+ "Released": "2019-08-30",
+ "Genre": "Electro house Electropop",
+ "Album": "Nemesis"
+ },
+ {
+ "Number": 10,
+ "Title": "Flying in the River",
+ "Released": "2019-09-02",
+ "Genre": "*",
+ "Album": "Nemesis"
+ }
+ ]
+ },
+ {
+ "Album": "First chance",
+ "LaunchDate": "2019-01-07",
+ "BillboardReview": 96,
+ "USBillboard200": 19,
+ "Artist": "Marti Valencia",
+ "Songs": [
+ {
+ "Number": 1,
+ "Title": "My Name is Jason",
+ "Released": "2019-07-12",
+ "Genre": "*",
+ "Album": "First chance"
+ },
+ {
+ "Number": 2,
+ "Title": "Amazing Andy",
+ "Released": "2019-03-05",
+ "Genre": "*",
+ "Album": "First chance"
+ },
+ {
+ "Number": 3,
+ "Title": "The Number of your Knight",
+ "Released": "2019-12-04",
+ "Genre": "*",
+ "Album": "First chance"
+ },
+ {
+ "Number": 4,
+ "Title": "I Sail",
+ "Released": "2019-03-03",
+ "Genre": "*",
+ "Album": "First chance"
+ },
+ {
+ "Number": 5,
+ "Title": "Goody Two Hands",
+ "Released": "2019-10-11",
+ "Genre": "Electro house Electropop",
+ "Album": "First chance"
+ },
+ {
+ "Number": 6,
+ "Title": "Careful With That Knife",
+ "Released": "2019-12-18",
+ "Genre": "R&B",
+ "Album": "First chance"
+ },
+ {
+ "Number": 7,
+ "Title": "Four Single Ants",
+ "Released": "2020-01-18",
+ "Genre": "*",
+ "Album": "First chance"
+ },
+ {
+ "Number": 8,
+ "Title": "Kiss Forever",
+ "Released": "2019-08-10",
+ "Genre": "*",
+ "Album": "First chance"
+ },
+ {
+ "Number": 9,
+ "Title": "Rich's Waiting",
+ "Released": "2019-03-15",
+ "Genre": "Synth-pop R&B",
+ "Album": "First chance"
+ },
+ {
+ "Number": 10,
+ "Title": "Japan is Your Land",
+ "Released": "2019-03-07",
+ "Genre": "ethno-tunes",
+ "Album": "First chance"
+ },
+ {
+ "Number": 11,
+ "Title": "Pencils in My Banana",
+ "Released": "2019-06-21",
+ "Genre": "Crunk reggaeton",
+ "Album": "First chance"
+ },
+ {
+ "Number": 12,
+ "Title": "I Sail in Your Arms",
+ "Released": "2019-04-30",
+ "Genre": "Synth-pop R&B",
+ "Album": "First chance"
+ }
+ ]
+ },
+ {
+ "Album": "God's advocate",
+ "LaunchDate": "2007-04-29",
+ "BillboardReview": 66,
+ "USBillboard200": 37,
+ "Artist": "Marti Valencia",
+ "Songs": [
+ {
+ "Number": 1,
+ "Title": "Wild River",
+ "Released": "2019-01-11",
+ "Genre": "*",
+ "Album": "God's advocate"
+ },
+ {
+ "Number": 2,
+ "Title": "Wicked Whisper",
+ "Released": "2019-02-16",
+ "Genre": "Electro house Electropop",
+ "Album": "God's advocate"
+ },
+ {
+ "Number": 3,
+ "Title": "Storm of Heart",
+ "Released": "2019-08-11",
+ "Genre": "*",
+ "Album": "God's advocate"
+ },
+ {
+ "Number": 4,
+ "Title": "Golden Dancing",
+ "Released": "2019-03-02",
+ "Genre": "Crunk reggaeton",
+ "Album": "God's advocate"
+ },
+ {
+ "Number": 5,
+ "Title": "Calling in the Sky",
+ "Released": "2019-09-10",
+ "Genre": "Electro house Electropop",
+ "Album": "God's advocate"
+ },
+ {
+ "Number": 6,
+ "Title": "Calling in the Heart",
+ "Released": "2019-01-12",
+ "Genre": "ethno-tunes",
+ "Album": "God's advocate"
+ },
+ {
+ "Number": 7,
+ "Title": "Running in the Storm",
+ "Released": "2019-11-10",
+ "Genre": "Synth-pop R&B",
+ "Album": "God's advocate"
+ },
+ {
+ "Number": 8,
+ "Title": "Wild Sky",
+ "Released": "2019-04-10",
+ "Genre": "R&B",
+ "Album": "God's advocate"
+ },
+ {
+ "Number": 9,
+ "Title": "Crying in the Shadow",
+ "Released": "2019-03-02",
+ "Genre": "R&B",
+ "Album": "God's advocate"
+ },
+ {
+ "Number": 10,
+ "Title": "Whisper of River",
+ "Released": "2019-05-12",
+ "Genre": "*",
+ "Album": "God's advocate"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "ID": 12,
+ "Artist": "Alicia Stanger",
+ "Photo": "https://dl.infragistics.com/x/img/people/names/alicia.png",
+ "Debut": 2010,
+ "GrammyNominations": 1,
+ "GrammyAwards": 0,
+ "HasGrammyAward": false,
+ "Tours": [],
+ "Albums": [
+ {
+ "Album": "Forever alone",
+ "LaunchDate": "2005-11-03",
+ "BillboardReview": 82,
+ "USBillboard200": 7,
+ "Artist": "Alicia Stanger",
+ "Songs": [
+ {
+ "Number": 1,
+ "Title": "Shadow of Light",
+ "Released": "2019-03-24",
+ "Genre": "ethno-tunes",
+ "Album": "Forever alone"
+ },
+ {
+ "Number": 2,
+ "Title": "Running in the Echo",
+ "Released": "2019-05-03",
+ "Genre": "Crunk reggaeton",
+ "Album": "Forever alone"
+ },
+ {
+ "Number": 3,
+ "Title": "Gentle Dream",
+ "Released": "2019-08-24",
+ "Genre": "Crunk reggaeton",
+ "Album": "Forever alone"
+ },
+ {
+ "Number": 4,
+ "Title": "Furious River",
+ "Released": "2019-04-24",
+ "Genre": "ethno-tunes",
+ "Album": "Forever alone"
+ },
+ {
+ "Number": 5,
+ "Title": "Wild Whisper",
+ "Released": "2019-03-09",
+ "Genre": "ethno-tunes",
+ "Album": "Forever alone"
+ },
+ {
+ "Number": 6,
+ "Title": "Whisper of Sky",
+ "Released": "2019-07-24",
+ "Genre": "Crunk reggaeton",
+ "Album": "Forever alone"
+ },
+ {
+ "Number": 7,
+ "Title": "Lonely Storm",
+ "Released": "2019-05-01",
+ "Genre": "Crunk reggaeton",
+ "Album": "Forever alone"
+ },
+ {
+ "Number": 8,
+ "Title": "Dancing in the River",
+ "Released": "2019-12-17",
+ "Genre": "*",
+ "Album": "Forever alone"
+ },
+ {
+ "Number": 9,
+ "Title": "Electric Fire",
+ "Released": "2019-10-17",
+ "Genre": "Electro house Electropop",
+ "Album": "Forever alone"
+ },
+ {
+ "Number": 10,
+ "Title": "Electric Sky",
+ "Released": "2019-09-25",
+ "Genre": "ethno-tunes",
+ "Album": "Forever alone"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "ID": 13,
+ "Artist": "Peter Taylor",
+ "Photo": "https://dl.infragistics.com/x/img/people/names/peter.png",
+ "Debut": 2005,
+ "GrammyNominations": 0,
+ "GrammyAwards": 2,
+ "HasGrammyAward": true,
+ "Tours": [
+ {
+ "Tour": "Love",
+ "StartedOn": "Jun 04",
+ "Location": "Europe, Asia",
+ "Headliner": "YES",
+ "TouredBy": "Peter Taylor"
+ },
+ {
+ "Tour": "Fault of treasures",
+ "StartedOn": "Oct 13",
+ "Location": "North America",
+ "Headliner": "NO",
+ "TouredBy": "Peter Taylor"
+ },
+ {
+ "Tour": "For eternity",
+ "StartedOn": "Mar 05",
+ "Location": "United States",
+ "Headliner": "YES",
+ "TouredBy": "Peter Taylor"
+ },
+ {
+ "Tour": "Time flies",
+ "StartedOn": "Jun 03",
+ "Location": "North America",
+ "Headliner": "NO",
+ "TouredBy": "Peter Taylor"
+ },
+ {
+ "Tour": "Highest difficulty",
+ "StartedOn": "Nov 01",
+ "Location": "Worldwide",
+ "Headliner": "YES",
+ "TouredBy": "Peter Taylor"
+ },
+ {
+ "Tour": "Sleeping dogs",
+ "StartedOn": "May 04",
+ "Location": "United States, Europe",
+ "Headliner": "NO",
+ "TouredBy": "Peter Taylor"
+ }
+ ],
+ "Albums": [
+ {
+ "Album": "Decisions decisions",
+ "LaunchDate": "2008-04-10",
+ "BillboardReview": 85,
+ "USBillboard200": 35,
+ "Artist": "Peter Taylor",
+ "Songs": [
+ {
+ "Number": 1,
+ "Title": "Calling in the Dream",
+ "Released": "2019-08-01",
+ "Genre": "R&B",
+ "Album": "Decisions decisions"
+ },
+ {
+ "Number": 2,
+ "Title": "Electric Burning",
+ "Released": "2019-09-10",
+ "Genre": "Electro house Electropop",
+ "Album": "Decisions decisions"
+ },
+ {
+ "Number": 3,
+ "Title": "Dark Flying",
+ "Released": "2019-04-28",
+ "Genre": "*",
+ "Album": "Decisions decisions"
+ },
+ {
+ "Number": 4,
+ "Title": "Gentle Sky",
+ "Released": "2019-11-20",
+ "Genre": "ethno-tunes",
+ "Album": "Decisions decisions"
+ },
+ {
+ "Number": 5,
+ "Title": "Gentle Calling",
+ "Released": "2019-01-13",
+ "Genre": "Crunk reggaeton",
+ "Album": "Decisions decisions"
+ },
+ {
+ "Number": 6,
+ "Title": "Golden Falling",
+ "Released": "2019-02-14",
+ "Genre": "Crunk reggaeton",
+ "Album": "Decisions decisions"
+ },
+ {
+ "Number": 7,
+ "Title": "Silent River",
+ "Released": "2019-02-13",
+ "Genre": "R&B",
+ "Album": "Decisions decisions"
+ },
+ {
+ "Number": 8,
+ "Title": "Furious Calling",
+ "Released": "2019-06-11",
+ "Genre": "Synth-pop R&B",
+ "Album": "Decisions decisions"
+ },
+ {
+ "Number": 9,
+ "Title": "Running in the Echo",
+ "Released": "2019-11-06",
+ "Genre": "Electro house Electropop",
+ "Album": "Decisions decisions"
+ },
+ {
+ "Number": 10,
+ "Title": "Furious River",
+ "Released": "2019-03-12",
+ "Genre": "*",
+ "Album": "Decisions decisions"
+ }
+ ]
+ },
+ {
+ "Album": "Climate changed",
+ "LaunchDate": "2015-06-20",
+ "BillboardReview": 66,
+ "USBillboard200": 89,
+ "Artist": "Peter Taylor",
+ "Songs": [
+ {
+ "Number": 1,
+ "Title": "Dark Crying",
+ "Released": "2019-04-27",
+ "Genre": "Electro house Electropop",
+ "Album": "Climate changed"
+ },
+ {
+ "Number": 2,
+ "Title": "Dark Waiting",
+ "Released": "2019-11-14",
+ "Genre": "Synth-pop R&B",
+ "Album": "Climate changed"
+ },
+ {
+ "Number": 3,
+ "Title": "Furious Waiting",
+ "Released": "2019-05-23",
+ "Genre": "*",
+ "Album": "Climate changed"
+ },
+ {
+ "Number": 4,
+ "Title": "Running in the Echo",
+ "Released": "2019-11-29",
+ "Genre": "Crunk reggaeton",
+ "Album": "Climate changed"
+ },
+ {
+ "Number": 5,
+ "Title": "Dream of Sky",
+ "Released": "2019-10-31",
+ "Genre": "Crunk reggaeton",
+ "Album": "Climate changed"
+ },
+ {
+ "Number": 6,
+ "Title": "Hiding in the Heart",
+ "Released": "2019-08-09",
+ "Genre": "R&B",
+ "Album": "Climate changed"
+ },
+ {
+ "Number": 7,
+ "Title": "Sky of Storm",
+ "Released": "2019-06-01",
+ "Genre": "R&B",
+ "Album": "Climate changed"
+ },
+ {
+ "Number": 8,
+ "Title": "Light of Storm",
+ "Released": "2020-01-17",
+ "Genre": "ethno-tunes",
+ "Album": "Climate changed"
+ },
+ {
+ "Number": 9,
+ "Title": "Light of Sky",
+ "Released": "2019-05-26",
+ "Genre": "*",
+ "Album": "Climate changed"
+ },
+ {
+ "Number": 10,
+ "Title": "Golden River",
+ "Released": "2019-06-19",
+ "Genre": "*",
+ "Album": "Climate changed"
+ }
+ ]
+ }
+ ]
+ }
+]
\ No newline at end of file
diff --git a/samples/grids/hierarchical-grid/grid-batch-editing/src/index.css b/samples/grids/hierarchical-grid/grid-batch-editing/src/index.css
new file mode 100644
index 0000000000..94f5e82799
--- /dev/null
+++ b/samples/grids/hierarchical-grid/grid-batch-editing/src/index.css
@@ -0,0 +1,39 @@
+/* shared styles are loaded from: */
+/* https://dl.infragistics.com/x/css/samples/shared.v8.css */
+
+#grid {
+ --ig-size: var(--ig-size-medium);
+}
+
+.buttons-wrapper {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ padding: 10px 0;
+}
+
+.buttons-right {
+ display: flex;
+ gap: 8px;
+}
+
+.dialog-buttons {
+ display: flex;
+ gap: 8px;
+ justify-content: flex-end;
+}
+
+.transaction--add {
+ color: #6b3;
+ font-weight: 600;
+}
+
+.transaction--update {
+ color: #4a71b9;
+ font-weight: 600;
+}
+
+.transaction--delete {
+ color: #ee4920;
+ font-weight: 600;
+}
diff --git a/samples/grids/hierarchical-grid/grid-batch-editing/src/index.ts b/samples/grids/hierarchical-grid/grid-batch-editing/src/index.ts
new file mode 100644
index 0000000000..8875e9f92d
--- /dev/null
+++ b/samples/grids/hierarchical-grid/grid-batch-editing/src/index.ts
@@ -0,0 +1,137 @@
+import 'igniteui-webcomponents-grids/grids/combined';
+import { IgcHierarchicalGridComponent, IgcGridComponent, IgcColumnComponent } from 'igniteui-webcomponents-grids/grids';
+import SingersData from './SingersData.json';
+import { IgcCellTemplateContext } from 'igniteui-webcomponents-grids/grids';
+import { html } from 'lit-html';
+
+import "igniteui-webcomponents-grids/grids/themes/light/bootstrap.css";
+import 'igniteui-webcomponents/themes/light/bootstrap.css';
+import { defineAllComponents, IgcButtonComponent, IgcDialogComponent } from 'igniteui-webcomponents';
+defineAllComponents();
+
+import "./index.css";
+
+export class HierarchicalGridBatchEditingSample {
+
+ private grid: IgcHierarchicalGridComponent;
+ private deleteRowColumn: IgcColumnComponent;
+ private addRowBtn: IgcButtonComponent;
+ private undoBtn: IgcButtonComponent;
+ private redoBtn: IgcButtonComponent;
+ private commitBtn: IgcButtonComponent;
+ private discardBtn: IgcButtonComponent;
+ private dialog: IgcDialogComponent;
+ private transactionGrid: IgcGridComponent;
+ private typeColumn: IgcColumnComponent;
+ private valueColumn: IgcColumnComponent;
+ private addId: number = 1000;
+
+ constructor() {
+ this.grid = document.getElementById('grid') as IgcHierarchicalGridComponent;
+ this.deleteRowColumn = document.getElementById('actionsColumn') as IgcColumnComponent;
+ this.addRowBtn = document.getElementById('addRowBtn') as IgcButtonComponent;
+ this.undoBtn = document.getElementById('undoBtn') as IgcButtonComponent;
+ this.redoBtn = document.getElementById('redoBtn') as IgcButtonComponent;
+ this.commitBtn = document.getElementById('commitBtn') as IgcButtonComponent;
+ this.discardBtn = document.getElementById('discardBtn') as IgcButtonComponent;
+ this.dialog = document.getElementById('dialog') as IgcDialogComponent;
+ this.transactionGrid = document.getElementById('transactionGrid') as IgcGridComponent;
+ this.typeColumn = document.getElementById('typeColumn') as IgcColumnComponent;
+ this.valueColumn = document.getElementById('valueColumn') as IgcColumnComponent;
+
+ this.grid.batchEditing = true;
+ this.grid.data = this.singersData;
+ this.deleteRowColumn.bodyTemplate = this.deleteRowColumnTemplate;
+ this.typeColumn.bodyTemplate = this.typeColumnTemplate;
+ this.valueColumn.bodyTemplate = this.valueColumnTemplate;
+
+ this.addRowBtn.addEventListener('click', this.onAddRowClick);
+ this.undoBtn.addEventListener('click', this.onUndoClick);
+ this.redoBtn.addEventListener('click', this.onRedoClick);
+ this.commitBtn.addEventListener('click', this.onOpenCommitDialog);
+ this.discardBtn.addEventListener('click', this.onDiscardClick);
+
+ document.getElementById('dialogCommitBtn')!.addEventListener('click', this.onCommitClick);
+ document.getElementById('dialogDiscardBtn')!.addEventListener('click', this.onDiscardClick);
+ document.getElementById('dialogCancelBtn')!.addEventListener('click', this.onCancelClick);
+
+ this.grid.transactions.onStateUpdate.subscribe(() => {
+ this.undoBtn.disabled = !this.grid.transactions.canUndo;
+ this.redoBtn.disabled = !this.grid.transactions.canRedo;
+ const hasChanges = this.grid.transactions.getAggregatedChanges(false).length > 0;
+ this.commitBtn.disabled = !hasChanges;
+ this.discardBtn.disabled = !hasChanges;
+ });
+ }
+
+ private _singersData: any[] = SingersData;
+ public get singersData(): any[] {
+ return this._singersData;
+ }
+
+ public deleteRowColumnTemplate = (ctx: IgcCellTemplateContext) => {
+ return html` this.onDeleteRowClick(ctx.cell.id.rowID)}>Delete `;
+ }
+
+ public typeColumnTemplate = (ctx: IgcCellTemplateContext) => {
+ const type = ctx.cell.value as string;
+ return html`${type.toUpperCase()} `;
+ }
+
+ public valueColumnTemplate = (ctx: IgcCellTemplateContext) => {
+ return html`${JSON.stringify(ctx.cell.value)} `;
+ }
+
+ public onAddRowClick = () => {
+ this.grid.addRow({
+ ID: this.addId++,
+ Artist: 'New Artist ' + this.randomInt(1, 100),
+ Debut: this.randomInt(1990, 2025),
+ GrammyNominations: this.randomInt(0, 20),
+ GrammyAwards: this.randomInt(0, 10),
+ HasGrammyAward: this.randomInt(0, 1) === 1,
+ Albums: [],
+ Tours: []
+ });
+ }
+
+ private randomInt(min: number, max: number): number {
+ return Math.floor(Math.random() * (max - min + 1)) + min;
+ }
+
+ public onUndoClick = () => {
+ this.grid.endEdit(true);
+ this.grid.transactions.undo();
+ }
+
+ public onRedoClick = () => {
+ this.grid.endEdit(true);
+ this.grid.transactions.redo();
+ }
+
+ public onOpenCommitDialog = () => {
+ this.transactionGrid.data = this.grid.transactions.getAggregatedChanges(true);
+ this.dialog.show();
+ }
+
+ public onCommitClick = () => {
+ this.grid.transactions.commit(this.grid.data);
+ this.dialog.hide();
+ }
+
+ public onDiscardClick = () => {
+ this.grid.transactions.clear();
+ this.dialog.hide();
+ }
+
+ public onCancelClick = () => {
+ this.dialog.hide();
+ }
+
+ public onDeleteRowClick = (rowId: any) => {
+ this.grid.deleteRow(rowId);
+ }
+
+}
+
+new HierarchicalGridBatchEditingSample();
diff --git a/samples/grids/hierarchical-grid/grid-batch-editing/tsconfig.json b/samples/grids/hierarchical-grid/grid-batch-editing/tsconfig.json
new file mode 100644
index 0000000000..02c7f095e6
--- /dev/null
+++ b/samples/grids/hierarchical-grid/grid-batch-editing/tsconfig.json
@@ -0,0 +1,42 @@
+{
+ "compilerOptions": {
+ "noImplicitReturns": true,
+ "esModuleInterop": true,
+ "resolveJsonModule": true,
+ "noImplicitAny": true,
+ "declarationDir": "dist/types",
+ "moduleResolution": "node",
+ "declaration": true,
+ "target": "es2015",
+ "module": "es2015",
+ "strict": true,
+ "skipLibCheck": true,
+ "strictNullChecks": false,
+ "baseUrl": ".",
+ "paths": {
+ "igniteui-webcomponents-core": [ "node_modules/igniteui-webcomponents-core", "node_modules/@infragistics/igniteui-webcomponents-core" ],
+ "igniteui-webcomponents-charts": [ "node_modules/igniteui-webcomponents-charts", "node_modules/@infragistics/igniteui-webcomponents-charts" ],
+ "igniteui-webcomponents-gauges": [ "node_modules/igniteui-webcomponents-gauges", "node_modules/@infragistics/igniteui-webcomponents-gauges" ],
+ "igniteui-webcomponents-datasources": [ "node_modules/igniteui-webcomponents-datasources", "node_modules/@infragistics/igniteui-webcomponents-datasources" ],
+ "igniteui-webcomponents-excel": [ "node_modules/igniteui-webcomponents-excel", "node_modules/@infragistics/igniteui-webcomponents-excel" ],
+ "igniteui-webcomponents-inputs": [ "node_modules/igniteui-webcomponents-inputs", "node_modules/@infragistics/igniteui-webcomponents-inputs" ],
+ "igniteui-webcomponents-grids": [ "node_modules/igniteui-webcomponents-grids", "node_modules/@infragistics/igniteui-webcomponents-grids" ],
+ "igniteui-webcomponents-maps": [ "node_modules/igniteui-webcomponents-maps", "node_modules/@infragistics/igniteui-webcomponents-maps" ],
+ "igniteui-webcomponents-spreadsheet": [ "node_modules/igniteui-webcomponents-spreadsheet", "node_modules/@infragistics/igniteui-webcomponents-spreadsheet" ],
+ "igniteui-webcomponents-spreadsheet-chart-adapter": [ "node_modules/igniteui-webcomponents-spreadsheet-chart-adapter", "node_modules/@infragistics/igniteui-webcomponents-spreadsheet-chart-adapter" ],
+ "igniteui-webcomponents-grids/*": [ "node_modules/igniteui-webcomponents-grids/*", "node_modules/@infragistics/igniteui-webcomponents-grids/*" ],
+ "igniteui-webcomponents-grids/grids": [ "node_modules/igniteui-webcomponents-grids/grids", "node_modules/@infragistics/igniteui-webcomponents-grids/grids" ],
+ "igniteui-webcomponents-grids/grids/*": [ "node_modules/igniteui-webcomponents-grids/grids/*", "node_modules/@infragistics/igniteui-webcomponents-grids/grids/*" ],
+ "igniteui-webcomponents-grids/grids/combined": [ "node_modules/igniteui-webcomponents-grids/grids/combined", "node_modules/@infragistics/igniteui-webcomponents-grids/grids/combined" ],
+ "igniteui-webcomponents-layouts": [ "node_modules/igniteui-webcomponents-layouts", "node_modules/@infragistics/igniteui-webcomponents-layouts" ],
+ "igniteui-webcomponents-dashboards": [ "node_modules/igniteui-webcomponents-dashboards", "node_modules/@infragistics/igniteui-webcomponents-dashboards" ]
+ }
+ },
+ "include": [
+ "src/**/*"
+ ],
+ "exclude": [
+ "node_modules",
+ "dist"
+ ]
+}
\ No newline at end of file
diff --git a/samples/grids/hierarchical-grid/grid-batch-editing/tslint.json b/samples/grids/hierarchical-grid/grid-batch-editing/tslint.json
new file mode 100644
index 0000000000..e3b56e93a1
--- /dev/null
+++ b/samples/grids/hierarchical-grid/grid-batch-editing/tslint.json
@@ -0,0 +1,54 @@
+{
+ "extends": ["tslint:recommended", "tslint-react", "tslint-config-prettier"],
+ "linterOptions": {
+ "exclude": [
+ "node_modules/**/*.ts",
+ "**/odatajs-4.0.0.js",
+ "src/images/*.*"
+ ]
+ },
+ "rules": {
+ "curly": [false, "ignore-same-line"],
+ "jsx-no-lambda": false,
+ "jsx-self-close": false,
+ "jsx-wrap-multiline": false,
+ "max-classes-per-file": [true, 10],
+ "member-ordering": false,
+ "no-console": false,
+ "no-string-literal": false,
+ "no-unused-vars": false,
+ "no-useless-constructor": false,
+ "no-trailing-whitespace": false,
+ "no-var": false,
+ "no-var-requires": false,
+ "no-var-keyword": false,
+ "ordered-imports": false,
+ "object-literal-sort-keys": false,
+ "object-literal-shorthand": false,
+ "only-arrow-functions": false,
+ "prefer-const": false,
+ "prefer-for-of": false,
+ "@typescript-eslint/no-unused-vars": "off",
+ "@typescript-eslint/no-useless-constructor": "off",
+ "@typescript-eslint/type-annotation-spacing": "off"
+ },
+ "jsRules": {
+ "curly": [false, "ignore-same-line"],
+ "jsx-no-lambda": false,
+ "jsx-self-close": false,
+ "jsx-wrap-multiline": false,
+ "max-classes-per-file": [true, 10],
+ "no-console": false,
+ "no-unused-vars": false,
+ "no-useless-constructor": false,
+ "no-var-requires": false,
+ "object-literal-sort-keys": false,
+ "object-literal-shorthand": false,
+ "only-arrow-functions": false,
+ "ordered-imports": false,
+ "prefer-const": false,
+ "prefer-for-of": false,
+ "@typescript-eslint/no-unused-vars": "off",
+ "@typescript-eslint/no-useless-constructor": "off"
+ }
+ }
\ No newline at end of file
diff --git a/samples/grids/hierarchical-grid/grid-batch-editing/webpack.config.js b/samples/grids/hierarchical-grid/grid-batch-editing/webpack.config.js
new file mode 100644
index 0000000000..90d8c30eaa
--- /dev/null
+++ b/samples/grids/hierarchical-grid/grid-batch-editing/webpack.config.js
@@ -0,0 +1,105 @@
+const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
+const HtmlWebpackPlugin = require('html-webpack-plugin');
+const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
+const path = require('path');
+const webpack = require('webpack');
+
+module.exports = env => {
+ const nodeEnv = process.env.NODE_ENV || 'development';
+ const isProd = nodeEnv === 'production';
+ const isLegacy = !!process.env.legacy && !(process.env.legacy == "false");
+ console.log(">> webpack nodeEnv=" + nodeEnv);
+ console.log(">> webpack isProd=" + isProd);
+ console.log(">> webpack isLegacy=" + isLegacy);
+ const presets = [
+ ["@babel/preset-env", {
+ "useBuiltIns": "usage",
+ "corejs": 3,
+ "targets": {
+ "browsers": isLegacy ? ["defaults"] : [
+ "last 2 Chrome versions",
+ "last 2 Safari versions",
+ "last 2 iOS versions",
+ "last 2 Firefox versions",
+ "last 2 Edge versions"]
+ }
+ }],
+ "@babel/preset-typescript"
+ ];
+
+ return {
+ entry: isLegacy ? [
+ path.resolve(__dirname, 'src')
+ ] : path.resolve(__dirname, 'src'),
+ devtool: isProd ? false : 'source-map',
+ output: {
+ filename: isProd ? '[fullhash].bundle.js' : '[fullhash].bundle.js',
+ globalObject: 'this',
+ path: path.resolve(__dirname, 'dist'),
+ },
+
+ resolve: {
+ mainFields: ['esm2015', 'module', 'main'],
+ extensions: ['.ts', '.js', '.json'],
+ plugins: [new TsconfigPathsPlugin({
+ configFile: './tsconfig.json',
+ extensions: ['.ts', '.js'],
+ mainFields: ['esm2015', 'module', 'main']
+ })]
+ },
+
+ module: {
+ rules: [
+ { test: /\.(png|svg|jpg|gif)$/, use: ['file-loader'] },
+ { test: /\.(csv|tsv)$/, use: ['csv-loader'] },
+ { test: /\.xml$/, use: ['xml-loader'] },
+ { test: /\.css$/, sideEffects: true, use: ['style-loader', 'css-loader'] },
+ {
+ test: /worker\.(ts|js)$/,
+ use: [
+ { loader: 'worker-loader' },
+ {
+ loader: 'babel-loader', options: {
+ "compact": isProd ? true : false,
+ "presets": presets,
+ "plugins": [
+ "@babel/plugin-transform-class-static-block",
+ "@babel/plugin-transform-class-properties",
+ "@babel/plugin-transform-runtime"
+ ]
+ }
+ }
+ ]
+ },
+ {
+ test: /\.(ts|js)$/, loader: 'babel-loader',
+ options: {
+ "compact": isProd ? true : false,
+ "presets": presets,
+ "plugins": [
+ "@babel/plugin-transform-class-static-block",
+ "@babel/plugin-transform-class-properties",
+ "@babel/plugin-transform-runtime"
+ ]
+ },
+ exclude:
+ function (modulePath) {
+ return /node_modules/.test(modulePath) &&
+ !/igniteui-webcomponents/.test(modulePath) &&
+ !/lit-html/.test(modulePath);
+ }
+ }],
+ },
+
+ plugins: [
+ new webpack.DefinePlugin({
+ 'process.env.NODE_ENV': JSON.stringify(nodeEnv)
+ }),
+ new HtmlWebpackPlugin({
+ title: 'Hierarchical Grid Batch Editing',
+ template: 'index.html'
+ }),
+ new ForkTsCheckerWebpackPlugin()
+ ]
+ };
+};
diff --git a/samples/grids/tree-grid/grid-batch-editing/.prettierrc b/samples/grids/tree-grid/grid-batch-editing/.prettierrc
new file mode 100644
index 0000000000..15a7c7c6cf
--- /dev/null
+++ b/samples/grids/tree-grid/grid-batch-editing/.prettierrc
@@ -0,0 +1,11 @@
+{
+ "printWidth": 250,
+ "tabWidth": 4,
+ "useTabs": false,
+ "semi": true,
+ "singleQuote": false,
+ "trailingComma": "none",
+ "bracketSpacing": true,
+ "jsxBracketSameLine": false,
+ "fluid": false
+}
\ No newline at end of file
diff --git a/samples/grids/tree-grid/grid-batch-editing/ReadMe.md b/samples/grids/tree-grid/grid-batch-editing/ReadMe.md
new file mode 100644
index 0000000000..46e4cea940
--- /dev/null
+++ b/samples/grids/tree-grid/grid-batch-editing/ReadMe.md
@@ -0,0 +1,56 @@
+
+
+
+This folder contains implementation of Web Components application with example of Batch Editing feature using [Tree Grid](https://infragistics.com/webcomponentssite/components/general-getting-started.html) component.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Branches
+
+> **_NOTE:_** You should use [master](https://github.com/IgniteUI/igniteui-angular-examples/tree/master) branch of this repository if you want to run samples on your computer. Use the [vnext](https://github.com/IgniteUI/igniteui-angular-examples/tree/vnext) branch only when you want to contribute new samples to this repository.
+
+## Instructions
+
+To set up this project locally, execute these commands:
+
+```
+git clone https://github.com/IgniteUI/igniteui-wc-examples.git
+git checkout master
+cd ./igniteui-wc-examples
+cd ./samples/grids/tree-grid/grid-batch-editing
+```
+
+open above folder in VS Code or type:
+```
+code .
+```
+
+In terminal window, run:
+
+```
+npm install
+npm run start
+```
+
+Then open http://localhost:4200/ in your browser
+
+
+## Learn More
+
+To learn more about **Ignite UI for Web Components**, check out the [Web Components documentation](https://infragistics.com/webcomponentssite/components/general-getting-started.html).
diff --git a/samples/grids/tree-grid/grid-batch-editing/index.html b/samples/grids/tree-grid/grid-batch-editing/index.html
new file mode 100644
index 0000000000..95ae2d2b07
--- /dev/null
+++ b/samples/grids/tree-grid/grid-batch-editing/index.html
@@ -0,0 +1,114 @@
+
+
+
+ Tree Grid Batch Editing | Ignite UI | Web Components | infragistics
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Commit
+ Discard
+ Cancel
+
+
+
+
+
+
+ <% if (false) { %><% } %>
+
+
diff --git a/samples/grids/tree-grid/grid-batch-editing/package.json b/samples/grids/tree-grid/grid-batch-editing/package.json
new file mode 100644
index 0000000000..2ebd6c4fc1
--- /dev/null
+++ b/samples/grids/tree-grid/grid-batch-editing/package.json
@@ -0,0 +1,60 @@
+{
+ "name": "example-ignite-ui-web-components",
+ "description": "This project provides example of using Ignite UI for Web Components",
+ "author": "Infragistics",
+ "version": "1.0.0",
+ "license": "",
+ "private": true,
+ "homepage": ".",
+ "main": "src/index.ts",
+ "scripts": {
+ "build": "npm run build:prod",
+ "build:dev": "webpack --mode development --config ./webpack.config.js --progress --color --display-error-details",
+ "build:prod": "webpack --env.NODE_ENV=production --mode production --config ./webpack.config.js --progress --color --display-error-details --bail",
+ "serve:dev": "node --max-old-space-size=8192 node_modules/webpack-dev-server/bin/webpack-dev-server.js --mode development --config ./webpack.config.js --hot --progress --open",
+ "serve:prod": "webpack-dev-server --env.NODE_ENV=production --mode production --config ./webpack.config.js --port 3000 --host 0.0.0.0 --hot --progress --open --content-base dist/",
+ "start": "npm run serve:dev",
+ "build:legacy": "npm run build:prod:legacy",
+ "build:dev:legacy": "webpack --env.legacy=true --mode development --config ./webpack.config.js --progress --color --display-error-details",
+ "build:prod:legacy": "webpack --env.NODE_ENV=production --env.legacy=true --mode production --config ./webpack.config.js --progress --color --display-error-details --bail",
+ "serve:dev:legacy": "node --max-old-space-size=8192 node_modules/webpack-dev-server/bin/webpack-dev-server.js --env.legacy=true --mode development --config ./webpack.config.js --hot --progress --open",
+ "serve:prod:legacy": "webpack-dev-server --env.NODE_ENV=production --env.legacy=true --mode production --config ./webpack.config.js --port 3000 --host 0.0.0.0 --hot --progress --open --content-base dist/",
+ "start:legacy": "npm run serve:dev:legacy"
+ },
+ "dependencies": {
+ "babel-runtime": "^6.26.0",
+ "igniteui-webcomponents-core": "6.3.1",
+ "igniteui-webcomponents-grids": "6.3.0-alpha.1",
+ "igniteui-webcomponents-inputs": "6.3.1",
+ "igniteui-webcomponents-layouts": "6.3.1",
+ "lit-html": "^3.3.1",
+ "tslib": "^2.8.1"
+ },
+ "devDependencies": {
+ "@babel/cli": "^7.28.3",
+ "@babel/core": "^7.28.4",
+ "@babel/plugin-transform-class-properties": "^7.27.1",
+ "@babel/plugin-transform-class-static-block": "^7.28.3",
+ "@babel/plugin-transform-runtime": "^7.28.3",
+ "@babel/preset-env": "^7.28.3",
+ "@babel/preset-typescript": "^7.27.1",
+ "@types/source-map": "^0.5.7",
+ "babel-loader": "^10.0.0",
+ "babel-plugin-transform-custom-element-classes": "^0.1.0",
+ "css-loader": "^7.1.2",
+ "csv-loader": "^3.0.5",
+ "file-loader": "^6.2.0",
+ "fork-ts-checker-webpack-plugin": "^9.1.0",
+ "html-webpack-plugin": "^5.6.4",
+ "parcel-bundler": "^1.12.5",
+ "source-map": "^0.7.6",
+ "style-loader": "^4.0.0",
+ "tsconfig-paths-webpack-plugin": "^4.2.0",
+ "typescript": "^5.9.2",
+ "webpack": "^5.101.3",
+ "webpack-cli": "^6.0.1",
+ "webpack-dev-server": "^5.2.2",
+ "worker-loader": "^3.0.8",
+ "xml-loader": "^1.2.1"
+ }
+}
diff --git a/samples/grids/tree-grid/grid-batch-editing/sandbox.config.json b/samples/grids/tree-grid/grid-batch-editing/sandbox.config.json
new file mode 100644
index 0000000000..52c7875103
--- /dev/null
+++ b/samples/grids/tree-grid/grid-batch-editing/sandbox.config.json
@@ -0,0 +1,6 @@
+{
+ "infiniteLoopProtection": false,
+ "hardReloadOnChange": false,
+ "view": "browser",
+ "template": "parcel"
+}
\ No newline at end of file
diff --git a/samples/grids/tree-grid/grid-batch-editing/src/EmployeesNestedTreeData.ts b/samples/grids/tree-grid/grid-batch-editing/src/EmployeesNestedTreeData.ts
new file mode 100644
index 0000000000..a51b020df3
--- /dev/null
+++ b/samples/grids/tree-grid/grid-batch-editing/src/EmployeesNestedTreeData.ts
@@ -0,0 +1,44 @@
+export class EmployeesNestedTreeDataItem {
+ public constructor(init: Partial) {
+ Object.assign(this, init);
+ }
+
+ public Age: number;
+ public HireDate: string;
+ public ID: number;
+ public Name: string;
+ public Phone: string;
+ public OnPTO: boolean;
+ public ParentID: number;
+ public Title: string;
+
+}
+export class EmployeesNestedTreeData extends Array {
+ public constructor(items: Array | number = -1) {
+ if (Array.isArray(items)) {
+ super(...items);
+ } else {
+ const newItems = [
+ new EmployeesNestedTreeDataItem({ Age: 55, HireDate: `2008-03-20`, ID: 1, Name: `Johnathan Winchester`, Phone: `0251-031259`, OnPTO: false, ParentID: -1, Title: `Development Manager` }),
+ new EmployeesNestedTreeDataItem({ Age: 42, HireDate: `2014-01-22`, ID: 4, Name: `Ana Sanders`, Phone: `(21) 555-0091`, OnPTO: true, ParentID: -1, Title: `CEO` }),
+ new EmployeesNestedTreeDataItem({ Age: 49, HireDate: `2014-01-22`, ID: 18, Name: `Victoria Lincoln`, Phone: `(071) 23 67 22 20`, OnPTO: true, ParentID: -1, Title: `Accounting Manager` }),
+ new EmployeesNestedTreeDataItem({ Age: 61, HireDate: `2010-01-01`, ID: 10, Name: `Yang Wang`, Phone: `(21) 555-0091`, OnPTO: false, ParentID: -1, Title: `Localization Manager` }),
+ new EmployeesNestedTreeDataItem({ Age: 43, HireDate: `2011-06-03`, ID: 3, Name: `Michael Burke`, Phone: `0452-076545`, OnPTO: true, ParentID: 1, Title: `Senior Software Developer` }),
+ new EmployeesNestedTreeDataItem({ Age: 29, HireDate: `2009-06-19`, ID: 2, Name: `Thomas Anderson`, Phone: `(14) 555-8122`, OnPTO: false, ParentID: 1, Title: `Senior Software Developer` }),
+ new EmployeesNestedTreeDataItem({ Age: 31, HireDate: `2014-08-18`, ID: 11, Name: `Monica Reyes`, Phone: `7675-3425`, OnPTO: false, ParentID: 1, Title: `Software Development Team Lead` }),
+ new EmployeesNestedTreeDataItem({ Age: 35, HireDate: `2015-09-17`, ID: 6, Name: `Roland Mendel`, Phone: `(505) 555-5939`, OnPTO: false, ParentID: 11, Title: `Senior Software Developer` }),
+ new EmployeesNestedTreeDataItem({ Age: 44, HireDate: `2009-10-11`, ID: 12, Name: `Sven Cooper`, Phone: `0695-34 67 21`, OnPTO: true, ParentID: 11, Title: `Senior Software Developer` }),
+ new EmployeesNestedTreeDataItem({ Age: 44, HireDate: `2014-04-04`, ID: 14, Name: `Laurence Johnson`, Phone: `981-443655`, OnPTO: false, ParentID: 4, Title: `Director` }),
+ new EmployeesNestedTreeDataItem({ Age: 25, HireDate: `2017-11-09`, ID: 5, Name: `Elizabeth Richards`, Phone: `(2) 283-2951`, OnPTO: true, ParentID: 4, Title: `Vice President` }),
+ new EmployeesNestedTreeDataItem({ Age: 39, HireDate: `2010-03-22`, ID: 13, Name: `Trevor Ashworth`, Phone: `981-443655`, OnPTO: true, ParentID: 5, Title: `Director` }),
+ new EmployeesNestedTreeDataItem({ Age: 44, HireDate: `2014-04-04`, ID: 17, Name: `Antonio Moreno`, Phone: `(505) 555-5939`, OnPTO: false, ParentID: 18, Title: `Senior Accountant` }),
+ new EmployeesNestedTreeDataItem({ Age: 50, HireDate: `2007-11-18`, ID: 7, Name: `Pedro Rodriguez`, Phone: `035-640230`, OnPTO: false, ParentID: 10, Title: `Senior Localization Developer` }),
+ new EmployeesNestedTreeDataItem({ Age: 27, HireDate: `2016-02-19`, ID: 8, Name: `Casey Harper`, Phone: `0342-023176`, OnPTO: true, ParentID: 10, Title: `Senior Localization` }),
+ new EmployeesNestedTreeDataItem({ Age: 25, HireDate: `2017-11-09`, ID: 15, Name: `Patricia Simpson`, Phone: `069-0245984`, OnPTO: false, ParentID: 7, Title: `Localization Intern` }),
+ new EmployeesNestedTreeDataItem({ Age: 39, HireDate: `2010-03-22`, ID: 9, Name: `Francisco Chang`, Phone: `(91) 745 6200`, OnPTO: false, ParentID: 7, Title: `Localization Intern` }),
+ new EmployeesNestedTreeDataItem({ Age: 25, HireDate: `2018-03-18`, ID: 16, Name: `Peter Lewis`, Phone: `069-0245984`, OnPTO: true, ParentID: 7, Title: `Localization Intern` }),
+ ];
+ super(...newItems.slice(0));
+ }
+ }
+}
diff --git a/samples/grids/tree-grid/grid-batch-editing/src/index.css b/samples/grids/tree-grid/grid-batch-editing/src/index.css
new file mode 100644
index 0000000000..94f5e82799
--- /dev/null
+++ b/samples/grids/tree-grid/grid-batch-editing/src/index.css
@@ -0,0 +1,39 @@
+/* shared styles are loaded from: */
+/* https://dl.infragistics.com/x/css/samples/shared.v8.css */
+
+#grid {
+ --ig-size: var(--ig-size-medium);
+}
+
+.buttons-wrapper {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ padding: 10px 0;
+}
+
+.buttons-right {
+ display: flex;
+ gap: 8px;
+}
+
+.dialog-buttons {
+ display: flex;
+ gap: 8px;
+ justify-content: flex-end;
+}
+
+.transaction--add {
+ color: #6b3;
+ font-weight: 600;
+}
+
+.transaction--update {
+ color: #4a71b9;
+ font-weight: 600;
+}
+
+.transaction--delete {
+ color: #ee4920;
+ font-weight: 600;
+}
diff --git a/samples/grids/tree-grid/grid-batch-editing/src/index.ts b/samples/grids/tree-grid/grid-batch-editing/src/index.ts
new file mode 100644
index 0000000000..aca42cc2d4
--- /dev/null
+++ b/samples/grids/tree-grid/grid-batch-editing/src/index.ts
@@ -0,0 +1,142 @@
+import 'igniteui-webcomponents-grids/grids/combined';
+import { IgcTreeGridComponent, IgcGridComponent, IgcColumnComponent } from 'igniteui-webcomponents-grids/grids';
+import { EmployeesNestedTreeData } from './EmployeesNestedTreeData';
+import { IgcCellTemplateContext } from 'igniteui-webcomponents-grids/grids';
+import { html } from 'lit-html';
+
+import "igniteui-webcomponents-grids/grids/themes/light/bootstrap.css";
+import 'igniteui-webcomponents/themes/light/bootstrap.css';
+import { defineAllComponents, IgcButtonComponent, IgcDialogComponent } from 'igniteui-webcomponents';
+defineAllComponents();
+
+import "./index.css";
+
+export class TreeGridBatchEditingSample {
+
+ private grid: IgcTreeGridComponent;
+ private deleteRowColumn: IgcColumnComponent;
+ private addRowBtn: IgcButtonComponent;
+ private undoBtn: IgcButtonComponent;
+ private redoBtn: IgcButtonComponent;
+ private commitBtn: IgcButtonComponent;
+ private discardBtn: IgcButtonComponent;
+ private dialog: IgcDialogComponent;
+ private transactionGrid: IgcGridComponent;
+ private typeColumn: IgcColumnComponent;
+ private valueColumn: IgcColumnComponent;
+ private addId: number = 1000;
+
+ constructor() {
+ this.grid = document.getElementById('grid') as IgcTreeGridComponent;
+ this.deleteRowColumn = document.getElementById('actionsColumn') as IgcColumnComponent;
+ this.addRowBtn = document.getElementById('addRowBtn') as IgcButtonComponent;
+ this.undoBtn = document.getElementById('undoBtn') as IgcButtonComponent;
+ this.redoBtn = document.getElementById('redoBtn') as IgcButtonComponent;
+ this.commitBtn = document.getElementById('commitBtn') as IgcButtonComponent;
+ this.discardBtn = document.getElementById('discardBtn') as IgcButtonComponent;
+ this.dialog = document.getElementById('dialog') as IgcDialogComponent;
+ this.transactionGrid = document.getElementById('transactionGrid') as IgcGridComponent;
+ this.typeColumn = document.getElementById('typeColumn') as IgcColumnComponent;
+ this.valueColumn = document.getElementById('valueColumn') as IgcColumnComponent;
+
+ this.grid.batchEditing = true;
+ this.grid.data = this.employeesData;
+ this.deleteRowColumn.bodyTemplate = this.deleteRowColumnTemplate;
+ this.typeColumn.bodyTemplate = this.typeColumnTemplate;
+ this.valueColumn.bodyTemplate = this.valueColumnTemplate;
+
+ this.addRowBtn.addEventListener('click', this.onAddRowClick);
+ this.undoBtn.addEventListener('click', this.onUndoClick);
+ this.redoBtn.addEventListener('click', this.onRedoClick);
+ this.commitBtn.addEventListener('click', this.onOpenCommitDialog);
+ this.discardBtn.addEventListener('click', this.onDiscardClick);
+
+ document.getElementById('dialogCommitBtn')!.addEventListener('click', this.onCommitClick);
+ document.getElementById('dialogDiscardBtn')!.addEventListener('click', this.onDiscardClick);
+ document.getElementById('dialogCancelBtn')!.addEventListener('click', this.onCancelClick);
+
+ this.grid.transactions.onStateUpdate.subscribe(() => {
+ this.undoBtn.disabled = !this.grid.transactions.canUndo;
+ this.redoBtn.disabled = !this.grid.transactions.canRedo;
+ const hasChanges = this.grid.transactions.getAggregatedChanges(false).length > 0;
+ this.commitBtn.disabled = !hasChanges;
+ this.discardBtn.disabled = !hasChanges;
+ });
+ }
+
+ private _employeesData: EmployeesNestedTreeData | null = null;
+ public get employeesData(): EmployeesNestedTreeData {
+ if (this._employeesData == null) {
+ this._employeesData = new EmployeesNestedTreeData();
+ }
+ return this._employeesData;
+ }
+
+ public deleteRowColumnTemplate = (ctx: IgcCellTemplateContext) => {
+ return html` this.onDeleteRowClick(ctx.cell.id.rowID)}>Delete `;
+ }
+
+ public typeColumnTemplate = (ctx: IgcCellTemplateContext) => {
+ const type = ctx.cell.value as string;
+ return html`${type.toUpperCase()} `;
+ }
+
+ public valueColumnTemplate = (ctx: IgcCellTemplateContext) => {
+ return html`${JSON.stringify(ctx.cell.value)} `;
+ }
+
+ public onAddRowClick = () => {
+ this.grid.addRow({
+ ID: this.addId++,
+ ParentID: -1,
+ Name: 'New Employee ' + this.randomInt(1, 100),
+ Title: 'Employee',
+ Age: this.randomInt(20, 60),
+ HireDate: new Date(this.randomInt(2000, 2025),
+ this.randomInt(0, 11), this.randomInt(1, 25))
+ .toISOString().slice(0, 10),
+ Phone: '555-' + this.randomInt(1000, 9999),
+ OnPTO: this.randomInt(0, 1) === 1
+ });
+ }
+
+ private randomInt(min: number, max: number): number {
+ return Math.floor(Math.random() * (max - min + 1)) + min;
+ }
+
+ public onUndoClick = () => {
+ this.grid.endEdit(true);
+ this.grid.transactions.undo();
+ }
+
+ public onRedoClick = () => {
+ this.grid.endEdit(true);
+ this.grid.transactions.redo();
+ }
+
+ public onOpenCommitDialog = () => {
+ this.transactionGrid.data = this.grid.transactions.getAggregatedChanges(true);
+ this.dialog.show();
+ }
+
+ public onCommitClick = () => {
+ this.grid.transactions.commit(this.grid.data);
+ this.dialog.hide();
+ }
+
+ public onDiscardClick = () => {
+ this.grid.transactions.clear();
+ this.dialog.hide();
+ }
+
+ public onCancelClick = () => {
+ this.dialog.hide();
+ }
+
+ public onDeleteRowClick = (rowId: any) => {
+ this.grid.deleteRow(rowId);
+ }
+
+}
+
+new TreeGridBatchEditingSample();
diff --git a/samples/grids/tree-grid/grid-batch-editing/tsconfig.json b/samples/grids/tree-grid/grid-batch-editing/tsconfig.json
new file mode 100644
index 0000000000..e7c370def4
--- /dev/null
+++ b/samples/grids/tree-grid/grid-batch-editing/tsconfig.json
@@ -0,0 +1,41 @@
+{
+ "compilerOptions": {
+ "noImplicitReturns": true,
+ "esModuleInterop": true,
+ "resolveJsonModule": true,
+ "noImplicitAny": true,
+ "declarationDir": "dist/types",
+ "moduleResolution": "node",
+ "declaration": true,
+ "target": "es2015",
+ "module": "es2015",
+ "strict": true,
+ "strictNullChecks": false,
+ "baseUrl": ".",
+ "paths": {
+ "igniteui-webcomponents-core": [ "node_modules/igniteui-webcomponents-core", "node_modules/@infragistics/igniteui-webcomponents-core" ],
+ "igniteui-webcomponents-charts": [ "node_modules/igniteui-webcomponents-charts", "node_modules/@infragistics/igniteui-webcomponents-charts" ],
+ "igniteui-webcomponents-gauges": [ "node_modules/igniteui-webcomponents-gauges", "node_modules/@infragistics/igniteui-webcomponents-gauges" ],
+ "igniteui-webcomponents-datasources": [ "node_modules/igniteui-webcomponents-datasources", "node_modules/@infragistics/igniteui-webcomponents-datasources" ],
+ "igniteui-webcomponents-excel": [ "node_modules/igniteui-webcomponents-excel", "node_modules/@infragistics/igniteui-webcomponents-excel" ],
+ "igniteui-webcomponents-inputs": [ "node_modules/igniteui-webcomponents-inputs", "node_modules/@infragistics/igniteui-webcomponents-inputs" ],
+ "igniteui-webcomponents-grids": [ "node_modules/igniteui-webcomponents-grids", "node_modules/@infragistics/igniteui-webcomponents-grids" ],
+ "igniteui-webcomponents-maps": [ "node_modules/igniteui-webcomponents-maps", "node_modules/@infragistics/igniteui-webcomponents-maps" ],
+ "igniteui-webcomponents-spreadsheet": [ "node_modules/igniteui-webcomponents-spreadsheet", "node_modules/@infragistics/igniteui-webcomponents-spreadsheet" ],
+ "igniteui-webcomponents-spreadsheet-chart-adapter": [ "node_modules/igniteui-webcomponents-spreadsheet-chart-adapter", "node_modules/@infragistics/igniteui-webcomponents-spreadsheet-chart-adapter" ],
+ "igniteui-webcomponents-grids/*": [ "node_modules/igniteui-webcomponents-grids/*", "node_modules/@infragistics/igniteui-webcomponents-grids/*" ],
+ "igniteui-webcomponents-grids/grids": [ "node_modules/igniteui-webcomponents-grids/grids", "node_modules/@infragistics/igniteui-webcomponents-grids/grids" ],
+ "igniteui-webcomponents-grids/grids/*": [ "node_modules/igniteui-webcomponents-grids/grids/*", "node_modules/@infragistics/igniteui-webcomponents-grids/grids/*" ],
+ "igniteui-webcomponents-grids/grids/combined": [ "node_modules/igniteui-webcomponents-grids/grids/combined", "node_modules/@infragistics/igniteui-webcomponents-grids/grids/combined" ],
+ "igniteui-webcomponents-layouts": [ "node_modules/igniteui-webcomponents-layouts", "node_modules/@infragistics/igniteui-webcomponents-layouts" ],
+ "igniteui-webcomponents-dashboards": [ "node_modules/igniteui-webcomponents-dashboards", "node_modules/@infragistics/igniteui-webcomponents-dashboards" ]
+ }
+ },
+ "include": [
+ "src/**/*"
+ ],
+ "exclude": [
+ "node_modules",
+ "dist"
+ ]
+}
\ No newline at end of file
diff --git a/samples/grids/tree-grid/grid-batch-editing/tslint.json b/samples/grids/tree-grid/grid-batch-editing/tslint.json
new file mode 100644
index 0000000000..e3b56e93a1
--- /dev/null
+++ b/samples/grids/tree-grid/grid-batch-editing/tslint.json
@@ -0,0 +1,54 @@
+{
+ "extends": ["tslint:recommended", "tslint-react", "tslint-config-prettier"],
+ "linterOptions": {
+ "exclude": [
+ "node_modules/**/*.ts",
+ "**/odatajs-4.0.0.js",
+ "src/images/*.*"
+ ]
+ },
+ "rules": {
+ "curly": [false, "ignore-same-line"],
+ "jsx-no-lambda": false,
+ "jsx-self-close": false,
+ "jsx-wrap-multiline": false,
+ "max-classes-per-file": [true, 10],
+ "member-ordering": false,
+ "no-console": false,
+ "no-string-literal": false,
+ "no-unused-vars": false,
+ "no-useless-constructor": false,
+ "no-trailing-whitespace": false,
+ "no-var": false,
+ "no-var-requires": false,
+ "no-var-keyword": false,
+ "ordered-imports": false,
+ "object-literal-sort-keys": false,
+ "object-literal-shorthand": false,
+ "only-arrow-functions": false,
+ "prefer-const": false,
+ "prefer-for-of": false,
+ "@typescript-eslint/no-unused-vars": "off",
+ "@typescript-eslint/no-useless-constructor": "off",
+ "@typescript-eslint/type-annotation-spacing": "off"
+ },
+ "jsRules": {
+ "curly": [false, "ignore-same-line"],
+ "jsx-no-lambda": false,
+ "jsx-self-close": false,
+ "jsx-wrap-multiline": false,
+ "max-classes-per-file": [true, 10],
+ "no-console": false,
+ "no-unused-vars": false,
+ "no-useless-constructor": false,
+ "no-var-requires": false,
+ "object-literal-sort-keys": false,
+ "object-literal-shorthand": false,
+ "only-arrow-functions": false,
+ "ordered-imports": false,
+ "prefer-const": false,
+ "prefer-for-of": false,
+ "@typescript-eslint/no-unused-vars": "off",
+ "@typescript-eslint/no-useless-constructor": "off"
+ }
+ }
\ No newline at end of file
diff --git a/samples/grids/tree-grid/grid-batch-editing/webpack.config.js b/samples/grids/tree-grid/grid-batch-editing/webpack.config.js
new file mode 100644
index 0000000000..0e55b75f1b
--- /dev/null
+++ b/samples/grids/tree-grid/grid-batch-editing/webpack.config.js
@@ -0,0 +1,105 @@
+const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
+const HtmlWebpackPlugin = require('html-webpack-plugin');
+const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
+const path = require('path');
+const webpack = require('webpack');
+
+module.exports = env => {
+ const nodeEnv = process.env.NODE_ENV || 'development';
+ const isProd = nodeEnv === 'production';
+ const isLegacy = !!process.env.legacy && !(process.env.legacy == "false");
+ console.log(">> webpack nodeEnv=" + nodeEnv);
+ console.log(">> webpack isProd=" + isProd);
+ console.log(">> webpack isLegacy=" + isLegacy);
+ const presets = [
+ ["@babel/preset-env", {
+ "useBuiltIns": "usage",
+ "corejs": 3,
+ "targets": {
+ "browsers": isLegacy ? ["defaults"] : [
+ "last 2 Chrome versions",
+ "last 2 Safari versions",
+ "last 2 iOS versions",
+ "last 2 Firefox versions",
+ "last 2 Edge versions"]
+ }
+ }],
+ "@babel/preset-typescript"
+ ];
+
+ return {
+ entry: isLegacy ? [
+ path.resolve(__dirname, 'src')
+ ] : path.resolve(__dirname, 'src'),
+ devtool: isProd ? false : 'source-map',
+ output: {
+ filename: isProd ? '[fullhash].bundle.js' : '[fullhash].bundle.js',
+ globalObject: 'this',
+ path: path.resolve(__dirname, 'dist'),
+ },
+
+ resolve: {
+ mainFields: ['esm2015', 'module', 'main'],
+ extensions: ['.ts', '.js', '.json'],
+ plugins: [new TsconfigPathsPlugin({
+ configFile: './tsconfig.json',
+ extensions: ['.ts', '.js'],
+ mainFields: ['esm2015', 'module', 'main']
+ })]
+ },
+
+ module: {
+ rules: [
+ { test: /\.(png|svg|jpg|gif)$/, use: ['file-loader'] },
+ { test: /\.(csv|tsv)$/, use: ['csv-loader'] },
+ { test: /\.xml$/, use: ['xml-loader'] },
+ { test: /\.css$/, sideEffects: true, use: ['style-loader', 'css-loader'] },
+ {
+ test: /worker\.(ts|js)$/,
+ use: [
+ { loader: 'worker-loader' },
+ {
+ loader: 'babel-loader', options: {
+ "compact": isProd ? true : false,
+ "presets": presets,
+ "plugins": [
+ "@babel/plugin-transform-class-static-block",
+ "@babel/plugin-transform-class-properties",
+ "@babel/plugin-transform-runtime"
+ ]
+ }
+ }
+ ]
+ },
+ {
+ test: /\.(ts|js)$/, loader: 'babel-loader',
+ options: {
+ "compact": isProd ? true : false,
+ "presets": presets,
+ "plugins": [
+ "@babel/plugin-transform-class-static-block",
+ "@babel/plugin-transform-class-properties",
+ "@babel/plugin-transform-runtime"
+ ]
+ },
+ exclude:
+ function (modulePath) {
+ return /node_modules/.test(modulePath) &&
+ !/igniteui-webcomponents/.test(modulePath) &&
+ !/lit-html/.test(modulePath);
+ }
+ }],
+ },
+
+ plugins: [
+ new webpack.DefinePlugin({
+ 'process.env.NODE_ENV': JSON.stringify(nodeEnv)
+ }),
+ new HtmlWebpackPlugin({
+ title: 'Tree Grid Batch Editing',
+ template: 'index.html'
+ }),
+ new ForkTsCheckerWebpackPlugin()
+ ]
+ };
+};