Demo DataGrid ExcelJSExportMultipleGrids remove odata#31567
Conversation
| import { Workbook } from 'devextreme-exceljs-fork'; | ||
| import { type DataGridCell as ExсelDataGridCell, exportDataGrid } from 'devextreme-vue/common/export/excel'; | ||
| import { type DataSourceOptions } from 'devextreme-vue/common/data'; | ||
| import { Product, products } from './data.ts'; |
| import { Workbook } from 'devextreme-exceljs-fork'; | ||
| import { saveAs } from 'file-saver-es'; | ||
| import { exportDataGrid } from 'devextreme-react/common/export/excel'; | ||
| import { Product, products } from './data.ts'; |
There was a problem hiding this comment.
Pull Request Overview
This PR refactors the ExcelJSExportMultipleGrids demo across all framework implementations (jQuery, Angular, React, ReactJs, and Vue) to replace remote OData service calls with local static data arrays. This improves demo performance, reduces external dependencies, and ensures consistent offline functionality.
Key changes:
- Replaced OData store configuration with local
productsdata arrays - Added
keyExprproperty to jQuery DataGrid configurations - Created new
data.js/data.tsfiles containing the Product class and products array for each framework - Imported
DataSourceOptionstype for TypeScript implementations
Reviewed Changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| apps/demos/Demos/DataGrid/ExcelJSExportMultipleGrids/jQuery/index.js | Replaced OData store with local products array and added keyExpr property |
| apps/demos/Demos/DataGrid/ExcelJSExportMultipleGrids/jQuery/index.html | Added script reference for data.js file |
| apps/demos/Demos/DataGrid/ExcelJSExportMultipleGrids/jQuery/data.js | New file containing static products array with 9 product records |
| apps/demos/Demos/DataGrid/ExcelJSExportMultipleGrids/Vue/data.ts | New file with Product class and typed products array for Vue |
| apps/demos/Demos/DataGrid/ExcelJSExportMultipleGrids/Vue/App.vue | Updated to import and use local products data instead of OData |
| apps/demos/Demos/DataGrid/ExcelJSExportMultipleGrids/ReactJs/data.js | New file with Product class (empty) and products array for ReactJs |
| apps/demos/Demos/DataGrid/ExcelJSExportMultipleGrids/ReactJs/App.js | Replaced OData store with local products data, removed unused import |
| apps/demos/Demos/DataGrid/ExcelJSExportMultipleGrids/React/data.ts | New file with Product class and typed products array for React TypeScript |
| apps/demos/Demos/DataGrid/ExcelJSExportMultipleGrids/React/App.tsx | Updated to import and use local products data, added DataSourceOptions typing |
| apps/demos/Demos/DataGrid/ExcelJSExportMultipleGrids/Angular/app/app.service.ts | New service file with Product class and products array, following Angular patterns |
| apps/demos/Demos/DataGrid/ExcelJSExportMultipleGrids/Angular/app/app.component.ts | Refactored to use Service dependency injection for data access |
| @@ -0,0 +1,75 @@ | |||
| export class Product {} | |||
There was a problem hiding this comment.
The empty Product class serves no purpose and should be removed. Unlike the TypeScript versions where it defines the type structure, in JavaScript this empty class export is unused and unnecessary.
| export class Product {} |
| import Button from 'devextreme-react/button'; | ||
| import TabPanel, { Item } from 'devextreme-react/tab-panel'; | ||
| import DataGrid, { Column, DataGridRef } from 'devextreme-react/data-grid'; | ||
| import { DataSourceOptions } from 'devextreme-angular/common/data'; |
There was a problem hiding this comment.
Incorrect import path: importing from 'devextreme-angular/common/data' in a React application. This should be 'devextreme-react/common/data' or 'devextreme/common/data' to match the framework being used.
| import { DataSourceOptions } from 'devextreme-angular/common/data'; | |
| import { DataSourceOptions } from 'devextreme/common/data'; |
| select: ['Product_ID', 'Product_Name', 'Product_Sale_Price', 'Product_Retail_Price'], | ||
| filter: ['Product_ID', '<', 10], | ||
| }; | ||
|
|
There was a problem hiding this comment.
Inconsistent whitespace: there's trailing whitespace on line 102. This should be removed to maintain code cleanliness.
| url: 'https://js.devexpress.com/Demos/DevAV/odata/Products', | ||
| key: 'Product_ID', | ||
| }, | ||
|
|
There was a problem hiding this comment.
Inconsistent whitespace: there's trailing whitespace on line 16. This should be removed to maintain code cleanliness.
| url: 'https://js.devexpress.com/Demos/DevAV/odata/Products', | ||
| key: 'Product_ID', | ||
| }, | ||
|
|
There was a problem hiding this comment.
Here there is a trailing space
| Product_Consumer_Rating: 4, | ||
| Product_Category: "Televisions", | ||
| }, | ||
| ]; No newline at end of file |
| Product_Consumer_Rating: 4, | ||
| Product_Category: "Televisions", | ||
| }, | ||
| ]; No newline at end of file |
| }, | ||
| ]; | ||
|
|
||
|
|
| select: ['Product_ID', 'Product_Name', 'Product_Sale_Price', 'Product_Retail_Price'], | ||
| filter: ['Product_ID', '<', 10], | ||
| }; | ||
|
|
There was a problem hiding this comment.
Extra line/trailing space here
There was a problem hiding this comment.
Pull Request Overview
Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (1)
apps/demos/Demos/DataGrid/ExcelJSExportMultipleGrids/Vue/App.vue:1
- [nitpick] Trailing zeros after the decimal point (e.g.,
220.00,330.00) are unnecessary in JavaScript/TypeScript numeric literals and will be stripped by the interpreter. For consistency with other data files and standard practices, these should be written as220.0or just220. This pattern appears throughout all data files in the PR.
<template>
| @@ -0,0 +1,75 @@ | |||
| export class Product {} | |||
There was a problem hiding this comment.
The Product class is exported but has no properties or implementation. It should either be removed as unused or properly implemented with properties matching the product data structure (Product_ID, Product_Name, etc.). Since TypeScript versions define the class properly, this appears to be unnecessarily exported.
| export class Product {} |
| Product_ID: number; | ||
|
|
||
| Product_Name: string; | ||
|
|
||
| Product_Sale_Price: number; | ||
|
|
||
| Product_Retail_Price: number; | ||
|
|
||
| Product_Consumer_Rating: number; | ||
|
|
||
| Product_Category: string; |
There was a problem hiding this comment.
TypeScript class properties should use the non-null assertion operator (!) or be marked as optional since they are not initialized in the constructor. The Vue version correctly uses ! for all properties, but this React TypeScript version is missing those assertions.
| Product_ID: number; | |
| Product_Name: string; | |
| Product_Sale_Price: number; | |
| Product_Retail_Price: number; | |
| Product_Consumer_Rating: number; | |
| Product_Category: string; | |
| Product_ID!: number; | |
| Product_Name!: string; | |
| Product_Sale_Price!: number; | |
| Product_Retail_Price!: number; | |
| Product_Consumer_Rating!: number; | |
| Product_Category!: string; |
| import Button from 'devextreme-react/button'; | ||
| import TabPanel, { Item } from 'devextreme-react/tab-panel'; | ||
| import DataGrid, { Column, DataGridRef } from 'devextreme-react/data-grid'; | ||
| import { DataSourceOptions } from 'devextreme/common/data'; |
There was a problem hiding this comment.
It seem should be
import { DataSourceOptions } from 'devextreme-react/common/data';
| @@ -0,0 +1,88 @@ | |||
| export class Product { | |||
| Product_ID!: number; | |||
| const ratingDataSource = { | ||
| store: { | ||
| type: 'odata', | ||
| version: 2, | ||
| url: 'https://js.devexpress.com/Demos/DevAV/odata/Products', | ||
| key: 'Product_ID', | ||
| }, | ||
| store: products, | ||
| select: ['Product_ID', 'Product_Name', 'Product_Consumer_Rating', 'Product_Category'], | ||
| filter: ['Product_ID', '<', 10], | ||
| }; |
There was a problem hiding this comment.
Potential bug: Using a raw array directly as the store value when the DataSource also uses select and filter operations may not work correctly. DevExtreme DataSource's select and filter are designed to work with store objects (like ArrayStore), not raw arrays. The jQuery implementation correctly wraps the array in an ArrayStore. Consider wrapping the products array in an ArrayStore with a key property:
import ArrayStore from 'devextreme/data/array_store';
const ratingDataSource = {
store: new ArrayStore({
data: products,
key: 'Product_ID',
}),
select: ['Product_ID', 'Product_Name', 'Product_Consumer_Rating', 'Product_Category'],
filter: ['Product_ID', '<', 10],
};| const priceDataSource: DataSourceOptions = { | ||
| store: products, | ||
| select: ['Product_ID', 'Product_Name', 'Product_Sale_Price', 'Product_Retail_Price'], | ||
| filter: ['Product_ID', '<', 10], | ||
| }; |
There was a problem hiding this comment.
Potential bug: Using a raw array directly as the store value when the DataSource also uses select and filter operations may not work correctly. DevExtreme DataSource's select and filter are designed to work with store objects (like ArrayStore), not raw arrays. The jQuery implementation correctly wraps the array in an ArrayStore. Consider wrapping the products array in an ArrayStore with a key property:
import ArrayStore from 'devextreme/data/array_store';
const priceDataSource: DataSourceOptions = {
store: new ArrayStore({
data: products,
key: 'Product_ID',
}),
select: ['Product_ID', 'Product_Name', 'Product_Sale_Price', 'Product_Retail_Price'],
filter: ['Product_ID', '<', 10],
};| const ratingDataSource: DataSourceOptions = { | ||
| store: products, | ||
| select: ['Product_ID', 'Product_Name', 'Product_Consumer_Rating', 'Product_Category'], | ||
| filter: ['Product_ID', '<', 10], | ||
| }; |
There was a problem hiding this comment.
Potential bug: Using a raw array directly as the store value when the DataSource also uses select and filter operations may not work correctly. DevExtreme DataSource's select and filter are designed to work with store objects (like ArrayStore), not raw arrays. The jQuery implementation correctly wraps the array in an ArrayStore. Consider wrapping the products array in an ArrayStore with a key property:
import ArrayStore from 'devextreme/data/array_store';
const ratingDataSource: DataSourceOptions = {
store: new ArrayStore({
data: products,
key: 'Product_ID',
}),
select: ['Product_ID', 'Product_Name', 'Product_Consumer_Rating', 'Product_Category'],
filter: ['Product_ID', '<', 10],
};| const ratingDataSource: DataSourceOptions = { | ||
| store: { | ||
| type: 'odata', | ||
| version: 2, | ||
| url: 'https://js.devexpress.com/Demos/DevAV/odata/Products', | ||
| key: 'Product_ID', | ||
| }, | ||
| store: products, | ||
| select: ['Product_ID', 'Product_Name', 'Product_Consumer_Rating', 'Product_Category'], | ||
| filter: ['Product_ID', '<', 10], | ||
| }; |
There was a problem hiding this comment.
Potential bug: Using a raw array directly as the store value when the DataSource also uses select and filter operations may not work correctly. DevExtreme DataSource's select and filter are designed to work with store objects (like ArrayStore), not raw arrays. The jQuery implementation correctly wraps the array in an ArrayStore. Consider wrapping the products array in an ArrayStore with a key property:
import ArrayStore from 'devextreme/data/array_store';
const ratingDataSource: DataSourceOptions = {
store: new ArrayStore({
data: products,
key: 'Product_ID',
}),
select: ['Product_ID', 'Product_Name', 'Product_Consumer_Rating', 'Product_Category'],
filter: ['Product_ID', '<', 10],
};| this.priceDataSource = { | ||
| store: service.getProducts(), | ||
| select: ['Product_ID', 'Product_Name', 'Product_Sale_Price', 'Product_Retail_Price'], | ||
| filter: ['Product_ID', '<', 10], | ||
| }; |
There was a problem hiding this comment.
Potential bug: Using a raw array directly as the store value when the DataSource also uses select and filter operations may not work correctly. DevExtreme DataSource's select and filter are designed to work with store objects (like ArrayStore), not raw arrays. The jQuery implementation correctly wraps the array in an ArrayStore. Consider wrapping the products array returned by service.getProducts() in an ArrayStore with a key property:
import ArrayStore from 'devextreme/data/array_store';
this.priceDataSource = {
store: new ArrayStore({
data: service.getProducts(),
key: 'Product_ID',
}),
select: ['Product_ID', 'Product_Name', 'Product_Sale_Price', 'Product_Retail_Price'],
filter: ['Product_ID', '<', 10],
};| const priceDataSource: DataSourceOptions = { | ||
| store: { | ||
| type: 'odata', | ||
| version: 2, | ||
| url: 'https://js.devexpress.com/Demos/DevAV/odata/Products', | ||
| key: 'Product_ID', | ||
| }, | ||
| store: products, | ||
| select: ['Product_ID', 'Product_Name', 'Product_Sale_Price', 'Product_Retail_Price'], | ||
| filter: ['Product_ID', '<', 10], | ||
| }; |
There was a problem hiding this comment.
Potential bug: Using a raw array directly as the store value when the DataSource also uses select and filter operations may not work correctly. DevExtreme DataSource's select and filter are designed to work with store objects (like ArrayStore), not raw arrays. The jQuery implementation correctly wraps the array in an ArrayStore. Consider wrapping the products array in an ArrayStore with a key property:
import ArrayStore from 'devextreme/data/array_store';
const priceDataSource: DataSourceOptions = {
store: new ArrayStore({
data: products,
key: 'Product_ID',
}),
select: ['Product_ID', 'Product_Name', 'Product_Sale_Price', 'Product_Retail_Price'],
filter: ['Product_ID', '<', 10],
};| this.ratingDataSource = { | ||
| store: service.getProducts(), | ||
| select: ['Product_ID', 'Product_Name', 'Product_Consumer_Rating', 'Product_Category'], | ||
| filter: ['Product_ID', '<', 10], | ||
| }; |
There was a problem hiding this comment.
Potential bug: Using a raw array directly as the store value when the DataSource also uses select and filter operations may not work correctly. DevExtreme DataSource's select and filter are designed to work with store objects (like ArrayStore), not raw arrays. The jQuery implementation correctly wraps the array in an ArrayStore. Consider wrapping the products array returned by service.getProducts() in an ArrayStore with a key property:
import ArrayStore from 'devextreme/data/array_store';
this.ratingDataSource = {
store: new ArrayStore({
data: service.getProducts(),
key: 'Product_ID',
}),
select: ['Product_ID', 'Product_Name', 'Product_Consumer_Rating', 'Product_Category'],
filter: ['Product_ID', '<', 10],
};| Product_ID: number = 0; | ||
|
|
||
| Product_Name: string = ''; | ||
|
|
||
| Product_Sale_Price: number = 0; | ||
|
|
||
| Product_Retail_Price: number = 0; | ||
|
|
||
| Product_Consumer_Rating: number = 0; | ||
|
|
||
| Product_Category: string = ''; |
There was a problem hiding this comment.
The Product class properties have default initializers (= 0, = '') which is unnecessary for a type-only class. This is inconsistent with the React TypeScript version where the class is used purely for typing. Consider either removing the default initializers or following the pattern in React/data.ts where properties are declared without initializers.
| Product_ID: number = 0; | |
| Product_Name: string = ''; | |
| Product_Sale_Price: number = 0; | |
| Product_Retail_Price: number = 0; | |
| Product_Consumer_Rating: number = 0; | |
| Product_Category: string = ''; | |
| Product_ID: number; | |
| Product_Name: string; | |
| Product_Sale_Price: number; | |
| Product_Retail_Price: number; | |
| Product_Consumer_Rating: number; | |
| Product_Category: string; |
| const priceDataSource = { | ||
| store: { | ||
| type: 'odata', | ||
| version: 2, | ||
| url: 'https://js.devexpress.com/Demos/DevAV/odata/Products', | ||
| key: 'Product_ID', | ||
| }, | ||
| store: products, | ||
| select: ['Product_ID', 'Product_Name', 'Product_Sale_Price', 'Product_Retail_Price'], | ||
| filter: ['Product_ID', '<', 10], | ||
| }; |
There was a problem hiding this comment.
Potential bug: Using a raw array directly as the store value when the DataSource also uses select and filter operations may not work correctly. DevExtreme DataSource's select and filter are designed to work with store objects (like ArrayStore), not raw arrays. The jQuery implementation correctly wraps the array in an ArrayStore. Consider wrapping the products array in an ArrayStore with a key property:
import ArrayStore from 'devextreme/data/array_store';
const priceDataSource = {
store: new ArrayStore({
data: products,
key: 'Product_ID',
}),
select: ['Product_ID', 'Product_Name', 'Product_Sale_Price', 'Product_Retail_Price'],
filter: ['Product_ID', '<', 10],
};| import { Workbook } from 'devextreme-exceljs-fork'; | ||
| import { saveAs } from 'file-saver-es'; | ||
| import { exportDataGrid } from 'devextreme-react/common/export/excel'; | ||
| import { products } from './data.ts'; |
There was a problem hiding this comment.
The .ts file extension should be omitted in TypeScript imports. In TypeScript/JavaScript module systems, file extensions are typically not included for local modules as the bundler/compiler resolves them automatically. Change to import { products } from './data';
| import { products } from './data.ts'; | |
| import { products } from './data'; |
| import { type DataGridCell as ExсelDataGridCell, exportDataGrid } from 'devextreme-vue/common/export/excel'; | ||
| import { type DataSourceOptions } from 'devextreme-vue/common/data'; | ||
| import { ArrayStore, type DataSourceOptions } from 'devextreme-vue/common/data'; | ||
| import { products } from './data.ts'; |
There was a problem hiding this comment.
The .ts file extension should be omitted in TypeScript imports. In TypeScript/JavaScript module systems, file extensions are typically not included for local modules as the bundler/compiler resolves them automatically. Change to import { products } from './data';
| import { products } from './data.ts'; | |
| import { products } from './data'; |
Replace OData with local arrays in the ExcelJSExportMultipleGrids demo