diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/README.md b/README.md index 41c8aac..e3eb4ed 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,109 @@ -# syncfusion-react-spreadsheet-data-binding -A comprehensive set of samples demonstrating data binding in the Syncfusion React Spreadsheet component. These examples show how to bind data from JSON, remote services, and dynamic APIs for real-time data visualization and editing in modern web applications. +# Syncfusion React Spreadsheet Data Binding + +A comprehensive sample demonstrating various data binding techniques in Syncfusion React Spreadsheet. It covers local data binding, remote data sources, custom column mapping, cell-level binding, and dynamic data updates for real-time data visualization and editing. + +## 📁 Project Structure + +``` +├── samples/localDataBinding +├── samples/cellDataBinding +├── samples/customColumn +├── samples/remoteDataBinding +├── samples/oDataRemoteDataBinding +├── samples/webApiRemoteDataBinding +├── samples/dynamicDataBinding +└── samples/updateRangeDynamicDataBinding +``` + +## ✨ Features + +- **Local Data Binding**: Bind JSON data directly to spreadsheet ranges for static datasets. +- **Cell Data Binding**: Populate individual cells with specific data values programmatically. +- **Custom Column Mapping**: Map custom field names from your data source to spreadsheet columns. +- **Remote Data Binding**: Fetch and bind data from remote REST APIs dynamically. +- **OData Remote Binding**: Connect to OData services for enterprise data integration. +- **Web API Integration**: Bind data from ASP.NET Core Web APIs with real-time synchronization. +- **Dynamic Data Binding**: Update spreadsheet data dynamically based on user interactions or events. +- **Update Range Binding**: Programmatically update specific ranges with new data without full reload. + +## 🧩 Technologies Used + +- React + Syncfusion Spreadsheet +- React Router (for sample navigation) +- REST APIs / OData / Web APIs + +## 🚀 Getting Started + +### 1. Clone the Repository + +```bash +git clone https://github.com/SyncfusionExamples/syncfusion-react-spreadsheet-data-binding +``` + +### 2. Install Dependencies + +Install the Syncfusion React Spreadsheet package as a dependency + +```bash +npm install @syncfusion/ej2-react-spreadsheet --save +``` + +### 3. Run the Application + +Run the project and explore different data binding samples using the dropdown + +```bash +npm run dev +``` + +## 📋 Sample Descriptions + +### Local Data Binding +Bind an array of JSON objects directly to the spreadsheet using the `dataSource` property within sheet configuration. + +### Cell Data Binding +Use the `updateCell()` method to bind data to individual cells for granular control over cell values. + +### Custom Column Mapping +Define custom field mappings when your data model field names differ from the desired column headers in the spreadsheet. + +### Remote Data Binding +Fetch data from remote REST APIs using fetch or axios and bind it to the spreadsheet for live data scenarios. + +### OData Remote Data Binding +Connect to OData services for standardized enterprise data access with filtering, sorting, and pagination support. + +### Web API Remote Data Binding +Integrate with ASP.NET Core Web APIs to fetch, update, and synchronize data between the spreadsheet and backend services. + +### Dynamic Data Binding +Implement real-time data updates based on user actions, timers, or external events to keep the spreadsheet data current. + +### Update Range Dynamic Data Binding +Use the `updateRange()` method to programmatically update specific cell ranges with new data without refreshing the entire sheet. + +## 🔗 Resources + +- [Syncfusion React Spreadsheet - Getting Started](https://help.syncfusion.com/document-processing/excel/spreadsheet/react/getting-started) +- [Syncfusion React Spreadsheet - Data Binding](https://help.syncfusion.com/document-processing/excel/spreadsheet/react/data-binding) +- [Syncfusion React Spreadsheet - API Reference](https://ej2.syncfusion.com/react/documentation/spreadsheet/api-spreadsheet) + +## ✅ Benefits + +- **Flexible Data Integration**: Connect to local JSON, REST APIs, OData, or Web APIs seamlessly. +- **Real-Time Updates**: Support dynamic data binding for live dashboards and collaborative applications. +- **Custom Mapping**: Adapt any data structure to your spreadsheet layout with custom column mapping. +- **Improved Performance**: Update only specific ranges instead of reloading entire datasets. +- **Enterprise Ready**: Built-in support for OData and Web API standards for enterprise-grade applications. + +## 📣 Try It Out + +Clone the repo, run the samples, and explore how to implement various data binding techniques in your React application! + +## 📄 License and Copyright + +> This is a commercial product and requires a paid license for possession or use. Syncfusion® licensed software, including this control, is subject to the terms and conditions of Syncfusion® [EULA](https://www.syncfusion.com/eula/es/). To acquire a license for 140+ [JavaScript UI controls](https://www.syncfusion.com/javascript-ui-controls), you can [purchase](https://www.syncfusion.com/sales/products) or [start a free 30-day trial](https://www.syncfusion.com/account/manage-trials/start-trials). + +> A [free community license](https://www.syncfusion.com/products/communitylicense) is also available for companies and individuals whose organizations have less than $1 million USD in annual gross revenue and five or fewer developers. + +See [LICENSE FILE](https://github.com/syncfusion/ej2-javascript-ui-controls/blob/master/license?utm_source=npm&utm_medium=listing&utm_campaign=javascript-spreadsheet-npm) for more info. \ No newline at end of file diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..4fa125d --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,29 @@ +import js from '@eslint/js' +import globals from 'globals' +import reactHooks from 'eslint-plugin-react-hooks' +import reactRefresh from 'eslint-plugin-react-refresh' +import { defineConfig, globalIgnores } from 'eslint/config' + +export default defineConfig([ + globalIgnores(['dist']), + { + files: ['**/*.{js,jsx}'], + extends: [ + js.configs.recommended, + reactHooks.configs.flat.recommended, + reactRefresh.configs.vite, + ], + languageOptions: { + ecmaVersion: 2020, + globals: globals.browser, + parserOptions: { + ecmaVersion: 'latest', + ecmaFeatures: { jsx: true }, + sourceType: 'module', + }, + }, + rules: { + 'no-unused-vars': ['error', { varsIgnorePattern: '^[A-Z_]' }], + }, + }, +]) diff --git a/index.html b/index.html new file mode 100644 index 0000000..d625ef0 --- /dev/null +++ b/index.html @@ -0,0 +1,13 @@ + + + + + + + my-app + + +
+ + + diff --git a/package.json b/package.json new file mode 100644 index 0000000..54daf8f --- /dev/null +++ b/package.json @@ -0,0 +1,40 @@ +{ + "name": "my-app", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "lint": "eslint .", + "preview": "vite preview" + }, + "dependencies": { + "@syncfusion/ej2-buttons": "*", + "@syncfusion/ej2-dropdowns": "*", + "@syncfusion/ej2-grids": "*", + "@syncfusion/ej2-inputs": "*", + "@syncfusion/ej2-lists": "*", + "@syncfusion/ej2-navigations": "*", + "@syncfusion/ej2-popups": "*", + "@syncfusion/ej2-react-base": "*", + "@syncfusion/ej2-react-splitbuttons": "*", + "@syncfusion/ej2-react-spreadsheet": "^32.2.9", + "@syncfusion/ej2-splitbuttons": "*", + "@syncfusion/ej2-spreadsheet": "*", + "react": "^19.2.0", + "react-dom": "^19.2.0", + "react-router-dom": "^7.12.0" + }, + "devDependencies": { + "@eslint/js": "^9.39.1", + "@types/react": "^19.2.7", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^5.1.1", + "eslint": "^9.39.1", + "eslint-plugin-react-hooks": "^7.0.1", + "eslint-plugin-react-refresh": "^0.4.24", + "globals": "^16.5.0", + "vite": "^7.3.1" + } +} diff --git a/public/vite.svg b/public/vite.svg new file mode 100644 index 0000000..e7b8dfb --- /dev/null +++ b/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/samples/cellDataBinding.jsx b/samples/cellDataBinding.jsx new file mode 100644 index 0000000..8690564 --- /dev/null +++ b/samples/cellDataBinding.jsx @@ -0,0 +1,96 @@ +import * as React from 'react'; +import { createRoot } from 'react-dom/client'; +import { SpreadsheetComponent, SheetsDirective, SheetDirective, RowsDirective, CellsDirective, RowDirective, CellDirective } from '@syncfusion/ej2-react-spreadsheet'; +import { ColumnsDirective, ColumnDirective } from '@syncfusion/ej2-react-spreadsheet'; + +function CellDataBinding() { + const spreadsheetRef = React.useRef(null); + React.useEffect(() => { + let spreadsheet = spreadsheetRef.current; + if (spreadsheet) { + spreadsheet.cellFormat( + { fontWeight: 'bold', textAlign: 'center', verticalAlign: 'middle' }, + 'A1:H1' + ); + } + }, []); + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +}; +export default CellDataBinding; \ No newline at end of file diff --git a/samples/customColumn.jsx b/samples/customColumn.jsx new file mode 100644 index 0000000..48c729a --- /dev/null +++ b/samples/customColumn.jsx @@ -0,0 +1,103 @@ +import * as React from 'react'; +import { createRoot } from 'react-dom/client'; +import { SpreadsheetComponent, SheetsDirective, SheetDirective, RangesDirective, RangeDirective, ColumnsDirective, ColumnDirective } from '@syncfusion/ej2-react-spreadsheet'; + +function CutomColumnMap() { + const spreadsheetRef = React.useRef(null); + React.useEffect(() => { + let spreadsheet = spreadsheetRef.current; + if (spreadsheet) { + spreadsheet.cellFormat( + { fontWeight: 'bold', textAlign: 'center', verticalAlign: 'middle' }, + 'A1:H1' + ); + } + }, []); + const data = [ + { + "Customer Name": "Romona Heaslip", + "Model": "Taurus", + "Color": "Aquamarine", + "Payment Mode": "Debit Card", + "Delivery Date": "07/11/2015", + "Amount": "8529.22" + }, + { + "Customer Name": "Clare Batterton", + "Model": "Sparrow", + "Color": "Pink", + "Payment Mode": "Cash On Delivery", + "Delivery Date": "7/13/2016", + "Amount": "17866.19" + }, + { + "Customer Name": "Eamon Traise", + "Model": "Grand Cherokee", + "Color": "Blue", + "Payment Mode": "Net Banking", + "Delivery Date": "09/04/2015", + "Amount": "13853.09" + }, + { + "Customer Name": "Julius Gorner", + "Model": "GTO", + "Color": "Aquamarine", + "Payment Mode": "Credit Card", + "Delivery Date": "12/15/2017", + "Amount": "2338.74" + }, + { + "Customer Name": "Jenna Schoolfield", + "Model": "LX", + "Color": "Yellow", + "Payment Mode": "Credit Card", + "Delivery Date": "10/08/2014", + "Amount": "9578.45" + }, + { + "Customer Name": "Marylynne Harring", + "Model": "Catera", + "Color": "Green", + "Payment Mode": "Cash On Delivery", + "Delivery Date": "7/01/2017", + "Amount": "19141.62" + }, + { + "Customer Name": "Vilhelmina Leipelt", + "Model": "7 Series", + "Color": "Goldenrod", + "Payment Mode": "Credit Card", + "Delivery Date": "12/20/2015", + "Amount": "6543.30" + }, + { + "Customer Name": "Barby Heisler", + "Model": "Corvette", + "Color": "Red", + "Payment Mode": "Credit Card", + "Delivery Date": "11/24/2014", + "Amount": "13035.06" + } + ]; + const fieldsOrder = ['Customer Name', 'Payment Mode', 'Model', 'Color', 'Amount', 'Delivery Date']; + return ( + + + + + + + + + + + + + + + + + + ); +}; +export default CutomColumnMap; \ No newline at end of file diff --git a/samples/dataSource.jsx b/samples/dataSource.jsx new file mode 100644 index 0000000..975ea7f --- /dev/null +++ b/samples/dataSource.jsx @@ -0,0 +1,158 @@ +/** + * Default data source + */ +export let defaultData = [ + { 'Item Name': 'Casual Shoes', Date: '02/14/2014', Time: '11:34:32 AM', Quantity: 10, Price: 20, Amount: 200, Discount: 1, Profit: 10 }, + { 'Item Name': 'Sports Shoes', Date: '06/11/2014', Time: '05:56:32 AM', Quantity: 20, Price: 30, Amount: 600, Discount: 5, Profit: 50 }, + { 'Item Name': 'Formal Shoes', Date: '07/27/2014', Time: '03:32:44 AM', Quantity: 20, Price: 15, Amount: 300, Discount: 7, Profit: 27 }, + { 'Item Name': 'Sandals & Floaters', Date: '11/21/2014', Time: '06:23:54 AM', Quantity: 15, Price: 20, Amount: 300, Discount: 11, Profit: 67 }, + { 'Item Name': 'Flip- Flops & Slippers', Date: '06/23/2014', Time: '12:43:59 AM', Quantity: 30, Price: 10, Amount: 300, Discount: 10, Profit: 70 }, + { 'Item Name': 'Sneakers', Date: '07/22/2014', Time: '10:55:53 AM', Quantity: 40, Price: 20, Amount: 800, Discount: 13, Profit: 66 }, + { 'Item Name': 'Running Shoes', Date: '02/04/2014', Time: '03:44:34 AM', Quantity: 20, Price: 10, Amount: 200, Discount: 3, Profit: 14 }, + { 'Item Name': 'Loafers', Date: '11/30/2014', Time: '03:12:52 AM', Quantity: 31, Price: 10, Amount: 310, Discount: 6, Profit: 29 }, + { 'Item Name': 'Cricket Shoes', Date: '07/09/2014', Time: '11:32:14 AM', Quantity: 41, Price: 30, Amount: 1210, Discount: 12, Profit: 166 }, + { 'Item Name': 'T-Shirts', Date: '10/31/2014', Time: '12:01:44 AM', Quantity: 50, Price: 10, Amount: 500, Discount: 9, Profit: 55 }, +]; + +export let itemData = [{ + 'Item Name': 'Casual Shoes', + Date: '02/14/2019', + Time: '11:34:32 AM', + Quantity: 10, + Price: 20, + Amount: '=D2*E2', + Discount: 1, + Profit: 10 +}, +{ + 'Item Name': 'Sports Shoes', + Date: '06/11/2019', + Time: '05:56:32 AM', + Quantity: 20, + Price: 30, + Amount: '=D3*E3', + Discount: 5, + Profit: 50 +}, +{ + 'Item Name': 'Formal Shoes', + Date: '07/27/2019', + Time: '03:32:44 AM', + Quantity: 20, + Price: 15, + Amount: '=D4*E4', + Discount: 7, + Profit: 27 +}, +{ + 'Item Name': 'Sandals & Floaters', + Date: '11/21/2019', + Time: '06:23:54 AM', + Quantity: 15, + Price: 20, + Amount: '=D5*E5', + Discount: 11, + Profit: 67 +}, +{ + 'Item Name': 'Flip- Flops & Slippers', + Date: '06/23/2019', + Time: '12:43:59 AM', + Quantity: 30, + Price: 10, + Amount: '=D6*E6', + Discount: 10, + Profit: 70 +}, +{ + 'Item Name': 'Sneakers', + Date: '07/22/2019', + Time: '10:55:53 AM', + Quantity: 40, + Price: 20, + Amount: '=D7*E7', + Discount: 13, + Profit: 66 +}, +{ + 'Item Name': 'Running Shoes', + Date: '02/04/2019', + Time: '03:44:34 AM', + Quantity: 20, + Price: 10, + Amount: '=D8*E8', + Discount: 3, + Profit: 14 +}, +{ + 'Item Name': 'Loafers', + Date: '11/30/2019', + Time: '03:12:52 AM', + Quantity: 31, + Price: 10, + Amount: '=D9*E9', + Discount: 6, + Profit: 29 +}, +{ + 'Item Name': 'Cricket Shoes', + Date: '07/09/2019', + Time: '11:32:14 AM', + Quantity: 41, + Price: 30, + Amount: '=D10*E10', + Discount: 12, + Profit: 166 +}, +{ + 'Item Name': 'T-Shirts', + Date: '10/31/2019', + Time: '12:01:44 AM', + Quantity: 50, + Price: 10, + Amount: '=D11*E11', + Discount: 9, + Profit: 55 +} +]; + +export let data = [{ + OrderID: 10248, + CustomerID: 'VINET', + EmployeeID: 5, + ShipName: 'Vins et alcools Chevalier', + ShipCity: 'Reims', + ShipAddress: '59 rue de lAbbaye' +}, +{ + OrderID: 10249, + CustomerID: 'TOMSP', + EmployeeID: 6, + ShipName: 'Toms Spezialitäten', + ShipCity: 'Münster', + ShipAddress: 'Luisenstr. 48' +}, +{ + OrderID: 10250, + CustomerID: 'HANAR', + EmployeeID: 4, + ShipName: 'Hanari Carnes', + ShipCity: 'Rio de Janeiro', + ShipAddress: 'Rua do Paço, 67' +}, +{ + OrderID: 10251, + CustomerID: 'VICTE', + EmployeeID: 3, + ShipName: 'Victuailles en stock', + ShipCity: 'Lyon', + ShipAddress: '2, rue du Commerce' +}, +{ + OrderID: 10252, + CustomerID: 'SUPRD', + EmployeeID: 4, + ShipName: 'Suprêmes délices', + ShipCity: 'Charleroi', + ShipAddress: 'Boulevard Tirou, 255' +}]; \ No newline at end of file diff --git a/samples/dynamicDataBinding.jsx b/samples/dynamicDataBinding.jsx new file mode 100644 index 0000000..38409bb --- /dev/null +++ b/samples/dynamicDataBinding.jsx @@ -0,0 +1,66 @@ +import * as React from 'react'; +import { createRoot } from 'react-dom/client'; +import { SpreadsheetComponent, SheetsDirective, SheetDirective, RangesDirective } from '@syncfusion/ej2-react-spreadsheet'; +import { RangeDirective, ColumnsDirective, ColumnDirective } from '@syncfusion/ej2-react-spreadsheet'; +import { defaultData, itemData } from './dataSource'; + +function DynamicDataBinding() { + const spreadsheetRef = React.useRef(null); + const dataSourceChanged = (args) => { + appendElement(`Data source changed with  ${args.action} action
`); + }; + const btnClick = () => { + const spreadsheet = spreadsheetRef.current; + if (spreadsheet) { + spreadsheet.sheets[0].ranges[0].dataSource = itemData; + } + }; + const clearBtnClick = () => { + const eventLog = document.getElementById('EventLog'); + if (eventLog) { + eventLog.innerHTML = ""; + } + }; + const appendElement = (html) => { + const span = document.createElement("span"); + span.innerHTML = html; + const log = document.getElementById('EventLog'); + if (log) { + log.insertBefore(span, log.firstChild); + } + }; + + return ( +
+
+ + + + + + + + + + + + + + + + + +
+
+

Event Trace

+
+
+ +
+ +
+
+
+ ); +}; +export default DynamicDataBinding; \ No newline at end of file diff --git a/samples/localDataBinding.jsx b/samples/localDataBinding.jsx new file mode 100644 index 0000000..2cb3c04 --- /dev/null +++ b/samples/localDataBinding.jsx @@ -0,0 +1,37 @@ +import * as React from 'react'; +import { createRoot } from 'react-dom/client'; +import { SpreadsheetComponent, SheetsDirective, SheetDirective, RangesDirective, RangeDirective, ColumnsDirective, ColumnDirective } from '@syncfusion/ej2-react-spreadsheet'; +import { data } from './dataSource'; + +function LocalDataBinding() { + const spreadsheetRef = React.useRef(null); + React.useEffect(() => { + let spreadsheet = spreadsheetRef.current; + if (spreadsheet) { + spreadsheet.cellFormat( + { fontWeight: 'bold', textAlign: 'center', verticalAlign: 'middle' }, + 'A1:H1' + ); + } + }, []); + return ( + + + + + + + + + + + + + + + + + + ); +}; +export default LocalDataBinding; \ No newline at end of file diff --git a/samples/oDataRemoteDataBinding.jsx b/samples/oDataRemoteDataBinding.jsx new file mode 100644 index 0000000..d9a5ce8 --- /dev/null +++ b/samples/oDataRemoteDataBinding.jsx @@ -0,0 +1,48 @@ +import * as React from 'react'; +import { createRoot } from 'react-dom/client'; +import { DataManager, ODataAdaptor } from '@syncfusion/ej2-data'; +import { SpreadsheetComponent, SheetsDirective, SheetDirective, RangesDirective } from '@syncfusion/ej2-react-spreadsheet'; +import { RangeDirective, ColumnsDirective, ColumnDirective } from '@syncfusion/ej2-react-spreadsheet'; + +function ODataRemoteDataBinding() { + const spreadsheetRef = React.useRef(null); + const data = (new DataManager({ + adaptor: new ODataAdaptor(), + url: 'https://services.syncfusion.com/react/production/api/Orders' + })); + + React.useEffect(() => { + let spreadsheet = spreadsheetRef.current + // Applies cell and number formatting to specified range of the active sheet + if (spreadsheet) { + spreadsheet.cellFormat({ fontWeight: 'bold', textAlign: 'center', verticalAlign: 'middle' }, 'A1:K1'); + } + }, []); + + return ( + + + + + + + + + + + + + + + + + + + + + + + ); +}; + +export default ODataRemoteDataBinding; \ No newline at end of file diff --git a/samples/remoteDataBinding.jsx b/samples/remoteDataBinding.jsx new file mode 100644 index 0000000..7f515c6 --- /dev/null +++ b/samples/remoteDataBinding.jsx @@ -0,0 +1,44 @@ +import * as React from 'react'; +import { createRoot } from 'react-dom/client'; +import { DataManager, Query } from '@syncfusion/ej2-data'; +import { SpreadsheetComponent, SheetsDirective, SheetDirective, RangesDirective } from '@syncfusion/ej2-react-spreadsheet'; +import { RangeDirective, ColumnsDirective, ColumnDirective } from '@syncfusion/ej2-react-spreadsheet'; + +function RemoteDataBinding() { + const spreadsheetRef = React.useRef(null); + React.useEffect(() => { + let spreadsheet = spreadsheetRef.current; + if (spreadsheet) { + spreadsheet.cellFormat( + { fontWeight: 'bold', textAlign: 'center', verticalAlign: 'middle' }, + 'A1:H1' + ); + } + }, []); + const query = new Query().select(['OrderID', 'CustomerID', 'ShipName', 'ShipCity', 'ShipCountry', 'Freight']).take(200); + const data = new DataManager({ + url: 'https://services.syncfusion.com/react/production/api/Orders', + crossDomain: true + }); + + return ( + + + + + + + + + + + + + + + + + + ); +}; +export default RemoteDataBinding; \ No newline at end of file diff --git a/samples/updateRangeDynamicDataBinding.jsx b/samples/updateRangeDynamicDataBinding.jsx new file mode 100644 index 0000000..e2aa4a5 --- /dev/null +++ b/samples/updateRangeDynamicDataBinding.jsx @@ -0,0 +1,131 @@ +import * as React from 'react'; +import { createRoot } from 'react-dom/client'; +import { SpreadsheetComponent, SheetsDirective, SheetDirective, RangesDirective } from '@syncfusion/ej2-react-spreadsheet'; +import { RangeDirective, ColumnsDirective, ColumnDirective, getRangeIndexes, getSwapRange, getRangeAddress } from '@syncfusion/ej2-react-spreadsheet'; +import { defaultData } from './dataSource'; +import { isNullOrUndefined } from '@syncfusion/ej2-base'; + +function UpdateRangeDynamicDataBinding() { + const spreadsheetRef = React.useRef(null); + const created = () => { + spreadsheetRef.current.cellFormat({ fontWeight: 'bold', textAlign: 'center', verticalAlign: 'middle' }, 'A1:F1'); + }; + + const updateDataCollection = () => { + const newDataCollection = { + dataSource: [ + { + 'Payment Mode': 'Debit Card', + 'Delivery Date': '07/11/2015', + 'Amount': '8529.22', + }, + { + 'Payment Mode': 'Cash On Delivery', + 'Delivery Date': '7/13/2016', + 'Amount': '17866.19', + }, + { + 'Payment Mode': 'Net Banking', + 'Delivery Date': '09/04/2015', + 'Amount': '13853.09', + }, + { + 'Payment Mode': 'Credit Card', + 'Delivery Date': '12/15/2017', + 'Amount': '2338.74', + }, + { + 'Payment Mode': 'Credit Card', + 'Delivery Date': '10/08/2014', + 'Amount': '9578.45', + }, + { + 'Payment Mode': 'Cash On Delivery', + 'Delivery Date': '7/01/2017', + 'Amount': '19141.62', + }, + { + 'Payment Mode': 'Credit Card', + 'Delivery Date': '12/20/2015', + 'Amount': '6543.30', + }, + { + 'Payment Mode': 'Credit Card', + 'Delivery Date': '11/24/2014', + 'Amount': '13035.06', + }, + { + 'Payment Mode': 'Debit Card', + 'Delivery Date': '05/12/2014', + 'Amount': '18488.80', + }, + { + 'Payment Mode': 'Net Banking', + 'Delivery Date': '12/30/2014', + 'Amount': '12317.04', + }, + { + 'Payment Mode': 'Credit Card', + 'Delivery Date': '12/18/2013', + 'Amount': '6230.13', + }, + { + 'Payment Mode': 'Cash On Delivery', + 'Delivery Date': '02/02/2015', + 'Amount': '9709.49', + }, + { + 'Payment Mode': 'Debit Card', + 'Delivery Date': '11/19/2014', + 'Amount': '9766.10', + }, + { + 'Payment Mode': 'Net Banking', + 'Delivery Date': '02/08/2014', + 'Amount': '7685.49', + }, + { + 'Payment Mode': 'Debit Card', + 'Delivery Date': '08/05/2016', + 'Amount': '18012.45', + }, + { + 'Payment Mode': 'Credit Card', + 'Delivery Date': '05/30/2016', + 'Amount': '2785.49', + }, + { + 'Payment Mode': 'Debit Card', + 'Delivery Date': '12/10/2016', + 'Amount': '9967.74', + }, + ], + startCell: 'D1', + }; + spreadsheetRef.current.updateRange(newDataCollection, 0) + } + + return ( +
+ + + + + + + + + + + + + + + + + + +
+ ); +}; +export default UpdateRangeDynamicDataBinding; \ No newline at end of file diff --git a/samples/webApiRemoteDataBinding.jsx b/samples/webApiRemoteDataBinding.jsx new file mode 100644 index 0000000..fe653b9 --- /dev/null +++ b/samples/webApiRemoteDataBinding.jsx @@ -0,0 +1,43 @@ +import * as React from 'react'; +import { createRoot } from 'react-dom/client'; +import { DataManager, WebApiAdaptor } from '@syncfusion/ej2-data'; +import { SpreadsheetComponent, SheetsDirective, SheetDirective, RangesDirective } from '@syncfusion/ej2-react-spreadsheet'; +import { RangeDirective, ColumnsDirective, ColumnDirective } from '@syncfusion/ej2-react-spreadsheet'; + +function WebApiRemoteDataBinding() { + const spreadsheetRef = React.useRef(null); + const data = (new DataManager({ adaptor: new WebApiAdaptor(), url: 'https://services.syncfusion.com/react/production/api/Orders' })); + React.useEffect(() => { + let spreadsheet = spreadsheetRef.current; + // Applies cell and number formatting to specified range of the active sheet + if (spreadsheet) { + spreadsheet.cellFormat({ fontWeight: 'bold', textAlign: 'center', verticalAlign: 'middle' }, 'A1:K1'); + } + }, []); + + return ( + + + + + + + + + + + + + + + + + + + + + + + ); +}; +export default WebApiRemoteDataBinding; \ No newline at end of file diff --git a/src/App.css b/src/App.css new file mode 100644 index 0000000..8986c5e --- /dev/null +++ b/src/App.css @@ -0,0 +1,10 @@ +@import '../node_modules/@syncfusion/ej2-base/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-inputs/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-buttons/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-splitbuttons/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-lists/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-navigations/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-popups/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-dropdowns/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-grids/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-react-spreadsheet/styles/material.css'; diff --git a/src/App.jsx b/src/App.jsx new file mode 100644 index 0000000..3da9369 --- /dev/null +++ b/src/App.jsx @@ -0,0 +1,52 @@ +import React from 'react'; +import { Routes, Route, useNavigate } from 'react-router-dom'; +import LocalDataBinding from '../samples/localDataBinding'; +import CutomColumnMap from '../samples/customColumn'; +import RemoteDataBinding from '../samples/remoteDataBinding'; +import ODataRemoteDataBinding from '../samples/oDataRemoteDataBinding'; +import WebApiRemoteDataBinding from '../samples/webApiRemoteDataBinding'; +import CellDataBinding from '../samples/cellDataBinding'; +import DynamicDataBinding from '../samples/dynamicDataBinding'; +import UpdateRangeDynamicDataBinding from '../samples/updateRangeDynamicDataBinding'; + +const App = () => { + const navigate = useNavigate(); + + const handleChange = (event) => { + navigate(event.target.value); // dynamically switch route + }; + + return ( +
+ {/* Dropdown for switching samples */} +
+ + +
+ + {/* Routes */} + + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + +
+ ); +}; + +export default App; diff --git a/src/assets/react.svg b/src/assets/react.svg new file mode 100644 index 0000000..6c87de9 --- /dev/null +++ b/src/assets/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/index.css b/src/index.css new file mode 100644 index 0000000..c5f656f --- /dev/null +++ b/src/index.css @@ -0,0 +1,10 @@ +@import '../node_modules/@syncfusion/ej2-base/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-inputs/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-buttons/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-splitbuttons/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-lists/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-navigations/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-popups/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-dropdowns/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-grids/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-react-spreadsheet/styles/material.css'; \ No newline at end of file diff --git a/src/main.jsx b/src/main.jsx new file mode 100644 index 0000000..c7493c6 --- /dev/null +++ b/src/main.jsx @@ -0,0 +1,13 @@ +import { StrictMode } from 'react' +import { createRoot } from 'react-dom/client' +import { BrowserRouter } from 'react-router-dom'; +import './index.css' +import App from './App.jsx' + +createRoot(document.getElementById('root')).render( + + + + + , +) diff --git a/vite.config.js b/vite.config.js new file mode 100644 index 0000000..8b0f57b --- /dev/null +++ b/vite.config.js @@ -0,0 +1,7 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' + +// https://vite.dev/config/ +export default defineConfig({ + plugins: [react()], +})