gridjs-spreadsheet 26.6.1 → 26.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/{a08275ef8caf83cc1c2eae91f17663e8.svg → 1f345d060b26fa53bc9d78c36441afd6.svg} +106 -26
  2. package/angular.d.ts +67 -0
  3. package/angular.js +174 -0
  4. package/example/README.md +242 -41
  5. package/example/angular-gridjs/.nvmrc +1 -0
  6. package/example/angular-gridjs/angular.json +66 -0
  7. package/example/angular-gridjs/package.json +31 -0
  8. package/example/angular-gridjs/proxy.conf.json +12 -0
  9. package/example/angular-gridjs/src/app/api.ts +7 -0
  10. package/example/angular-gridjs/src/app/app.component.html +57 -0
  11. package/example/angular-gridjs/src/app/app.component.ts +153 -0
  12. package/example/angular-gridjs/src/app/routing.ts +52 -0
  13. package/example/angular-gridjs/src/favicon.ico +0 -0
  14. package/example/angular-gridjs/src/index.html +12 -0
  15. package/example/angular-gridjs/src/main.ts +7 -0
  16. package/example/angular-gridjs/src/styles.css +37 -0
  17. package/example/angular-gridjs/tsconfig.app.json +9 -0
  18. package/example/angular-gridjs/tsconfig.json +29 -0
  19. package/example/pom.xml +3 -3
  20. package/example/react-gridjs/index.html +12 -0
  21. package/example/react-gridjs/package.json +20 -0
  22. package/example/react-gridjs/src/App.jsx +188 -0
  23. package/example/react-gridjs/src/api.js +7 -0
  24. package/example/react-gridjs/src/main.jsx +9 -0
  25. package/example/react-gridjs/src/routing.js +51 -0
  26. package/example/react-gridjs/src/styles.css +37 -0
  27. package/example/react-gridjs/vite.config.js +16 -0
  28. package/example/src/main/java/com/aspose/gridjs/demo/controller/DataController.java +80 -2
  29. package/example/src/main/java/com/aspose/gridjs/demo/controller/GridJs2Controller.java +12 -0
  30. package/example/vanilla-gridjs/npm/index.html +29 -0
  31. package/example/vanilla-gridjs/npm/main.js +8 -0
  32. package/example/vanilla-gridjs/npm/package.json +16 -0
  33. package/example/vanilla-gridjs/npm/vite.config.js +11 -0
  34. package/example/vanilla-gridjs/script/index.html +32 -0
  35. package/example/vanilla-gridjs/script/main.js +9 -0
  36. package/example/vanilla-gridjs/script/package.json +12 -0
  37. package/example/vanilla-gridjs/script/vite.config.js +11 -0
  38. package/example/vanilla-gridjs/shared/demo-app.js +205 -0
  39. package/example/vanilla-gridjs/shared/styles.css +36 -0
  40. package/example/vue-gridjs/index.html +12 -0
  41. package/example/vue-gridjs/package.json +19 -0
  42. package/example/vue-gridjs/src/App.vue +199 -0
  43. package/example/vue-gridjs/src/api.js +7 -0
  44. package/example/vue-gridjs/src/main.js +9 -0
  45. package/example/vue-gridjs/src/routing.js +51 -0
  46. package/example/vue-gridjs/src/styles.css +37 -0
  47. package/example/vue-gridjs/vite.config.js +21 -0
  48. package/index.d.ts +528 -472
  49. package/index.js +1 -1
  50. package/package.json +143 -50
  51. package/react.d.ts +27 -0
  52. package/react.js +111 -0
  53. package/readme.md +183 -380
  54. package/shared.d.ts +66 -0
  55. package/shared.js +204 -0
  56. package/vue.d.ts +20 -0
  57. package/vue.js +125 -0
  58. package/xspreadsheet.css +365 -1
  59. package/xspreadsheet.js +5 -5
  60. package/example/.mvn/wrapper/maven-wrapper.properties +0 -18
  61. package/example/src/test/java/com/aspose/gridjs/demo/GridjsdemoApplicationTests.java +0 -1441
package/example/README.md CHANGED
@@ -1,71 +1,272 @@
1
- [Product Page](https://products.aspose.com/cells/java) | [Docs](https://docs.aspose.com/cells/java/aspose-cells-gridjs/) | [API Reference](https://reference.aspose.com/cells/java/com.aspose.gridjs/) | [Demos](https://products.aspose.app/cells/family/) | [Blog](https://blog.aspose.com/category/cells/) | [Code Samples](https://github.com/aspose-cells/Aspose.Cells-for-Java/tree/master/Examples.GridJs) | [Free Support](https://forum.aspose.com/c/cells) | [Temporary License](https://purchase.aspose.com/temporary-license) | [EULA](https://company.aspose.com/legal/eula)
1
+ # Aspose.Cells GridJs Java framework examples
2
2
 
3
- Try our [free online apps](https://products.aspose.app/cells/family) demonstrating some of the most popular Aspose.Cells functionality.
3
+ This directory contains one Spring Boot backend shared by five independent frontend demos:
4
4
 
5
- [Aspose.Cells.GridJs for Java](http://www.aspose.com/products/cells/java) is a lightweight, scalable, and customizable toolkit that provides cross-platform web applications, enables convenient development for editing or viewing Excel/Spreadsheet files, offers simple deployment, and provides easy-to-use APIs.
5
+ | Demo | Directory | Development URL |
6
+ | --- | --- | --- |
7
+ | React | `react-gridjs` | `http://127.0.0.1:5173` |
8
+ | Vue 3 | `vue-gridjs` | `http://127.0.0.1:5174` |
9
+ | Angular | `angular-gridjs` | `http://127.0.0.1:4200` |
10
+ | Vanilla HTML with npm | `vanilla-gridjs/npm` | `http://127.0.0.1:5175` |
11
+ | Vanilla HTML with CDN scripts | `vanilla-gridjs/script` | `http://127.0.0.1:5176` |
6
12
 
7
- This is a demo to show how we can use GridJs to implment a spreadsheet Editor .
8
-
13
+ The frontend files are served by Vite or Angular CLI during development. They are not copied into the Java application. Each development server proxies GridJS API requests to the Java backend on port 8080.
9
14
 
10
- ## Preview
15
+ ## Requirements
11
16
 
12
- <img alt='demo' src='https://unpkg.com/gridjs-spreadsheet@25.1.0/preview.gif' />
17
+ - Java 8 or newer
18
+ - Node.js 18 or newer
19
+ - npm
20
+ - Angular demo: Node.js 18, 20, or 22
21
+
22
+ ## Configure the Java backend
23
+
24
+ Edit `src/main/resources/application.properties` when the default local paths do not match your environment:
13
25
 
14
- ## How to Run the Examples
15
- ###1.edit the properties in src\main\resources\application.properties to meet your local environment
16
26
  ```properties
17
- # This is the directory contains the spread sheet files
18
- testconfig.ListDir=/app/wb
27
+ testconfig.ListDir=/path/to/workbooks
28
+ testconfig.CachePath=/path/to/grid_cache
29
+ testconfig.UploadPath=/path/to/upload
30
+ testconfig.AsposeLicensePath=/path/to/license
31
+ ```
32
+
33
+ The repository example already contains local `wb`, `grid_cache`, and `upload` directories for development.
34
+
35
+ ## 1. Start the Java backend
36
+
37
+ Open the first terminal in this `example` directory.
38
+
39
+ macOS or Linux:
40
+
41
+ ```bash
42
+ ./mvnw spring-boot:run -Dmaven.test.skip=true
43
+ ```
44
+
45
+ Windows:
46
+
47
+ ```bat
48
+ mvnw.cmd spring-boot:run -Dmaven.test.skip=true
49
+ ```
50
+
51
+ Wait until Spring Boot is listening on:
52
+
53
+ ```text
54
+ http://127.0.0.1:8080
55
+ ```
56
+
57
+ Backend health endpoint:
58
+
59
+ ```text
60
+ http://127.0.0.1:8080/gridjsdemo/api/health
61
+ ```
62
+
63
+ The legacy server-rendered Java page remains available at:
64
+
65
+ ```text
66
+ http://127.0.0.1:8080/gridjsdemo/list
67
+ ```
68
+
69
+ ## 2. Start a frontend
70
+
71
+ Open a second terminal. Install dependencies inside the selected frontend folder, then run its npm development command.
19
72
 
20
- # Directory for storing cache files
21
- testconfig.CachePath=/app/grid_cache
73
+ ### React
22
74
 
23
- # Directory for storing upload files
24
- testconfig.UploadPath=/app/upload
75
+ ```bash
76
+ cd react-gridjs
77
+ npm install
78
+ npm run dev
79
+ ```
80
+
81
+ Open `http://127.0.0.1:5173`.
82
+
83
+ The application imports:
84
+
85
+ ```js
86
+ import { GridJsSpreadsheet } from 'gridjs-spreadsheet/react';
87
+ import 'gridjs-spreadsheet/xspreadsheet.css';
88
+ ```
25
89
 
26
- # License file for Aspose.Cells
27
- testconfig.AsposeLicensePath=/app/license
90
+ ### Vue 3
91
+
92
+ ```bash
93
+ cd vue-gridjs
94
+ npm install
95
+ npm run dev
28
96
  ```
29
- ###2.run src\main\java\com\aspose\gridjs\demo\GridjsdemoApplication.java
30
97
 
31
- open browser and navigate to view all the files in the directory at http://localhost:8080/gridjsdemo/list
98
+ Open `http://127.0.0.1:5174`.
99
+
100
+ The application imports:
32
101
 
33
- ## Step to run in docker
102
+ ```js
103
+ import { GridJsSpreadsheet } from 'gridjs-spreadsheet/vue';
104
+ import 'gridjs-spreadsheet/xspreadsheet.css';
105
+ ```
34
106
 
35
- 1. docker build -t gridjs-demo-java .
107
+ ### Angular
36
108
 
37
- 2. run with aspose license file:
109
+ Use Node.js 18, 20, or 22:
38
110
 
39
111
  ```bash
40
- docker run -d -p 8080:8080 -v C:/path/to/license.txt:/app/license gridjs-demo-java
112
+ cd angular-gridjs
113
+ npm install
114
+ npm run dev
115
+ ```
116
+
117
+ Open `http://127.0.0.1:4200`.
118
+
119
+ The application imports:
120
+
121
+ ```ts
122
+ import { GridJsSpreadsheetComponent } from 'gridjs-spreadsheet/angular';
41
123
  ```
42
124
 
43
- or just run the demo in trial mode:
44
-
125
+ ### Vanilla HTML with npm
126
+
45
127
  ```bash
46
- docker run -d -p 8080:8080 gridjs-demo-java
128
+ cd vanilla-gridjs/npm
129
+ npm install
130
+ npm run dev
131
+ ```
132
+
133
+ Open `http://127.0.0.1:5175`.
134
+
135
+ The application imports the GridJS runtime and stylesheet from npm:
136
+
137
+ ```js
138
+ import Spreadsheet from 'gridjs-spreadsheet';
139
+ import JSZip from 'jszip';
140
+ import 'gridjs-spreadsheet/xspreadsheet.css';
141
+
142
+ window.JSZip = JSZip;
47
143
  ```
48
-
49
- 3. open browser and enter the url: http://localhost:8080/gridjsdemo/list
50
144
 
51
- ## Reference js lib used in the demo project:
52
- jquery.js v2.1.1
145
+ ### Vanilla HTML with CDN script tags
146
+
147
+ ```bash
148
+ cd vanilla-gridjs/script
149
+ npm install
150
+ npm run dev
151
+ ```
53
152
 
54
- jquery-ui.js v1.12.1
153
+ Open `http://127.0.0.1:5176`.
55
154
 
56
- jquery-ui.css v1.12.1
155
+ This project loads GridJS and JSZip directly from CDN script tags. npm installs only the Vite development server.
57
156
 
58
- jszip.min.js v3.6.0
157
+ ## Why the frontend can access Java
59
158
 
60
- bootstrap.css v22.5.5.2
159
+ The frontend applications call relative URLs such as:
61
160
 
62
- quantumui.css v22.5.5.2
161
+ ```text
162
+ /gridjsdemo/api/files
163
+ /gridjsdemo/api/upload
164
+ /GridJs2/DetailStreamJsonWithUid
165
+ /GridJs2/UpdateCell
166
+ /GridJs2/Download
167
+ ```
168
+
169
+ Vite and Angular CLI proxy the `/gridjsdemo` and `/GridJs2` prefixes to `http://127.0.0.1:8080`:
170
+
171
+ ```text
172
+ Browser :5173/:5174/:4200/:5175/:5176
173
+ -> frontend development proxy
174
+ -> Java Spring Boot :8080
175
+ -> Aspose.Cells GridJs service
176
+ -> JSON response
177
+ -> frontend GridJS component
178
+ ```
179
+
180
+ The browser sees a same-origin request to its frontend server, so separate CORS configuration is not required for local development.
181
+
182
+ ## Open a workbook directly
183
+
184
+ After the backend and frontend are running, a workbook can be opened through query parameters:
185
+
186
+ ```text
187
+ http://127.0.0.1:5174/?file=chart.xlsx&demo=permanent&uid=vue-uid-chart-xlsx
188
+ ```
189
+
190
+ Supported demo modes:
191
+
192
+ - `permanent`: uses a UID-backed GridJS cache.
193
+ - `highlight`: loads the workbook without the persistent UID route.
194
+
195
+ ## Upload file names
196
+
197
+ Uploaded files use two names:
198
+
199
+ - `file`: the original name shown in GridJS and used for downloads.
200
+ - `storedFile`: the unique internal filename used by the Java upload directory.
201
+
202
+ The URL retains both values so a refreshed page can reopen the internal file while continuing to display the original filename.
203
+
204
+ ## Run multiple demos together
205
+
206
+ Start Java once, then run `npm run dev` in multiple frontend directories. Their ports are different, and their GridJS UIDs use different framework prefixes, so the demos do not conflict.
207
+
208
+ Stopping one frontend does not stop Java or the other frontend demos. Press `Ctrl+C` in each terminal to stop the corresponding process.
209
+
210
+ ## Production builds
211
+
212
+ Each frontend can be built independently:
213
+
214
+ ```bash
215
+ npm run build
216
+ ```
217
+
218
+ The output is written to that project's `dist` directory. This example intentionally demonstrates separate frontend development servers; it does not copy the frontend output into Spring Boot.
219
+
220
+ ## npm package version
221
+
222
+ Each npm-based frontend declares:
223
+
224
+ ```json
225
+ "gridjs-spreadsheet": "latest"
226
+ ```
227
+
228
+ Running `npm install` resolves the npm registry's current latest release. The framework exports used by these demos require `gridjs-spreadsheet` 26.7.0 or newer.
229
+
230
+ Package lock files are intentionally not published with the example. Users may generate their own lock files when installing dependencies.
231
+
232
+ ## Troubleshooting
233
+
234
+ ### Frontend reports `ECONNREFUSED` or proxy errors
235
+
236
+ Confirm that Java is running on port 8080 and open the health URL:
237
+
238
+ ```text
239
+ http://127.0.0.1:8080/gridjsdemo/api/health
240
+ ```
241
+
242
+ ### A frontend port is already occupied
243
+
244
+ Stop the existing process using that port. All frontend commands use strict ports to avoid silently opening a different URL.
245
+
246
+ ### Angular rejects the current Node.js version
247
+
248
+ Use Node.js 18, 20, or 22. Node.js 23 and newer are outside the supported range of the included Angular 18 project.
249
+
250
+ ### Framework import path cannot be resolved
251
+
252
+ Run `npm install` again and verify that the installed `gridjs-spreadsheet` version is 26.7.0 or newer.
253
+
254
+ ### Trial warning appears in the workbook
255
+
256
+ Configure `testconfig.AsposeLicensePath` with a valid Aspose.Cells license, or continue using the example in evaluation mode.
257
+
258
+ ## Docker
259
+
260
+ The Docker configuration runs the Java backend and legacy server-rendered page. The five framework demos remain separate npm development projects.
261
+
262
+ ```bash
263
+ docker build -t gridjs-demo-java .
264
+ docker run -d -p 8080:8080 gridjs-demo-java
265
+ ```
63
266
 
64
267
  ## Resources
65
268
 
66
- + **Website:** [www.aspose.com](http://www.aspose.com)
67
- + **Product Home:** [Aspose.Cells for Java](http://www.aspose.com/products/cells/java)
68
- + **Download:** [Download Aspose.Cells for Java](https://downloads.aspose.com/cells/java)
69
- + **Documentation:** [Aspose.Cells for Java Documentation](https://docs.aspose.com/display/cellsjava/Home)
70
- + **Forum:** [Aspose.Cells for Java Forum](http://www.aspose.com/community/forums/aspose.cells-product-family/19/showforum.aspx)
71
- + **Blog:** [Aspose.Cells for Java Blog](https://blog.aspose.com/category/aspose-products/aspose-cells-product-family/)
269
+ - [Aspose.Cells for Java](https://products.aspose.com/cells/java/)
270
+ - [Aspose.Cells GridJs documentation](https://docs.aspose.com/cells/java/aspose-cells-gridjs/)
271
+ - [GridJs Java API reference](https://reference.aspose.com/cells/java/com.aspose.gridjs/)
272
+ - [Aspose.Cells support forum](https://forum.aspose.com/c/cells)
@@ -0,0 +1 @@
1
+ 22
@@ -0,0 +1,66 @@
1
+ {
2
+ "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
3
+ "version": 1,
4
+ "newProjectRoot": "projects",
5
+ "projects": {
6
+ "gridjs-angular-demo": {
7
+ "projectType": "application",
8
+ "schematics": {},
9
+ "root": "",
10
+ "sourceRoot": "src",
11
+ "prefix": "app",
12
+ "architect": {
13
+ "build": {
14
+ "builder": "@angular-devkit/build-angular:application",
15
+ "options": {
16
+ "outputPath": "dist/gridjs-angular-demo",
17
+ "index": "src/index.html",
18
+ "browser": "src/main.ts",
19
+ "polyfills": ["zone.js"],
20
+ "tsConfig": "tsconfig.app.json",
21
+ "assets": ["src/favicon.ico"],
22
+ "allowedCommonJsDependencies": ["gridjs-spreadsheet", "jszip"],
23
+ "styles": [
24
+ "node_modules/gridjs-spreadsheet/xspreadsheet.css",
25
+ "src/styles.css"
26
+ ],
27
+ "scripts": []
28
+ },
29
+ "configurations": {
30
+ "production": {
31
+ "budgets": [
32
+ {
33
+ "type": "initial",
34
+ "maximumWarning": "5mb",
35
+ "maximumError": "8mb"
36
+ }
37
+ ],
38
+ "outputHashing": "all"
39
+ },
40
+ "development": {
41
+ "optimization": false,
42
+ "extractLicenses": false,
43
+ "sourceMap": true
44
+ }
45
+ },
46
+ "defaultConfiguration": "production"
47
+ },
48
+ "serve": {
49
+ "builder": "@angular-devkit/build-angular:dev-server",
50
+ "configurations": {
51
+ "production": {
52
+ "buildTarget": "gridjs-angular-demo:build:production"
53
+ },
54
+ "development": {
55
+ "buildTarget": "gridjs-angular-demo:build:development"
56
+ }
57
+ },
58
+ "defaultConfiguration": "development"
59
+ }
60
+ }
61
+ }
62
+ },
63
+ "cli": {
64
+ "analytics": false
65
+ }
66
+ }
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "gridjs-angular-java-demo",
3
+ "private": true,
4
+ "type": "module",
5
+ "scripts": {
6
+ "dev": "cross-env NG_BUILD_MAX_WORKERS=1 ng serve --host 127.0.0.1 --port 4200 --proxy-config proxy.conf.json",
7
+ "build": "cross-env NG_BUILD_MAX_WORKERS=1 ng build"
8
+ },
9
+ "dependencies": {
10
+ "@angular/animations": "18.2.14",
11
+ "@angular/common": "18.2.14",
12
+ "@angular/compiler": "18.2.14",
13
+ "@angular/core": "18.2.14",
14
+ "@angular/platform-browser": "18.2.14",
15
+ "gridjs-spreadsheet": "latest",
16
+ "jszip": "^3.10.1",
17
+ "rxjs": "~7.8.1",
18
+ "tslib": "^2.6.2",
19
+ "zone.js": "~0.14.10"
20
+ },
21
+ "devDependencies": {
22
+ "@angular-devkit/build-angular": "18.2.21",
23
+ "@angular/cli": "18.2.21",
24
+ "@angular/compiler-cli": "18.2.14",
25
+ "cross-env": "^7.0.3",
26
+ "typescript": "~5.5.4"
27
+ },
28
+ "engines": {
29
+ "node": ">=18 <23"
30
+ }
31
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "/GridJs2": {
3
+ "target": "http://127.0.0.1:8080",
4
+ "secure": false,
5
+ "changeOrigin": true
6
+ },
7
+ "/gridjsdemo": {
8
+ "target": "http://127.0.0.1:8080",
9
+ "secure": false,
10
+ "changeOrigin": true
11
+ }
12
+ }
@@ -0,0 +1,7 @@
1
+ // Small fetch() wrapper that turns non-2xx responses into thrown Errors,
2
+ // so callers can just `await fetchJson(url)` and catch failures in one place.
3
+ export async function fetchJson<T>(url: string, options?: RequestInit): Promise<T> {
4
+ const response = await fetch(url, options);
5
+ if (!response.ok) throw new Error(response.status + ' ' + response.statusText);
6
+ return response.json() as Promise<T>;
7
+ }
@@ -0,0 +1,57 @@
1
+ <!-- A workbook is selected -> render the full-page spreadsheet editor. -->
2
+ <main *ngIf="current; else startPage" class="editor-page">
3
+ <gridjs-spreadsheet
4
+ *ngIf="workbookData; else loadingEditor"
5
+ [data]="workbookData"
6
+ height="100vh"
7
+ [showToolbar]="true"
8
+ [showContextmenu]="true"
9
+ (ready)="onReady($event)"
10
+ (change)="logEvent('changed')"
11
+ (error)="onError($event)"
12
+ (cellSelected)="logEvent('cell selected ' + (($event && $event[1]) ?? '') + ',' + (($event && $event[2]) ?? ''))"
13
+ (cellEdited)="logEvent('cell edited ' + (($event && $event[1]) ?? '') + ',' + (($event && $event[2]) ?? ''))"
14
+ (sheetSelected)="logEvent('sheet ' + (($event && $event[1]) ?? ''))"
15
+ ></gridjs-spreadsheet>
16
+ <ng-template #loadingEditor>
17
+ <div class="editor-loading">{{ status }}</div>
18
+ </ng-template>
19
+ </main>
20
+
21
+ <!-- No workbook selected -> render the start page (demo picker + file list + upload). -->
22
+ <ng-template #startPage>
23
+ <div class="demo-shell">
24
+ <header class="demo-navbar">
25
+ <a href="https://docs.aspose.com/cells/java/aspose-cells-gridjs/">Aspose.Cells.GridJs demo for Java</a>
26
+ </header>
27
+ <main class="demo-container">
28
+ <fieldset class="demo-selector">
29
+ <legend>Select a demo:</legend>
30
+ <label [class]="demoType === DEMO_PERMANENT ? 'radio-card active' : 'radio-card'">
31
+ <input type="radio" name="demoType" [checked]="demoType === DEMO_PERMANENT" (change)="demoType = DEMO_PERMANENT" />
32
+ <span>permanent url load demo</span>
33
+ </label>
34
+ <label [class]="demoType === DEMO_HIGHLIGHT ? 'radio-card active' : 'radio-card'">
35
+ <input type="radio" name="demoType" [checked]="demoType === DEMO_HIGHLIGHT" (change)="demoType = DEMO_HIGHLIGHT" />
36
+ <span>highlight and custom context menu demo</span>
37
+ </label>
38
+ </fieldset>
39
+ <section class="upload-block">
40
+ <h4>Upload a local file to start show workbook</h4>
41
+ <input type="file" accept=".xlsx,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" (change)="upload($event)" />
42
+ </section>
43
+ <section class="path-block">
44
+ <h4>The specific file path : {{ directory }}</h4>
45
+ <h4>Navigate one of the below file to start show workbook</h4>
46
+ </section>
47
+ <p class="status-message" role="status">{{ status }}</p>
48
+ <section class="file-list" aria-label="Workbook files">
49
+ <p *ngIf="status === 'Ready' && files.length === 0" class="empty-message">No workbooks found in the configured directory.</p>
50
+ <a *ngFor="let file of files" [href]="'/?file=' + file" class="file-item" (click)="$event.preventDefault(); openFile(file)">
51
+ <em>{{ file }}</em>
52
+ </a>
53
+ </section>
54
+ </main>
55
+ <footer class="demo-footer">© 2026 - <a href="https://products.aspose.com/cells/java">Aspose.Cells for Java</a></footer>
56
+ </div>
57
+ </ng-template>
@@ -0,0 +1,153 @@
1
+ import { CommonModule } from '@angular/common';
2
+ import { Component, HostListener, OnInit } from '@angular/core';
3
+ import { GridJsSpreadsheetComponent } from 'gridjs-spreadsheet/angular';
4
+ import { DEMO_PERMANENT, DEMO_HIGHLIGHT, DemoType, WorkbookRef, makeUid, readRoute, pushWorkbookRoute } from './routing';
5
+ import { fetchJson } from './api';
6
+
7
+ // Root demo component.
8
+ // Renders either:
9
+ // - the start page (demo picker + sample file list + upload box), or
10
+ // - the full-page spreadsheet editor once a workbook has been selected.
11
+ // Which one is shown is driven entirely by the URL (see ./routing.ts).
12
+ @Component({
13
+ selector: 'app-root',
14
+ standalone: true,
15
+ imports: [CommonModule, GridJsSpreadsheetComponent],
16
+ templateUrl: './app.component.html',
17
+ })
18
+ export class AppComponent implements OnInit {
19
+ readonly DEMO_PERMANENT = DEMO_PERMANENT;
20
+ readonly DEMO_HIGHLIGHT = DEMO_HIGHLIGHT;
21
+
22
+ // Sample workbooks listed on the start page.
23
+ files: string[] = [];
24
+ directory = '';
25
+ // The workbook selected via the URL; null means "show the start page".
26
+ current: WorkbookRef | null = readRoute();
27
+ // Which demo mode is active (only relevant while on the start page).
28
+ demoType: DemoType = this.current?.demo || DEMO_PERMANENT;
29
+ workbookData: any = null;
30
+ status = 'Loading workbook list...';
31
+ adapter: any = null;
32
+
33
+ async ngOnInit(): Promise<void> {
34
+ await this.loadFiles();
35
+ if (this.current) await this.loadWorkbook();
36
+ }
37
+
38
+ // Keeps state in sync when the user navigates with the browser's back/forward buttons.
39
+ @HostListener('window:popstate')
40
+ onPopState(): void {
41
+ this.current = readRoute();
42
+ if (this.current?.demo) {
43
+ this.demoType = this.current.demo;
44
+ }
45
+ void this.loadWorkbook();
46
+ }
47
+
48
+ logEvent(message: string): void {
49
+ console.log('[GridJS Event]', message);
50
+ }
51
+
52
+ // Loads the list of sample workbooks available on the server.
53
+ async loadFiles(): Promise<void> {
54
+ try {
55
+ const result = await fetchJson<{ directory: string; files: string[] }>('/gridjsdemo/api/files');
56
+ this.files = result.files || [];
57
+ this.directory = result.directory || '';
58
+ this.status = 'Ready';
59
+ } catch (error: any) {
60
+ this.status = 'Failed to load files: ' + error.message;
61
+ }
62
+ }
63
+
64
+ // Navigates to a workbook: updates the URL and local state together.
65
+ openWorkbook(workbook: WorkbookRef): void {
66
+ const normalized = { ...workbook, demo: workbook.demo || this.demoType };
67
+ pushWorkbookRoute(normalized);
68
+ this.current = normalized;
69
+ this.demoType = normalized.demo;
70
+ void this.loadWorkbook();
71
+ }
72
+
73
+ openFile(file: string): void {
74
+ this.openWorkbook({ file, storedFile: file, demo: this.demoType, uid: makeUid(file), fromUpload: '' });
75
+ }
76
+
77
+ // Fetches workbook data for the GridJsSpreadsheet component. Which endpoint
78
+ // is used depends on the demo mode:
79
+ // - permanent: uid-based endpoint, backend caches parsed data per uid.
80
+ // - highlight: plain endpoint, re-parses the file on every load.
81
+ async loadWorkbook(): Promise<void> {
82
+ if (!this.current?.file) {
83
+ this.workbookData = null;
84
+ return;
85
+ }
86
+ this.workbookData = null;
87
+ this.adapter = null;
88
+ this.status = 'Loading ' + this.current.file + '...';
89
+ try {
90
+ const demo = this.current.demo || DEMO_PERMANENT;
91
+ const params = new URLSearchParams({
92
+ filename: this.current.storedFile || this.current.file,
93
+ fromUpload: this.current.fromUpload || '',
94
+ });
95
+ let endpoint = '/GridJs2/DetailStreamJson';
96
+ if (this.current.fromUpload) {
97
+ params.set('uid', this.current.uid || makeUid(this.current.file));
98
+ endpoint = '/GridJs2/DetailStreamJsonWithUidFromUpload';
99
+ } else if (demo === DEMO_PERMANENT) {
100
+ params.set('uid', this.current.uid || makeUid(this.current.file));
101
+ endpoint = '/GridJs2/DetailStreamJsonWithUid';
102
+ }
103
+ const payload = await fetchJson<any>(endpoint + '?' + params);
104
+ this.workbookData = { ...payload, filename: this.current.file };
105
+ this.status = 'Loaded ' + this.current.file;
106
+ } catch (error: any) {
107
+ this.status = 'Workbook load failed: ' + error.message;
108
+ }
109
+ }
110
+
111
+ async upload(event: Event): Promise<void> {
112
+ const input = event.target as HTMLInputElement;
113
+ const file = input.files?.[0];
114
+ if (!file) return;
115
+ const form = new FormData();
116
+ form.append('file', file);
117
+ form.append('client', 'angular');
118
+ this.status = 'Uploading ' + file.name + '...';
119
+ try {
120
+ const result = await fetchJson<{ file: string; displayName: string; uid: string; fromUpload: string }>('/gridjsdemo/api/upload', { method: 'POST', body: form });
121
+ this.logEvent('uploaded ' + result.file);
122
+ // Newly uploaded files live under the server's uploads dir, flagged with fromUpload=1.
123
+ this.openWorkbook({
124
+ file: result.displayName || file.name,
125
+ storedFile: result.file,
126
+ demo: this.demoType,
127
+ uid: result.uid || makeUid(result.file),
128
+ fromUpload: '1',
129
+ });
130
+ } catch (error: any) {
131
+ this.status = 'Upload failed: ' + error.message;
132
+ } finally {
133
+ input.value = '';
134
+ }
135
+ }
136
+
137
+ // Restores the previously active sheet/cell (from the workbook data) once
138
+ // the grid has mounted, and points the "open file" link back at the start page.
139
+ onReady(event: { instance: any; adapter: any }): void {
140
+ this.adapter = event.adapter;
141
+ const sheetName = event.adapter.payload?.actname;
142
+ const row = event.adapter.payload?.actrow;
143
+ const col = event.adapter.payload?.actcol;
144
+ event.instance?.setActiveSheetByName?.(sheetName)?.setActiveCell?.(row, col);
145
+ event.instance?.setOpenFileUrl?.('/');
146
+ this.logEvent('ready ' + (event.adapter.payload?.filename || this.current?.file));
147
+ }
148
+
149
+ onError(payload: any): void {
150
+ console.error(payload);
151
+ this.logEvent('error ' + (payload?.message || payload?.type || 'unknown'));
152
+ }
153
+ }