@handsontable/angular-wrapper 17.0.1 → 17.1.0-rc10
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.
- package/README.md +74 -0
- package/fesm2022/handsontable-angular-wrapper.mjs +100 -108
- package/fesm2022/handsontable-angular-wrapper.mjs.map +1 -1
- package/lib/editor/custom-editor-placeholder.component.d.ts +1 -1
- package/lib/editor/hot-cell-editor-advanced.component.d.ts +1 -1
- package/lib/editor/hot-cell-editor.component.d.ts +1 -1
- package/lib/hot-table.component.d.ts +10 -10
- package/lib/hot-table.module.d.ts +2 -6
- package/lib/renderer/hot-cell-renderer-advanced.component.d.ts +1 -1
- package/lib/renderer/hot-cell-renderer.component.d.ts +1 -1
- package/lib/services/hot-settings-resolver.service.d.ts +4 -5
- package/package.json +1 -1
- package/esm2022/handsontable-angular-wrapper.mjs +0 -5
- package/esm2022/lib/editor/base-editor-adapter.mjs +0 -180
- package/esm2022/lib/editor/custom-editor-placeholder.component.mjs +0 -89
- package/esm2022/lib/editor/editor-factory-adapter.mjs +0 -140
- package/esm2022/lib/editor/hot-cell-editor-advanced.component.mjs +0 -92
- package/esm2022/lib/editor/hot-cell-editor.component.mjs +0 -95
- package/esm2022/lib/editor/models/factory-editor-properties.mjs +0 -2
- package/esm2022/lib/editor/models/keyboard-shortcut-config.mjs +0 -2
- package/esm2022/lib/hot-table.component.mjs +0 -157
- package/esm2022/lib/hot-table.module.mjs +0 -29
- package/esm2022/lib/models/column-settings.mjs +0 -2
- package/esm2022/lib/models/grid-settings.mjs +0 -2
- package/esm2022/lib/renderer/hot-cell-renderer-advanced.component.mjs +0 -55
- package/esm2022/lib/renderer/hot-cell-renderer.component.mjs +0 -55
- package/esm2022/lib/renderer/hot-dynamic-renderer-component.service.mjs +0 -203
- package/esm2022/lib/services/hot-global-config.service.mjs +0 -107
- package/esm2022/lib/services/hot-settings-resolver.service.mjs +0 -170
- package/esm2022/public-api.mjs +0 -14
package/README.md
CHANGED
|
@@ -55,6 +55,9 @@
|
|
|
55
55
|
✅ [Hiding columns](https://handsontable.com/docs/angular-data-grid/column-hiding/) <br>
|
|
56
56
|
✅ [Right-click context menu](https://handsontable.com/docs/angular-data-grid/context-menu/) <br>
|
|
57
57
|
✅ [Row pagination](https://handsontable.com/docs/angular-data-grid/rows-pagination/) <br>
|
|
58
|
+
✅ [Server-side data](https://handsontable.com/docs/angular-data-grid/server-side-data/) <br>
|
|
59
|
+
✅ [Notifications](https://handsontable.com/docs/angular-data-grid/notification/) <br>
|
|
60
|
+
✅ [Export to Excel](https://handsontable.com/docs/angular-data-grid/export-to-excel/) <br>
|
|
58
61
|
|
|
59
62
|
<div id="installation">
|
|
60
63
|
|
|
@@ -134,6 +137,77 @@ export class HotTableWrapperComponent {
|
|
|
134
137
|
|
|
135
138
|
<br>
|
|
136
139
|
|
|
140
|
+
## ⏳ Lazy loading with `@defer` (Angular 17+)
|
|
141
|
+
|
|
142
|
+
`HotTableComponent` is a standalone component and works with Angular's built-in
|
|
143
|
+
`@defer` block out of the box — no extra configuration required.
|
|
144
|
+
|
|
145
|
+
### Recommended pattern
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
import { Component, signal } from '@angular/core';
|
|
149
|
+
import { HotTableComponent } from '@handsontable/angular-wrapper';
|
|
150
|
+
|
|
151
|
+
@Component({
|
|
152
|
+
standalone: true,
|
|
153
|
+
imports: [HotTableComponent],
|
|
154
|
+
template: `
|
|
155
|
+
<button (click)="show.set(true)">Load grid</button>
|
|
156
|
+
|
|
157
|
+
@defer (when show()) {
|
|
158
|
+
<hot-table [data]="data" [settings]="settings"></hot-table>
|
|
159
|
+
} @placeholder {
|
|
160
|
+
<p>Click the button to load the grid.</p>
|
|
161
|
+
} @loading (minimum 300ms) {
|
|
162
|
+
<p>Loading…</p>
|
|
163
|
+
} @error {
|
|
164
|
+
<p>Failed to load the grid.</p>
|
|
165
|
+
}
|
|
166
|
+
`,
|
|
167
|
+
})
|
|
168
|
+
export class PageComponent {
|
|
169
|
+
show = signal(false);
|
|
170
|
+
data = [['Alice', 'has'], ['Bob', 'data']];
|
|
171
|
+
settings = { rowHeaders: true, colHeaders: ['Name', 'Note'] };
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### How it works
|
|
176
|
+
|
|
177
|
+
| Block | When shown |
|
|
178
|
+
|---|---|
|
|
179
|
+
| `@defer (when show())` | renders `<hot-table>` after the signal becomes `true` |
|
|
180
|
+
| `@placeholder` | shown immediately before the trigger fires |
|
|
181
|
+
| `@loading (minimum 300ms)` | shown while the JS chunk is being fetched |
|
|
182
|
+
| `@error` | shown if the dynamic import fails |
|
|
183
|
+
|
|
184
|
+
### Other trigger options
|
|
185
|
+
|
|
186
|
+
```html
|
|
187
|
+
<!-- on viewport — loads when the placeholder scrolls into view -->
|
|
188
|
+
@defer (on viewport) { <hot-table …> }
|
|
189
|
+
|
|
190
|
+
<!-- on interaction — loads on first click/focus inside the placeholder -->
|
|
191
|
+
@defer (on interaction) { <hot-table …> }
|
|
192
|
+
|
|
193
|
+
<!-- on idle — loads during browser idle time -->
|
|
194
|
+
@defer (on idle) { <hot-table …> }
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Important: `registerAllModules()`
|
|
198
|
+
|
|
199
|
+
Call `registerAllModules()` in `app.config.ts` **before** the deferred block
|
|
200
|
+
triggers — it is synchronous and must run before any Handsontable instance is
|
|
201
|
+
created. The recommended place is at module level, outside any component:
|
|
202
|
+
|
|
203
|
+
```ts
|
|
204
|
+
// app.config.ts
|
|
205
|
+
import { registerAllModules } from 'handsontable/registry';
|
|
206
|
+
registerAllModules(); // runs once at app startup, safe with @defer
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
<br>
|
|
210
|
+
|
|
137
211
|
## 🎨 Themes
|
|
138
212
|
|
|
139
213
|
Handsontable themes control how your data table looks: colors, spacing, typography, borders, and overall visual style.
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { ViewContainerRef,
|
|
2
|
+
import { ViewContainerRef, ViewChild, Input, ChangeDetectionStrategy, Component, createComponent, EventEmitter, Output, HostBinding, Directive, Injectable, InjectionToken, Inject, ViewEncapsulation, NgModule } from '@angular/core';
|
|
3
|
+
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
3
4
|
import Handsontable from 'handsontable/base';
|
|
4
|
-
import { take } from 'rxjs/operators';
|
|
5
|
+
import { take, skip } from 'rxjs/operators';
|
|
5
6
|
import { editorFactory } from 'handsontable/editors/factory';
|
|
6
7
|
import { baseRenderer, rendererFactory, registerRenderer } from 'handsontable/renderers';
|
|
7
8
|
import { BehaviorSubject } from 'rxjs';
|
|
@@ -42,8 +43,8 @@ class CustomEditorPlaceholderComponent {
|
|
|
42
43
|
detachEditor() {
|
|
43
44
|
this.container.detach();
|
|
44
45
|
}
|
|
45
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
46
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "
|
|
46
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: CustomEditorPlaceholderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
47
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.21", type: CustomEditorPlaceholderComponent, isStandalone: true, selector: "ng-component", inputs: { top: "top", left: "left", height: "height", width: "width", isVisible: "isVisible", placeholderCustomClass: "placeholderCustomClass", componentRef: "componentRef" }, viewQueries: [{ propertyName: "container", first: true, predicate: ["inputPlaceholder"], descendants: true, read: ViewContainerRef, static: true }], ngImport: i0, template: ` <div
|
|
47
48
|
[class]="placeholderCustomClass"
|
|
48
49
|
[style.display]="display"
|
|
49
50
|
[style.width.px]="width"
|
|
@@ -56,7 +57,7 @@ class CustomEditorPlaceholderComponent {
|
|
|
56
57
|
<ng-template #inputPlaceholder></ng-template>
|
|
57
58
|
</div>`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
58
59
|
}
|
|
59
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
60
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: CustomEditorPlaceholderComponent, decorators: [{
|
|
60
61
|
type: Component,
|
|
61
62
|
args: [{
|
|
62
63
|
template: ` <div
|
|
@@ -72,7 +73,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
72
73
|
<ng-template #inputPlaceholder></ng-template>
|
|
73
74
|
</div>`,
|
|
74
75
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
75
|
-
standalone:
|
|
76
|
+
standalone: true,
|
|
76
77
|
}]
|
|
77
78
|
}], propDecorators: { top: [{
|
|
78
79
|
type: Input
|
|
@@ -297,14 +298,16 @@ class HotCellRendererComponent {
|
|
|
297
298
|
getProps() {
|
|
298
299
|
return this.cellProperties?.rendererProps ?? {};
|
|
299
300
|
}
|
|
300
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
301
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "
|
|
301
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: HotCellRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
302
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.21", type: HotCellRendererComponent, isStandalone: true, selector: "hot-cell-renderer", inputs: { value: "value", instance: "instance", td: "td", row: "row", col: "col", prop: "prop", cellProperties: "cellProperties" }, ngImport: i0, template: `<!-- This is an abstract component. Extend this component and provide your own template. -->`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
302
303
|
}
|
|
303
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
304
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: HotCellRendererComponent, decorators: [{
|
|
304
305
|
type: Component,
|
|
305
306
|
args: [{
|
|
306
307
|
selector: 'hot-cell-renderer',
|
|
307
|
-
template: `<!-- This is an abstract component. Extend this component and provide your own template.
|
|
308
|
+
template: `<!-- This is an abstract component. Extend this component and provide your own template. -->`,
|
|
309
|
+
standalone: true,
|
|
310
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
308
311
|
}]
|
|
309
312
|
}], propDecorators: { value: [{
|
|
310
313
|
type: Input
|
|
@@ -379,10 +382,10 @@ class HotCellEditorComponent {
|
|
|
379
382
|
setValue(value) {
|
|
380
383
|
this._value = value;
|
|
381
384
|
}
|
|
382
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
383
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "
|
|
385
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: HotCellEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
386
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.21", type: HotCellEditorComponent, isStandalone: true, inputs: { row: "row", column: "column", prop: "prop", originalValue: "originalValue", cellProperties: "cellProperties" }, outputs: { finishEdit: "finishEdit", cancelEdit: "cancelEdit" }, host: { properties: { "attr.tabindex": "this.tabindex", "attr.data-hot-input": "this.dataHotInput", "class.handsontableInput": "this.handsontableInputClass", "style.height.%": "this.heightFitParentContainer", "style.width.%": "this.widthFitParentContainer" } }, ngImport: i0 });
|
|
384
387
|
}
|
|
385
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
388
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: HotCellEditorComponent, decorators: [{
|
|
386
389
|
type: Directive
|
|
387
390
|
}], propDecorators: { tabindex: [{
|
|
388
391
|
type: HostBinding,
|
|
@@ -514,8 +517,8 @@ function applyPropsToEditor(editor) {
|
|
|
514
517
|
editor._componentRef.setInput('cellProperties', editor.cellProperties);
|
|
515
518
|
const rect = editor.hot.getCell(editor.row, editor.col)?.getBoundingClientRect();
|
|
516
519
|
editor._editorPlaceHolderRef.setInput('placeholderCustomClass', '');
|
|
517
|
-
editor._editorPlaceHolderRef.setInput('height', rect
|
|
518
|
-
editor._editorPlaceHolderRef.setInput('width', rect
|
|
520
|
+
editor._editorPlaceHolderRef.setInput('height', rect?.height ?? 0);
|
|
521
|
+
editor._editorPlaceHolderRef.setInput('width', rect?.width ?? 0);
|
|
519
522
|
editor._editorPlaceHolderRef.setInput('isVisible', true);
|
|
520
523
|
editor._editorPlaceHolderRef.setInput('componentRef', editor._componentRef);
|
|
521
524
|
editor._editorPlaceHolderRef.changeDetectorRef.detectChanges();
|
|
@@ -579,14 +582,16 @@ class HotCellRendererAdvancedComponent {
|
|
|
579
582
|
getProps() {
|
|
580
583
|
return this.cellProperties?.rendererProps ?? {};
|
|
581
584
|
}
|
|
582
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
583
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "
|
|
585
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: HotCellRendererAdvancedComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
586
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.21", type: HotCellRendererAdvancedComponent, isStandalone: true, selector: "hot-cell-renderer-advanced", inputs: { value: "value", instance: "instance", td: "td", row: "row", col: "col", prop: "prop", cellProperties: "cellProperties" }, ngImport: i0, template: `<!-- This is an abstract component. Extend this component and provide your own template. -->`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
584
587
|
}
|
|
585
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
588
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: HotCellRendererAdvancedComponent, decorators: [{
|
|
586
589
|
type: Component,
|
|
587
590
|
args: [{
|
|
588
591
|
selector: 'hot-cell-renderer-advanced',
|
|
589
592
|
template: `<!-- This is an abstract component. Extend this component and provide your own template. -->`,
|
|
593
|
+
standalone: true,
|
|
594
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
590
595
|
}]
|
|
591
596
|
}], propDecorators: { value: [{
|
|
592
597
|
type: Input
|
|
@@ -667,10 +672,10 @@ class HotCellEditorAdvancedComponent {
|
|
|
667
672
|
afterInit(editor) { }
|
|
668
673
|
/** Lifecycle hook called before the editor is opened. Available in advanced mode. */
|
|
669
674
|
beforeOpen(editor, { row, col, prop, td, originalValue, cellProperties, }) { }
|
|
670
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
671
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "
|
|
675
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: HotCellEditorAdvancedComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
676
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.21", type: HotCellEditorAdvancedComponent, isStandalone: true, inputs: { row: "row", column: "column", prop: "prop", originalValue: "originalValue", cellProperties: "cellProperties" }, outputs: { finishEdit: "finishEdit", cancelEdit: "cancelEdit" }, host: { properties: { "style.height.%": "this.heightFitParentContainer", "style.width.%": "this.widthFitParentContainer" } }, ngImport: i0 });
|
|
672
677
|
}
|
|
673
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
678
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: HotCellEditorAdvancedComponent, decorators: [{
|
|
674
679
|
type: Directive
|
|
675
680
|
}], propDecorators: { heightFitParentContainer: [{
|
|
676
681
|
type: HostBinding,
|
|
@@ -851,7 +856,7 @@ class DynamicComponentService {
|
|
|
851
856
|
environmentInjector: this.environmentInjector,
|
|
852
857
|
});
|
|
853
858
|
Object.keys(rendererParameters).forEach((key) => {
|
|
854
|
-
if (
|
|
859
|
+
if (Object.prototype.hasOwnProperty.call(rendererParameters, key)) {
|
|
855
860
|
componentRef.setInput(key, rendererParameters[key]);
|
|
856
861
|
}
|
|
857
862
|
else {
|
|
@@ -881,67 +886,56 @@ class DynamicComponentService {
|
|
|
881
886
|
this.appRef.detachView(componentRef.hostView);
|
|
882
887
|
componentRef.destroy();
|
|
883
888
|
}
|
|
884
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
885
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
889
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: DynamicComponentService, deps: [{ token: i0.ApplicationRef }, { token: i0.EnvironmentInjector }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
890
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: DynamicComponentService, providedIn: 'root' });
|
|
886
891
|
}
|
|
887
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
892
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: DynamicComponentService, decorators: [{
|
|
888
893
|
type: Injectable,
|
|
889
894
|
args: [{
|
|
890
895
|
providedIn: 'root',
|
|
891
896
|
}]
|
|
892
|
-
}], ctorParameters:
|
|
897
|
+
}], ctorParameters: () => [{ type: i0.ApplicationRef }, { type: i0.EnvironmentInjector }] });
|
|
893
898
|
|
|
894
|
-
const
|
|
895
|
-
const AVAILABLE_HOOKS = Handsontable.hooks.getRegistered();
|
|
899
|
+
const AVAILABLE_HOOKS_SET = new Set(Handsontable.hooks.getRegistered());
|
|
896
900
|
/**
|
|
897
901
|
* Service to resolve and apply custom settings for Handsontable settings object.
|
|
898
902
|
*/
|
|
899
903
|
class HotSettingsResolver {
|
|
900
904
|
dynamicComponentService;
|
|
901
905
|
environmentInjector;
|
|
902
|
-
|
|
906
|
+
ngZone;
|
|
907
|
+
constructor(dynamicComponentService, environmentInjector, ngZone) {
|
|
903
908
|
this.dynamicComponentService = dynamicComponentService;
|
|
904
909
|
this.environmentInjector = environmentInjector;
|
|
910
|
+
this.ngZone = ngZone;
|
|
905
911
|
}
|
|
906
912
|
/**
|
|
907
913
|
* Applies custom settings to the provided GridSettings.
|
|
908
914
|
* @param settings The original grid settings.
|
|
909
|
-
* @param ngZone The NgZone instance to run hooks inside the zone context.
|
|
910
915
|
* @returns The merged grid settings with custom settings applied.
|
|
911
916
|
*/
|
|
912
|
-
applyCustomSettings(settings
|
|
917
|
+
applyCustomSettings(settings) {
|
|
913
918
|
const mergedSettings = settings;
|
|
914
919
|
this.updateColumnRendererForGivenCustomRenderer(mergedSettings);
|
|
915
920
|
this.updateColumnEditorForGivenCustomEditor(mergedSettings);
|
|
916
921
|
this.updateColumnValidatorForGivenCustomValidator(mergedSettings);
|
|
917
|
-
this.wrapHooksInNgZone(mergedSettings
|
|
922
|
+
this.wrapHooksInNgZone(mergedSettings);
|
|
918
923
|
return mergedSettings ?? {};
|
|
919
924
|
}
|
|
920
925
|
/**
|
|
921
926
|
* Ensures that hook callbacks in the provided grid settings run inside Angular's zone.
|
|
922
927
|
*
|
|
923
928
|
* @param settings The original grid settings.
|
|
924
|
-
* @param ngZone The NgZone instance to run hooks inside the zone context.
|
|
925
929
|
*/
|
|
926
|
-
wrapHooksInNgZone(settings
|
|
927
|
-
const
|
|
928
|
-
|
|
929
|
-
const
|
|
930
|
-
|
|
931
|
-
if (isHook) {
|
|
932
|
-
option = settings[key];
|
|
933
|
-
}
|
|
934
|
-
if (option === void 0) {
|
|
935
|
-
return;
|
|
936
|
-
}
|
|
937
|
-
else if (!!ngZone && typeof option === 'function' && isHook) {
|
|
930
|
+
wrapHooksInNgZone(settings) {
|
|
931
|
+
const ngZone = this.ngZone;
|
|
932
|
+
AVAILABLE_HOOKS_SET.forEach((key) => {
|
|
933
|
+
const option = settings[key];
|
|
934
|
+
if (typeof option === 'function') {
|
|
938
935
|
settings[key] = function (...args) {
|
|
939
936
|
return ngZone.run(() => option.apply(this, args));
|
|
940
937
|
};
|
|
941
938
|
}
|
|
942
|
-
else {
|
|
943
|
-
settings[key] = option;
|
|
944
|
-
}
|
|
945
939
|
});
|
|
946
940
|
}
|
|
947
941
|
/**
|
|
@@ -1044,12 +1038,12 @@ class HotSettingsResolver {
|
|
|
1044
1038
|
this.isTemplateRef(renderer) ||
|
|
1045
1039
|
this.isAdvancedRendererComponentRefType(renderer);
|
|
1046
1040
|
}
|
|
1047
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1048
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
1041
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: HotSettingsResolver, deps: [{ token: DynamicComponentService }, { token: i0.EnvironmentInjector }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1042
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: HotSettingsResolver });
|
|
1049
1043
|
}
|
|
1050
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1044
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: HotSettingsResolver, decorators: [{
|
|
1051
1045
|
type: Injectable
|
|
1052
|
-
}], ctorParameters:
|
|
1046
|
+
}], ctorParameters: () => [{ type: DynamicComponentService }, { type: i0.EnvironmentInjector }, { type: i0.NgZone }] });
|
|
1053
1047
|
|
|
1054
1048
|
/**
|
|
1055
1049
|
* A constant representing the non-commercial and evaluation license.
|
|
@@ -1090,9 +1084,7 @@ class HotGlobalConfigService {
|
|
|
1090
1084
|
* @private
|
|
1091
1085
|
* @type {HotGlobalConfig}
|
|
1092
1086
|
*/
|
|
1093
|
-
defaultConfig = {
|
|
1094
|
-
license: undefined,
|
|
1095
|
-
};
|
|
1087
|
+
defaultConfig = {};
|
|
1096
1088
|
/**
|
|
1097
1089
|
* A BehaviorSubject that holds the current Handsontable configuration.
|
|
1098
1090
|
*
|
|
@@ -1142,54 +1134,50 @@ class HotGlobalConfigService {
|
|
|
1142
1134
|
resetConfig() {
|
|
1143
1135
|
this.configSubject.next({ ...this.defaultConfig });
|
|
1144
1136
|
}
|
|
1145
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1146
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
1137
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: HotGlobalConfigService, deps: [{ token: HOT_GLOBAL_CONFIG }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1138
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: HotGlobalConfigService, providedIn: 'root' });
|
|
1147
1139
|
}
|
|
1148
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1140
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: HotGlobalConfigService, decorators: [{
|
|
1149
1141
|
type: Injectable,
|
|
1150
1142
|
args: [{
|
|
1151
1143
|
providedIn: 'root',
|
|
1152
1144
|
}]
|
|
1153
|
-
}], ctorParameters:
|
|
1145
|
+
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
1154
1146
|
type: Inject,
|
|
1155
1147
|
args: [HOT_GLOBAL_CONFIG]
|
|
1156
|
-
}] }]
|
|
1148
|
+
}] }] });
|
|
1157
1149
|
|
|
1158
|
-
const HOT_DESTROYED_WARNING = 'The Handsontable instance bound to this component was destroyed and cannot be
|
|
1150
|
+
const HOT_DESTROYED_WARNING = 'The Handsontable instance bound to this component was destroyed and cannot be used properly.';
|
|
1159
1151
|
class HotTableComponent {
|
|
1160
1152
|
_hotSettingsResolver;
|
|
1161
1153
|
_hotConfig;
|
|
1162
1154
|
ngZone;
|
|
1163
1155
|
environmentInjector;
|
|
1164
|
-
|
|
1156
|
+
destroyRef;
|
|
1165
1157
|
/** The data for the Handsontable instance. */
|
|
1166
1158
|
data = null;
|
|
1167
1159
|
/** The settings for the Handsontable instance. */
|
|
1168
1160
|
settings = {};
|
|
1169
|
-
/** The container element for the Handsontable instance. */
|
|
1170
1161
|
container;
|
|
1171
1162
|
/** The Handsontable instance. */
|
|
1172
1163
|
__hotInstance = null;
|
|
1173
|
-
|
|
1174
|
-
constructor(_hotSettingsResolver, _hotConfig, ngZone, environmentInjector) {
|
|
1164
|
+
constructor(_hotSettingsResolver, _hotConfig, ngZone, environmentInjector, destroyRef) {
|
|
1175
1165
|
this._hotSettingsResolver = _hotSettingsResolver;
|
|
1176
1166
|
this._hotConfig = _hotConfig;
|
|
1177
1167
|
this.ngZone = ngZone;
|
|
1178
1168
|
this.environmentInjector = environmentInjector;
|
|
1169
|
+
this.destroyRef = destroyRef;
|
|
1179
1170
|
}
|
|
1180
1171
|
/**
|
|
1181
1172
|
* Gets the Handsontable instance.
|
|
1182
1173
|
* @returns The Handsontable instance or `null` if it's not yet been created or has been destroyed.
|
|
1183
1174
|
*/
|
|
1184
1175
|
get hotInstance() {
|
|
1185
|
-
if (
|
|
1186
|
-
// Will return the Handsontable instance or `null` if it's not yet been created.
|
|
1187
|
-
return this.__hotInstance;
|
|
1188
|
-
}
|
|
1189
|
-
else {
|
|
1176
|
+
if (this.__hotInstance?.isDestroyed) {
|
|
1190
1177
|
console.warn(HOT_DESTROYED_WARNING);
|
|
1191
1178
|
return null;
|
|
1192
1179
|
}
|
|
1180
|
+
return this.__hotInstance;
|
|
1193
1181
|
}
|
|
1194
1182
|
/**
|
|
1195
1183
|
* Sets the Handsontable instance.
|
|
@@ -1203,7 +1191,7 @@ class HotTableComponent {
|
|
|
1203
1191
|
* The initial settings of the table are also prepared here
|
|
1204
1192
|
*/
|
|
1205
1193
|
ngAfterViewInit() {
|
|
1206
|
-
let options = this._hotSettingsResolver.applyCustomSettings(this.settings
|
|
1194
|
+
let options = this._hotSettingsResolver.applyCustomSettings(this.settings);
|
|
1207
1195
|
const negotiatedSettings = this.getNegotiatedSettings(options);
|
|
1208
1196
|
options = { ...options, ...negotiatedSettings, data: this.data };
|
|
1209
1197
|
this.ngZone.runOutsideAngular(() => {
|
|
@@ -1211,7 +1199,7 @@ class HotTableComponent {
|
|
|
1211
1199
|
this.hotInstance._angularEnvironmentInjector = this.environmentInjector;
|
|
1212
1200
|
this.hotInstance.init();
|
|
1213
1201
|
});
|
|
1214
|
-
this.
|
|
1202
|
+
this._hotConfig.config$.pipe(skip(1), takeUntilDestroyed(this.destroyRef)).subscribe(() => {
|
|
1215
1203
|
if (this.hotInstance) {
|
|
1216
1204
|
const negotiatedSettings = this.getNegotiatedSettings(this.settings);
|
|
1217
1205
|
this.updateHotTable(negotiatedSettings);
|
|
@@ -1223,32 +1211,36 @@ class HotTableComponent {
|
|
|
1223
1211
|
return;
|
|
1224
1212
|
}
|
|
1225
1213
|
if (changes.settings && !changes.settings.firstChange) {
|
|
1226
|
-
|
|
1227
|
-
this.
|
|
1214
|
+
this.destroyEditorComponentRefs();
|
|
1215
|
+
const newOptions = this._hotSettingsResolver.applyCustomSettings(changes.settings.currentValue);
|
|
1216
|
+
const dataChanged = changes.data && !changes.data.firstChange;
|
|
1217
|
+
this.updateHotTable(dataChanged ? { ...newOptions, data: changes.data.currentValue } : newOptions);
|
|
1218
|
+
return;
|
|
1228
1219
|
}
|
|
1229
1220
|
if (changes.data && !changes.data.firstChange) {
|
|
1230
|
-
this.
|
|
1221
|
+
this.ngZone.runOutsideAngular(() => {
|
|
1222
|
+
this.hotInstance.updateData(changes.data.currentValue);
|
|
1223
|
+
});
|
|
1231
1224
|
}
|
|
1232
1225
|
}
|
|
1233
1226
|
/**
|
|
1234
1227
|
* Destroys the Handsontable instance and clears the columns from custom editors.
|
|
1235
1228
|
*/
|
|
1236
1229
|
ngOnDestroy() {
|
|
1230
|
+
if (!this.hotInstance) {
|
|
1231
|
+
return;
|
|
1232
|
+
}
|
|
1233
|
+
this.destroyEditorComponentRefs();
|
|
1237
1234
|
this.ngZone.runOutsideAngular(() => {
|
|
1238
|
-
if (!this.hotInstance) {
|
|
1239
|
-
return;
|
|
1240
|
-
}
|
|
1241
|
-
const columns = this.hotInstance.getSettings().columns;
|
|
1242
|
-
if (columns && Array.isArray(columns)) {
|
|
1243
|
-
columns.forEach((column) => {
|
|
1244
|
-
if (column._editorComponentReference) {
|
|
1245
|
-
column._editorComponentReference.destroy();
|
|
1246
|
-
}
|
|
1247
|
-
});
|
|
1248
|
-
}
|
|
1249
1235
|
this.hotInstance.destroy();
|
|
1236
|
+
this.hotInstance = null;
|
|
1250
1237
|
});
|
|
1251
|
-
|
|
1238
|
+
}
|
|
1239
|
+
destroyEditorComponentRefs() {
|
|
1240
|
+
const columns = this.hotInstance.getSettings().columns;
|
|
1241
|
+
if (Array.isArray(columns)) {
|
|
1242
|
+
columns.forEach((column) => column._editorComponentReference?.destroy());
|
|
1243
|
+
}
|
|
1252
1244
|
}
|
|
1253
1245
|
/**
|
|
1254
1246
|
* Updates the Handsontable instance with new settings.
|
|
@@ -1258,8 +1250,15 @@ class HotTableComponent {
|
|
|
1258
1250
|
if (!this.hotInstance) {
|
|
1259
1251
|
return;
|
|
1260
1252
|
}
|
|
1253
|
+
const initOnlySettingKeys = new Set(this.hotInstance.getSettings()?._initOnlySettings ?? []);
|
|
1254
|
+
const filteredSettings = {};
|
|
1255
|
+
for (const key of Object.keys(newSettings)) {
|
|
1256
|
+
if (!initOnlySettingKeys.has(key)) {
|
|
1257
|
+
filteredSettings[key] = newSettings[key];
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1261
1260
|
this.ngZone.runOutsideAngular(() => {
|
|
1262
|
-
this.hotInstance
|
|
1261
|
+
this.hotInstance.updateSettings(filteredSettings, false);
|
|
1263
1262
|
});
|
|
1264
1263
|
}
|
|
1265
1264
|
/**
|
|
@@ -1291,19 +1290,19 @@ class HotTableComponent {
|
|
|
1291
1290
|
}
|
|
1292
1291
|
return negotiatedSettings;
|
|
1293
1292
|
}
|
|
1294
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1295
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "
|
|
1293
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: HotTableComponent, deps: [{ token: HotSettingsResolver }, { token: HotGlobalConfigService }, { token: i0.NgZone }, { token: i0.EnvironmentInjector }, { token: i0.DestroyRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
1294
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.21", type: HotTableComponent, isStandalone: true, selector: "hot-table", inputs: { data: "data", settings: "settings" }, providers: [HotSettingsResolver], viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true }], usesOnChanges: true, ngImport: i0, template: '<div #container></div>', isInline: true, styles: [":host{display:block}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
1296
1295
|
}
|
|
1297
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1296
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: HotTableComponent, decorators: [{
|
|
1298
1297
|
type: Component,
|
|
1299
|
-
args: [{ selector: 'hot-table', template: '<div #container></div>', encapsulation: ViewEncapsulation.None, providers: [HotSettingsResolver], styles: [":host{display:block}\n"] }]
|
|
1300
|
-
}], ctorParameters:
|
|
1298
|
+
args: [{ selector: 'hot-table', template: '<div #container></div>', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [HotSettingsResolver], styles: [":host{display:block}\n"] }]
|
|
1299
|
+
}], ctorParameters: () => [{ type: HotSettingsResolver }, { type: HotGlobalConfigService }, { type: i0.NgZone }, { type: i0.EnvironmentInjector }, { type: i0.DestroyRef }], propDecorators: { data: [{
|
|
1301
1300
|
type: Input
|
|
1302
1301
|
}], settings: [{
|
|
1303
1302
|
type: Input
|
|
1304
1303
|
}], container: [{
|
|
1305
1304
|
type: ViewChild,
|
|
1306
|
-
args: ['container'
|
|
1305
|
+
args: ['container']
|
|
1307
1306
|
}] } });
|
|
1308
1307
|
|
|
1309
1308
|
class HotTableModule {
|
|
@@ -1311,25 +1310,18 @@ class HotTableModule {
|
|
|
1311
1310
|
* Placeholder for the library version.
|
|
1312
1311
|
* Replaced automatically during the pre-build/post-build process.
|
|
1313
1312
|
*/
|
|
1314
|
-
static version = '17.0
|
|
1315
|
-
|
|
1316
|
-
static
|
|
1317
|
-
|
|
1318
|
-
ngModule: HotTableModule,
|
|
1319
|
-
};
|
|
1320
|
-
}
|
|
1321
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: HotTableModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
1322
|
-
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: HotTableModule, declarations: [HotTableComponent, CustomEditorPlaceholderComponent], exports: [HotTableComponent] });
|
|
1323
|
-
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: HotTableModule });
|
|
1313
|
+
static version = '17.1.0-rc10';
|
|
1314
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: HotTableModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
1315
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.21", ngImport: i0, type: HotTableModule, imports: [HotTableComponent], exports: [HotTableComponent] });
|
|
1316
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: HotTableModule });
|
|
1324
1317
|
}
|
|
1325
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1318
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: HotTableModule, decorators: [{
|
|
1326
1319
|
type: NgModule,
|
|
1327
1320
|
args: [{
|
|
1328
|
-
|
|
1329
|
-
imports: [],
|
|
1321
|
+
imports: [HotTableComponent],
|
|
1330
1322
|
exports: [HotTableComponent],
|
|
1331
1323
|
}]
|
|
1332
|
-
}]
|
|
1324
|
+
}] });
|
|
1333
1325
|
|
|
1334
1326
|
/*
|
|
1335
1327
|
* Public API Surface of hot-table
|