gridstack 10.1.2 → 10.2.1
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/angular/angular.json +3 -0
- package/angular/package.json +1 -1
- package/dist/angular/esm2020/gridstack-angular.mjs +4 -4
- package/dist/angular/esm2020/lib/base-widget.mjs +30 -30
- package/dist/angular/esm2020/lib/gridstack-item.component.mjs +52 -52
- package/dist/angular/esm2020/lib/gridstack.component.mjs +266 -264
- package/dist/angular/esm2020/lib/gridstack.module.mjs +39 -39
- package/dist/angular/esm2020/public-api.mjs +7 -7
- package/dist/angular/fesm2015/gridstack-angular.mjs +368 -366
- package/dist/angular/fesm2015/gridstack-angular.mjs.map +1 -1
- package/dist/angular/fesm2020/gridstack-angular.mjs +363 -361
- package/dist/angular/fesm2020/gridstack-angular.mjs.map +1 -1
- package/dist/angular/index.d.ts +5 -5
- package/dist/angular/lib/base-widget.d.ts +16 -16
- package/dist/angular/lib/gridstack-item.component.d.ts +37 -37
- package/dist/angular/lib/gridstack.component.d.ts +129 -129
- package/dist/angular/lib/gridstack.module.d.ts +10 -10
- package/dist/angular/public-api.d.ts +4 -4
- package/dist/dd-base-impl.d.ts +1 -1
- package/dist/dd-base-impl.js +1 -1
- package/dist/dd-base-impl.js.map +1 -1
- package/dist/dd-draggable.d.ts +4 -4
- package/dist/dd-draggable.js +63 -19
- package/dist/dd-draggable.js.map +1 -1
- package/dist/dd-droppable.d.ts +1 -1
- package/dist/dd-droppable.js +1 -1
- package/dist/dd-droppable.js.map +1 -1
- package/dist/dd-element.d.ts +1 -1
- package/dist/dd-element.js +1 -1
- package/dist/dd-element.js.map +1 -1
- package/dist/dd-gridstack.d.ts +1 -1
- package/dist/dd-gridstack.js +2 -2
- package/dist/dd-gridstack.js.map +1 -1
- package/dist/dd-manager.d.ts +1 -1
- package/dist/dd-manager.js +1 -1
- package/dist/dd-manager.js.map +1 -1
- package/dist/dd-resizable-handle.d.ts +4 -3
- package/dist/dd-resizable-handle.js +12 -1
- package/dist/dd-resizable-handle.js.map +1 -1
- package/dist/dd-resizable.d.ts +1 -1
- package/dist/dd-resizable.js +1 -1
- package/dist/dd-resizable.js.map +1 -1
- package/dist/dd-touch.d.ts +1 -1
- package/dist/dd-touch.js +1 -1
- package/dist/dd-touch.js.map +1 -1
- package/dist/es5/dd-base-impl.d.ts +1 -1
- package/dist/es5/dd-base-impl.js +1 -1
- package/dist/es5/dd-base-impl.js.map +1 -1
- package/dist/es5/dd-draggable.d.ts +4 -4
- package/dist/es5/dd-draggable.js +78 -21
- package/dist/es5/dd-draggable.js.map +1 -1
- package/dist/es5/dd-droppable.d.ts +1 -1
- package/dist/es5/dd-droppable.js +1 -1
- package/dist/es5/dd-droppable.js.map +1 -1
- package/dist/es5/dd-element.d.ts +1 -1
- package/dist/es5/dd-element.js +1 -1
- package/dist/es5/dd-element.js.map +1 -1
- package/dist/es5/dd-gridstack.d.ts +1 -1
- package/dist/es5/dd-gridstack.js +2 -2
- package/dist/es5/dd-gridstack.js.map +1 -1
- package/dist/es5/dd-manager.d.ts +1 -1
- package/dist/es5/dd-manager.js +1 -1
- package/dist/es5/dd-manager.js.map +1 -1
- package/dist/es5/dd-resizable-handle.d.ts +4 -3
- package/dist/es5/dd-resizable-handle.js +13 -1
- package/dist/es5/dd-resizable-handle.js.map +1 -1
- package/dist/es5/dd-resizable.d.ts +1 -1
- package/dist/es5/dd-resizable.js +1 -1
- package/dist/es5/dd-resizable.js.map +1 -1
- package/dist/es5/dd-touch.d.ts +1 -1
- package/dist/es5/dd-touch.js +1 -1
- package/dist/es5/dd-touch.js.map +1 -1
- package/dist/es5/gridstack-all.js +1 -1
- package/dist/es5/gridstack-all.js.LICENSE.txt +1 -1
- package/dist/es5/gridstack-all.js.map +1 -1
- package/dist/es5/gridstack-engine.d.ts +1 -1
- package/dist/es5/gridstack-engine.js +1 -1
- package/dist/es5/gridstack-engine.js.map +1 -1
- package/dist/es5/gridstack-poly.js +1 -1
- package/dist/es5/gridstack.d.ts +9 -3
- package/dist/es5/gridstack.js +61 -28
- package/dist/es5/gridstack.js.map +1 -1
- package/dist/es5/types.d.ts +8 -8
- package/dist/es5/types.js +1 -1
- package/dist/es5/types.js.map +1 -1
- package/dist/es5/utils.d.ts +6 -1
- package/dist/es5/utils.js +26 -10
- package/dist/es5/utils.js.map +1 -1
- package/dist/gridstack-all.js +1 -1
- package/dist/gridstack-all.js.LICENSE.txt +1 -1
- package/dist/gridstack-all.js.map +1 -1
- package/dist/gridstack-engine.d.ts +1 -1
- package/dist/gridstack-engine.js +1 -1
- package/dist/gridstack-engine.js.map +1 -1
- package/dist/gridstack.css +1 -1
- package/dist/gridstack.d.ts +9 -3
- package/dist/gridstack.js +56 -26
- package/dist/gridstack.js.map +1 -1
- package/dist/types.d.ts +8 -8
- package/dist/types.js +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils.d.ts +6 -1
- package/dist/utils.js +25 -10
- package/dist/utils.js.map +1 -1
- package/doc/CHANGES.md +15 -0
- package/doc/README.md +7 -1
- package/package.json +3 -2
- package/angular/.vscode/extensions.json +0 -4
- package/angular/.vscode/launch.json +0 -20
- package/angular/.vscode/tasks.json +0 -42
- package/angular/projects/demo/.browserslistrc +0 -16
- package/angular/projects/demo/src/app/app.component.css +0 -11
- package/angular/projects/demo/src/app/app.component.html +0 -110
- package/angular/projects/demo/src/app/app.component.spec.ts +0 -25
- package/angular/projects/demo/src/app/app.component.ts +0 -223
- package/angular/projects/demo/src/app/app.module.ts +0 -39
- package/angular/projects/demo/src/app/dummy.component.ts +0 -34
- package/angular/projects/demo/src/app/ngFor.ts +0 -131
- package/angular/projects/demo/src/app/ngFor_cmd.ts +0 -106
- package/angular/projects/demo/src/app/simple.ts +0 -46
- package/angular/projects/demo/src/assets/.gitkeep +0 -0
- package/angular/projects/demo/src/environments/environment.ts +0 -16
- package/angular/projects/demo/src/favicon.ico +0 -0
- package/angular/projects/demo/src/index.html +0 -13
- package/angular/projects/demo/src/main.ts +0 -12
- package/angular/projects/demo/src/polyfills.ts +0 -53
- package/angular/projects/demo/src/styles.css +0 -41
- package/angular/projects/demo/src/test.ts +0 -26
- package/angular/projects/demo/tsconfig.app.json +0 -15
- package/angular/projects/demo/tsconfig.spec.json +0 -18
- package/angular/projects/lib/src/lib/base-widget.ts +0 -28
- package/angular/projects/lib/src/lib/gridstack-item.component.ts +0 -78
- package/angular/projects/lib/src/lib/gridstack.component.ts +0 -287
- package/angular/projects/lib/src/lib/gridstack.module.ts +0 -32
- package/angular/projects/lib/src/public-api.ts +0 -8
- package/angular/projects/lib/src/test.ts +0 -27
- package/dist/angular/src/base-widget.ts +0 -28
- package/dist/angular/src/gridstack-item.component.ts +0 -78
- package/dist/angular/src/gridstack.component.ts +0 -287
- package/dist/angular/src/gridstack.module.ts +0 -32
- package/dist/src/gridstack-extra.scss +0 -25
- package/dist/src/gridstack.scss +0 -157
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
<div class="button-container">
|
|
3
|
-
<p class="pick-info">Pick a demo to load:</p>
|
|
4
|
-
<button (click)="onShow(0)" [class.active]="show===0">Simple</button>
|
|
5
|
-
<button (click)="onShow(1)" [class.active]="show===1">ngFor case</button>
|
|
6
|
-
<button (click)="onShow(2)" [class.active]="show===2">ngFor custom command</button>
|
|
7
|
-
<button (click)="onShow(3)" [class.active]="show===3">Component HTML template</button>
|
|
8
|
-
<button (click)="onShow(4)" [class.active]="show===4">Component ngFor</button>
|
|
9
|
-
<button (click)="onShow(5)" [class.active]="show===5">Component Dynamic</button>
|
|
10
|
-
<button (click)="onShow(6)" [class.active]="show===6">Nested Grid</button>
|
|
11
|
-
<button (click)="onShow(7)" [class.active]="show===7">Two Grids + sidebar</button>
|
|
12
|
-
</div>
|
|
13
|
-
|
|
14
|
-
<div class="test-container">
|
|
15
|
-
<angular-simple-test *ngIf="show===0"></angular-simple-test>
|
|
16
|
-
<angular-ng-for-test *ngIf="show===1"></angular-ng-for-test>
|
|
17
|
-
<angular-ng-for-cmd-test *ngIf="show===2"></angular-ng-for-cmd-test>
|
|
18
|
-
|
|
19
|
-
<div *ngIf="show===3">
|
|
20
|
-
<p><b>COMPONENT template</b>: using DOM template to use components statically</p>
|
|
21
|
-
<button (click)="add()">add item</button>
|
|
22
|
-
<button (click)="delete()">remove item</button>
|
|
23
|
-
<button (click)="modify()">modify item</button>
|
|
24
|
-
<button (click)="newLayout()">new layout</button>
|
|
25
|
-
<gridstack [options]="gridOptions" (changeCB)="onChange($event)" (resizeStopCB)="onResizeStop($event)">
|
|
26
|
-
<gridstack-item gs-x="1" gs-y="0">item 1</gridstack-item>
|
|
27
|
-
<gridstack-item gs-x="3" gs-y="0" gs-w="2">item 2 wide</gridstack-item>
|
|
28
|
-
</gridstack>
|
|
29
|
-
</div>
|
|
30
|
-
|
|
31
|
-
<div *ngIf="show===4">
|
|
32
|
-
<p><b>COMPONENT ngFor</b>: Most complete example that uses Component wrapper for grid and gridItem</p>
|
|
33
|
-
<button (click)="addNgFor()">add item</button>
|
|
34
|
-
<button (click)="deleteNgFor()">remove item</button>
|
|
35
|
-
<button (click)="modifyNgFor()">modify item</button>
|
|
36
|
-
<button (click)="newLayoutNgFor()">new layout</button>
|
|
37
|
-
<gridstack [options]="gridOptions" (changeCB)="onChange($event)" (resizeStopCB)="onResizeStop($event)">
|
|
38
|
-
<gridstack-item *ngFor="let n of items; trackBy: identify" [options]="n">
|
|
39
|
-
</gridstack-item>
|
|
40
|
-
</gridstack>
|
|
41
|
-
</div>
|
|
42
|
-
|
|
43
|
-
<div *ngIf="show===5">
|
|
44
|
-
<p><b>COMPONENT dynamic</b>: Best example that uses Component wrapper and dynamic grid creation (drag between grids, from toolbar, etc...)</p>
|
|
45
|
-
<button (click)="add()">add item</button>
|
|
46
|
-
<button (click)="delete()">remove item</button>
|
|
47
|
-
<button (click)="modify()">modify item</button>
|
|
48
|
-
<button (click)="newLayout()">new layout</button>
|
|
49
|
-
<button (click)="saveGrid()">Save</button>
|
|
50
|
-
<button (click)="clearGrid()">Clear</button>
|
|
51
|
-
<button (click)="loadGrid()">Load</button>
|
|
52
|
-
<gridstack [options]="gridOptionsFull" (changeCB)="onChange($event)" (resizeStopCB)="onResizeStop($event)">
|
|
53
|
-
</gridstack>
|
|
54
|
-
</div>
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
<div *ngIf="show===6">
|
|
58
|
-
<p><b>Nested Grid</b>: shows nested component grids, like nested.html demo but with Ng Components</p>
|
|
59
|
-
<button (click)="add()">add item</button>
|
|
60
|
-
<button (click)="delete()">remove item</button>
|
|
61
|
-
<button (click)="modify()">modify item</button>
|
|
62
|
-
<button (click)="newLayout()">new layout</button>
|
|
63
|
-
<button (click)="saveGrid()">Save</button>
|
|
64
|
-
<button (click)="clearGrid()">Clear</button>
|
|
65
|
-
<button (click)="loadGrid()">Load</button>
|
|
66
|
-
<!-- TODO: addGrid() in code for testing instead ? -->
|
|
67
|
-
<gridstack [options]="nestedGridOptions" (changeCB)="onChange($event)" (resizeStopCB)="onResizeStop($event)">
|
|
68
|
-
<div empty-content>Add items here or reload the grid</div>
|
|
69
|
-
</gridstack>
|
|
70
|
-
</div>
|
|
71
|
-
|
|
72
|
-
<div *ngIf="show===7">
|
|
73
|
-
<p><b>two.html</b>: shows multiple grids and outside drag&drop</p>
|
|
74
|
-
<div class="row">
|
|
75
|
-
<div class="col-md-3">
|
|
76
|
-
<div class="sidebar">
|
|
77
|
-
<!-- will size to match content -->
|
|
78
|
-
<div class="grid-stack-item">
|
|
79
|
-
<div class="grid-stack-item-content">Drag me</div>
|
|
80
|
-
</div>
|
|
81
|
-
<!-- manually force a drop size of 2x1 -->
|
|
82
|
-
<div class="grid-stack-item" gs-w="2" gs-h="1" gs-max-w="3">
|
|
83
|
-
<div class="grid-stack-item-content">2x1, max=3</div>
|
|
84
|
-
</div>
|
|
85
|
-
</div>
|
|
86
|
-
</div>
|
|
87
|
-
<div class="col-md-9">
|
|
88
|
-
<div class="trash" id="trash">
|
|
89
|
-
</div>
|
|
90
|
-
</div>
|
|
91
|
-
</div>
|
|
92
|
-
<div class="row" style="margin-top: 20px">
|
|
93
|
-
<div class="col-md-6">
|
|
94
|
-
<gridstack [options]="twoGridOpt1"></gridstack>
|
|
95
|
-
</div>
|
|
96
|
-
<div class="col-md-6">
|
|
97
|
-
<gridstack [options]="twoGridOpt2"></gridstack>
|
|
98
|
-
</div>
|
|
99
|
-
</div>
|
|
100
|
-
</div>
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
<div class="grid-container"></div>
|
|
104
|
-
|
|
105
|
-
<div class="text-container">
|
|
106
|
-
<textarea #origTextArea cols="50" rows="50" readonly="readonly"></textarea>
|
|
107
|
-
<textarea #textArea cols="50" rows="50" readonly="readonly"></textarea>
|
|
108
|
-
</div>
|
|
109
|
-
|
|
110
|
-
</div>
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { TestBed } from '@angular/core/testing';
|
|
2
|
-
import { AppComponent } from './app.component';
|
|
3
|
-
|
|
4
|
-
describe('AppComponent', () => {
|
|
5
|
-
beforeEach(async () => {
|
|
6
|
-
await TestBed.configureTestingModule({
|
|
7
|
-
declarations: [
|
|
8
|
-
AppComponent
|
|
9
|
-
],
|
|
10
|
-
}).compileComponents();
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
it('should create the app', () => {
|
|
14
|
-
const fixture = TestBed.createComponent(AppComponent);
|
|
15
|
-
const app = fixture.componentInstance;
|
|
16
|
-
expect(app).toBeTruthy();
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
it('should have content', () => {
|
|
20
|
-
const fixture = TestBed.createComponent(AppComponent);
|
|
21
|
-
fixture.detectChanges();
|
|
22
|
-
const compiled = fixture.nativeElement as HTMLElement;
|
|
23
|
-
expect(compiled.querySelector('.pick-info')?.textContent).toContain('Pick a demo to load');
|
|
24
|
-
});
|
|
25
|
-
});
|
|
@@ -1,223 +0,0 @@
|
|
|
1
|
-
import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';
|
|
2
|
-
import { GridStack, GridStackOptions, GridStackWidget } from 'gridstack';
|
|
3
|
-
import { AngularSimpleComponent } from './simple';
|
|
4
|
-
import { AngularNgForTestComponent } from './ngFor';
|
|
5
|
-
import { AngularNgForCmdTestComponent } from './ngFor_cmd';
|
|
6
|
-
|
|
7
|
-
// NOTE: local testing of file
|
|
8
|
-
// import { GridstackComponent, NgGridStackOptions, NgGridStackWidget, elementCB, gsCreateNgComponents, nodesCB } from './gridstack.component';
|
|
9
|
-
import { GridstackComponent, NgGridStackOptions, NgGridStackWidget, elementCB, gsCreateNgComponents, nodesCB } from 'gridstack/dist/angular';
|
|
10
|
-
|
|
11
|
-
// unique ids sets for each item for correct ngFor updating
|
|
12
|
-
let ids = 1;
|
|
13
|
-
@Component({
|
|
14
|
-
selector: 'app-root',
|
|
15
|
-
templateUrl: './app.component.html',
|
|
16
|
-
styleUrls: ['./app.component.css']
|
|
17
|
-
})
|
|
18
|
-
export class AppComponent implements OnInit {
|
|
19
|
-
|
|
20
|
-
@ViewChild(AngularSimpleComponent) case0Comp?: AngularSimpleComponent;
|
|
21
|
-
@ViewChild(AngularNgForTestComponent) case1Comp?: AngularNgForTestComponent;
|
|
22
|
-
@ViewChild(AngularNgForCmdTestComponent) case2Comp?: AngularNgForCmdTestComponent;
|
|
23
|
-
@ViewChild(GridstackComponent) gridComp?: GridstackComponent;
|
|
24
|
-
@ViewChild('origTextArea', {static: true}) origTextEl?: ElementRef<HTMLTextAreaElement>;
|
|
25
|
-
@ViewChild('textArea', {static: true}) textEl?: ElementRef<HTMLTextAreaElement>;
|
|
26
|
-
|
|
27
|
-
// which sample to show
|
|
28
|
-
public show = 5;
|
|
29
|
-
|
|
30
|
-
/** sample grid options and items to load... */
|
|
31
|
-
public items: GridStackWidget[] = [
|
|
32
|
-
{x: 0, y: 0, minW: 2},
|
|
33
|
-
{x: 1, y: 1},
|
|
34
|
-
{x: 2, y: 2},
|
|
35
|
-
];
|
|
36
|
-
public gridOptions: GridStackOptions = {
|
|
37
|
-
margin: 5,
|
|
38
|
-
// float: true,
|
|
39
|
-
minRow: 1,
|
|
40
|
-
cellHeight: 70,
|
|
41
|
-
columnOpts: { breakpoints: [{w:768, c:1}] },
|
|
42
|
-
}
|
|
43
|
-
private sub0: NgGridStackWidget[] = [{x:0, y:0, selector:'app-a'}, {x:1, y:0, content:'plain html'}, {x:0, y:1, selector:'app-b'} ];
|
|
44
|
-
public gridOptionsFull: NgGridStackOptions = {
|
|
45
|
-
...this.gridOptions,
|
|
46
|
-
children: this.sub0,
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// nested grid options
|
|
50
|
-
private subOptions: GridStackOptions = {
|
|
51
|
-
cellHeight: 50, // should be 50 - top/bottom
|
|
52
|
-
column: 'auto', // size to match container. make sure to include gridstack-extra.min.css
|
|
53
|
-
acceptWidgets: true, // will accept .grid-stack-item by default
|
|
54
|
-
margin: 5,
|
|
55
|
-
};
|
|
56
|
-
private sub1: NgGridStackWidget[] = [ {x:0, y:0, selector:'app-a'}, {x:1, y:0, selector:'app-b'}, {x:2, y:0, selector:'app-c'}, {x:3, y:0}, {x:0, y:1}, {x:1, y:1}];
|
|
57
|
-
private sub2: NgGridStackWidget[] = [ {x:0, y:0}, {x:0, y:1, w:2}];
|
|
58
|
-
private subChildren: NgGridStackWidget[] = [
|
|
59
|
-
{x:0, y:0, content: 'regular item'},
|
|
60
|
-
{x:1, y:0, w:4, h:4, subGridOpts: {children: this.sub1, class: 'sub1', ...this.subOptions}},
|
|
61
|
-
{x:5, y:0, w:3, h:4, subGridOpts: {children: this.sub2, class: 'sub2', ...this.subOptions}},
|
|
62
|
-
]
|
|
63
|
-
public nestedGridOptions: NgGridStackOptions = { // main grid options
|
|
64
|
-
cellHeight: 50,
|
|
65
|
-
margin: 5,
|
|
66
|
-
minRow: 2, // don't collapse when empty
|
|
67
|
-
acceptWidgets: true,
|
|
68
|
-
children: this.subChildren
|
|
69
|
-
};
|
|
70
|
-
public twoGridOpt1: NgGridStackOptions = {
|
|
71
|
-
column: 6,
|
|
72
|
-
cellHeight: 50,
|
|
73
|
-
margin: 5,
|
|
74
|
-
minRow: 1, // don't collapse when empty
|
|
75
|
-
removable: '.trash',
|
|
76
|
-
acceptWidgets: true,
|
|
77
|
-
float: true,
|
|
78
|
-
children: [
|
|
79
|
-
{x: 0, y: 0, w: 2, h: 2},
|
|
80
|
-
{x: 3, y: 1, h: 2},
|
|
81
|
-
{x: 4, y: 1},
|
|
82
|
-
{x: 2, y: 3, w: 3, maxW: 3, id: 'special', content: 'has maxW=3'},
|
|
83
|
-
]
|
|
84
|
-
};
|
|
85
|
-
public twoGridOpt2: NgGridStackOptions = { ...this.twoGridOpt1, float: false }
|
|
86
|
-
private serializedData?: NgGridStackOptions;
|
|
87
|
-
|
|
88
|
-
constructor() {
|
|
89
|
-
// give them content and unique id to make sure we track them during changes below...
|
|
90
|
-
[...this.items, ...this.subChildren, ...this.sub1, ...this.sub2, ...this.sub0].forEach((w: NgGridStackWidget) => {
|
|
91
|
-
if (!w.selector && !w.content && !w.subGridOpts) w.content = `item ${ids}`;
|
|
92
|
-
w.id = String(ids++);
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
ngOnInit(): void {
|
|
97
|
-
this.onShow(this.show);
|
|
98
|
-
|
|
99
|
-
// TEST
|
|
100
|
-
// setTimeout(() => {
|
|
101
|
-
// if (!this.gridComp) return;
|
|
102
|
-
// this.saveGrid();
|
|
103
|
-
// // this.clearGrid();
|
|
104
|
-
// this.delete();
|
|
105
|
-
// this.delete();
|
|
106
|
-
// this.loadGrid();
|
|
107
|
-
// this.delete();
|
|
108
|
-
// this.delete();
|
|
109
|
-
// }, 500)
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
public onShow(val: number) {
|
|
113
|
-
this.show = val;
|
|
114
|
-
|
|
115
|
-
// set globally our method to create the right widget type
|
|
116
|
-
if (val < 3) GridStack.addRemoveCB = undefined;
|
|
117
|
-
else GridStack.addRemoveCB = gsCreateNgComponents;
|
|
118
|
-
|
|
119
|
-
// let the switch take affect then load the starting values (since we sometimes save())
|
|
120
|
-
setTimeout(() => {
|
|
121
|
-
let data;
|
|
122
|
-
switch(val) {
|
|
123
|
-
case 0: data = this.case0Comp?.items; break;
|
|
124
|
-
case 1: data = this.case1Comp?.items; break;
|
|
125
|
-
case 2: data = this.case2Comp?.items; break;
|
|
126
|
-
case 3: data = this.gridComp?.grid?.save(true, true); break;
|
|
127
|
-
case 4: data = this.items; break;
|
|
128
|
-
case 5: data = this.gridOptionsFull; break;
|
|
129
|
-
case 6: data = this.nestedGridOptions; break;
|
|
130
|
-
case 7: data = this.twoGridOpt1;
|
|
131
|
-
GridStack.setupDragIn('.sidebar .grid-stack-item', { appendTo: 'body', helper: 'clone' });
|
|
132
|
-
break;
|
|
133
|
-
}
|
|
134
|
-
if (this.origTextEl) this.origTextEl.nativeElement.value = JSON.stringify(data, null, ' ');
|
|
135
|
-
});
|
|
136
|
-
if (this.textEl) this.textEl.nativeElement.value = '';
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/** called whenever items change size/position/etc.. */
|
|
140
|
-
public onChange(data: nodesCB) {
|
|
141
|
-
// TODO: update our TEMPLATE list to match ?
|
|
142
|
-
// NOTE: no need for dynamic as we can always use grid.save() to get latest layout, or grid.engine.nodes
|
|
143
|
-
console.log('change ', data.nodes.length > 1 ? data.nodes : data.nodes[0]);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
public onResizeStop(data: elementCB) {
|
|
147
|
-
console.log('resizestop ', data.el.gridstackNode);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* TEST dynamic grid operations - uses grid API directly (since we don't track structure that gets out of sync)
|
|
152
|
-
*/
|
|
153
|
-
public add() {
|
|
154
|
-
// TODO: BUG the content doesn't appear until widget is moved around (or another created). Need to force
|
|
155
|
-
// angular detection changes...
|
|
156
|
-
this.gridComp?.grid?.addWidget({x:3, y:0, w:2, content:`item ${ids}`, id:String(ids++)});
|
|
157
|
-
}
|
|
158
|
-
public delete() {
|
|
159
|
-
let grid = this.gridComp?.grid;
|
|
160
|
-
if (!grid) return;
|
|
161
|
-
let node = grid.engine.nodes[0];
|
|
162
|
-
// delete any children first before subGrid itself...
|
|
163
|
-
if (node?.subGrid && node.subGrid.engine.nodes.length) {
|
|
164
|
-
grid = node.subGrid;
|
|
165
|
-
node = grid.engine.nodes[0];
|
|
166
|
-
}
|
|
167
|
-
if (node) grid.removeWidget(node.el!);
|
|
168
|
-
}
|
|
169
|
-
public modify() {
|
|
170
|
-
this.gridComp?.grid?.update(this.gridComp?.grid.engine.nodes[0]?.el!, {w:3})
|
|
171
|
-
}
|
|
172
|
-
public newLayout() {
|
|
173
|
-
this.gridComp?.grid?.load([
|
|
174
|
-
{x:0, y:1, id:'1', minW:1, w:1}, // new size/constrain
|
|
175
|
-
{x:1, y:1, id:'2'},
|
|
176
|
-
// {x:2, y:1, id:'3'}, // delete item
|
|
177
|
-
{x:3, y:0, w:2, content:'new item'}, // new item
|
|
178
|
-
]);
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
/**
|
|
182
|
-
* ngFor case: TEST TEMPLATE operations - NOT recommended unless you have no GS creating/re-parenting
|
|
183
|
-
*/
|
|
184
|
-
public addNgFor() {
|
|
185
|
-
// new array isn't required as Angular detects changes to content with trackBy:identify()
|
|
186
|
-
// this.items = [...this.items, { x:3, y:0, w:3, content:`item ${ids}`, id:String(ids++) }];
|
|
187
|
-
this.items.push({w:2, content:`item ${ids}`, id:String(ids++)});
|
|
188
|
-
}
|
|
189
|
-
public deleteNgFor() {
|
|
190
|
-
this.items.pop();
|
|
191
|
-
}
|
|
192
|
-
public modifyNgFor() {
|
|
193
|
-
// this will not update the DOM nor trigger gridstackItems.changes for GS to auto-update, so set new option of the gridItem instead
|
|
194
|
-
// this.items[0].w = 3;
|
|
195
|
-
const gridItem = this.gridComp?.gridstackItems?.get(0);
|
|
196
|
-
if (gridItem) gridItem.options = {w:3};
|
|
197
|
-
}
|
|
198
|
-
public newLayoutNgFor() {
|
|
199
|
-
this.items = [
|
|
200
|
-
{x:0, y:1, id:'1', minW:1, w:1}, // new size/constrain
|
|
201
|
-
{x:1, y:1, id:'2'},
|
|
202
|
-
// {x:2, y:1, id:'3'}, // delete item
|
|
203
|
-
{x:3, y:0, w:2, content:'new item'}, // new item
|
|
204
|
-
];
|
|
205
|
-
}
|
|
206
|
-
public clearGrid() {
|
|
207
|
-
if (!this.gridComp) return;
|
|
208
|
-
this.gridComp.grid?.removeAll();
|
|
209
|
-
}
|
|
210
|
-
public saveGrid() {
|
|
211
|
-
this.serializedData = this.gridComp?.grid?.save(false, true) as GridStackOptions || ''; // no content, full options
|
|
212
|
-
if (this.textEl) this.textEl.nativeElement.value = JSON.stringify(this.serializedData, null, ' ');
|
|
213
|
-
}
|
|
214
|
-
public loadGrid() {
|
|
215
|
-
if (!this.gridComp) return;
|
|
216
|
-
GridStack.addGrid(this.gridComp.el, this.serializedData);
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
// ngFor TEMPLATE unique node id to have correct match between our items used and GS
|
|
220
|
-
public identify(index: number, w: GridStackWidget) {
|
|
221
|
-
return w.id; // or use index if no id is set and you only modify at the end...
|
|
222
|
-
}
|
|
223
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { NgModule } from '@angular/core';
|
|
2
|
-
import { BrowserModule } from '@angular/platform-browser';
|
|
3
|
-
|
|
4
|
-
import { AppComponent } from './app.component';
|
|
5
|
-
import { AngularNgForTestComponent } from './ngFor';
|
|
6
|
-
import { AngularNgForCmdTestComponent } from './ngFor_cmd';
|
|
7
|
-
import { AngularSimpleComponent } from './simple';
|
|
8
|
-
import { AComponent, BComponent, CComponent } from './dummy.component';
|
|
9
|
-
|
|
10
|
-
// local testing
|
|
11
|
-
// import { GridstackModule } from './gridstack.module';
|
|
12
|
-
// import { GridstackComponent } from './gridstack.component';
|
|
13
|
-
import { GridstackModule, GridstackComponent } from 'gridstack/dist/angular';
|
|
14
|
-
|
|
15
|
-
@NgModule({
|
|
16
|
-
imports: [
|
|
17
|
-
BrowserModule,
|
|
18
|
-
GridstackModule,
|
|
19
|
-
],
|
|
20
|
-
declarations: [
|
|
21
|
-
AngularNgForCmdTestComponent,
|
|
22
|
-
AngularNgForTestComponent,
|
|
23
|
-
AngularSimpleComponent,
|
|
24
|
-
AppComponent,
|
|
25
|
-
AComponent,
|
|
26
|
-
BComponent,
|
|
27
|
-
CComponent,
|
|
28
|
-
],
|
|
29
|
-
exports: [
|
|
30
|
-
],
|
|
31
|
-
providers: [],
|
|
32
|
-
bootstrap: [AppComponent]
|
|
33
|
-
})
|
|
34
|
-
export class AppModule {
|
|
35
|
-
constructor() {
|
|
36
|
-
// register all our dynamic components created in the grid
|
|
37
|
-
GridstackComponent.addComponentToSelectorType([AComponent, BComponent, CComponent]);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* gridstack.component.ts 8.2.1
|
|
3
|
-
* Copyright (c) 2022 Alain Dumesny - see GridStack root license
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
// dummy testing component that will be grid items content
|
|
7
|
-
|
|
8
|
-
import { Component, OnDestroy, Input } from '@angular/core';
|
|
9
|
-
import { BaseWidget, NgCompInputs } from 'gridstack/dist/angular';
|
|
10
|
-
|
|
11
|
-
@Component({
|
|
12
|
-
selector: 'app-a',
|
|
13
|
-
template: 'Comp A {{text}}',
|
|
14
|
-
})
|
|
15
|
-
export class AComponent extends BaseWidget implements OnDestroy {
|
|
16
|
-
@Input() text: string = 'foo'; // test custom input data
|
|
17
|
-
public override serialize(): NgCompInputs | undefined { return this.text ? {text: this.text} : undefined; }
|
|
18
|
-
ngOnDestroy() { console.log('Comp A destroyed'); } // test to make sure cleanup happens
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
@Component({
|
|
22
|
-
selector: 'app-b',
|
|
23
|
-
template: 'Comp B',
|
|
24
|
-
})
|
|
25
|
-
export class BComponent extends BaseWidget implements OnDestroy {
|
|
26
|
-
ngOnDestroy() { console.log('Comp B destroyed'); }
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
@Component({
|
|
30
|
-
selector: 'app-c',
|
|
31
|
-
template: 'Comp C',
|
|
32
|
-
})
|
|
33
|
-
export class CComponent extends BaseWidget {
|
|
34
|
-
}
|
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Example using Angular ngFor to loop through items and create DOM items
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { Component, AfterViewInit, Input, ViewChildren, QueryList, ElementRef } from '@angular/core';
|
|
6
|
-
import { GridItemHTMLElement, GridStack, GridStackNode, GridStackWidget, Utils } from 'gridstack';
|
|
7
|
-
|
|
8
|
-
// unique ids sets for each item for correct ngFor updating
|
|
9
|
-
let ids = 1;
|
|
10
|
-
|
|
11
|
-
@Component({
|
|
12
|
-
selector: "angular-ng-for-test",
|
|
13
|
-
template: `
|
|
14
|
-
<p><b>ngFor</b>: Example using Angular ngFor to loop through items and create DOM items. This track changes made to the array of items, waits for DOM rendering, then update GS</p>
|
|
15
|
-
<button (click)="add()">add item</button>
|
|
16
|
-
<button (click)="delete()">remove item</button>
|
|
17
|
-
<button (click)="modify()">modify item</button>
|
|
18
|
-
<button (click)="newLayout()">new layout</button>
|
|
19
|
-
<div class="grid-stack">
|
|
20
|
-
<!-- using angular templating to create DOM, otherwise an easier way is to simply call grid.load(items)
|
|
21
|
-
NOTE: this example is NOT complete as there are many more properties than listed (minW, maxW, etc....)
|
|
22
|
-
-->
|
|
23
|
-
<div *ngFor="let n of items; trackBy: identify"
|
|
24
|
-
class="grid-stack-item"
|
|
25
|
-
[attr.gs-id]="n.id"
|
|
26
|
-
[attr.gs-x]="n.x"
|
|
27
|
-
[attr.gs-y]="n.y"
|
|
28
|
-
[attr.gs-w]="n.w"
|
|
29
|
-
[attr.gs-h]="n.h"
|
|
30
|
-
#gridStackItem
|
|
31
|
-
>
|
|
32
|
-
<div class="grid-stack-item-content">item {{ n.id }}</div>
|
|
33
|
-
</div>
|
|
34
|
-
</div>
|
|
35
|
-
`,
|
|
36
|
-
// gridstack.min.css and other custom styles should be included in global styles.scss or here
|
|
37
|
-
})
|
|
38
|
-
export class AngularNgForTestComponent implements AfterViewInit {
|
|
39
|
-
/** list of HTML items that we track to know when the DOM has been updated to make/remove GS widgets */
|
|
40
|
-
@ViewChildren("gridStackItem") gridstackItems!: QueryList<ElementRef<GridItemHTMLElement>>;
|
|
41
|
-
|
|
42
|
-
/** set the items to display. */
|
|
43
|
-
@Input() public set items(list: GridStackWidget[]) {
|
|
44
|
-
this._items = list || [];
|
|
45
|
-
this._items.forEach(w => w.id = w.id || String(ids++)); // make sure a unique id is generated for correct ngFor loop update
|
|
46
|
-
}
|
|
47
|
-
public get items(): GridStackWidget[] { return this._items}
|
|
48
|
-
|
|
49
|
-
private grid!: GridStack;
|
|
50
|
-
public _items!: GridStackWidget[];
|
|
51
|
-
|
|
52
|
-
constructor() {
|
|
53
|
-
this.items = [
|
|
54
|
-
{x: 0, y: 0},
|
|
55
|
-
{x: 1, y: 1},
|
|
56
|
-
{x: 2, y: 2},
|
|
57
|
-
];
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// wait until after DOM is ready to init gridstack - can't be ngOnInit() as angular ngFor needs to run first!
|
|
61
|
-
public ngAfterViewInit() {
|
|
62
|
-
this.grid = GridStack.init({
|
|
63
|
-
margin: 5,
|
|
64
|
-
float: true,
|
|
65
|
-
})
|
|
66
|
-
.on('change added', (event: Event, nodes: GridStackNode[]) => this.onChange(nodes));
|
|
67
|
-
|
|
68
|
-
// sync initial actual valued rendered (in case init() had to merge conflicts)
|
|
69
|
-
this.onChange();
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* this is called when the list of items changes - get a list of nodes and
|
|
73
|
-
* update the layout accordingly (which will take care of adding/removing items changed by Angular)
|
|
74
|
-
*/
|
|
75
|
-
this.gridstackItems.changes.subscribe(() => {
|
|
76
|
-
const layout: GridStackWidget[] = [];
|
|
77
|
-
this.gridstackItems.forEach(ref => {
|
|
78
|
-
const n = ref.nativeElement.gridstackNode || this.grid.makeWidget(ref.nativeElement).gridstackNode;
|
|
79
|
-
if (n) layout.push(n);
|
|
80
|
-
});
|
|
81
|
-
this.grid.load(layout); // efficient that does diffs only
|
|
82
|
-
})
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/** Optional: called when given widgets are changed (moved/resized/added) - update our list to match.
|
|
86
|
-
* Note this is not strictly necessary as demo works without this
|
|
87
|
-
*/
|
|
88
|
-
public onChange(list = this.grid.engine.nodes) {
|
|
89
|
-
setTimeout(() => // prevent new 'added' items from ExpressionChangedAfterItHasBeenCheckedError. TODO: find cleaner way to sync outside Angular change detection ?
|
|
90
|
-
list.forEach(n => {
|
|
91
|
-
const item = this._items.find(i => i.id === n.id);
|
|
92
|
-
if (item) Utils.copyPos(item, n);
|
|
93
|
-
})
|
|
94
|
-
, 0);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* CRUD operations
|
|
99
|
-
*/
|
|
100
|
-
public add() {
|
|
101
|
-
// new array isn't required as Angular seem to detect changes to content
|
|
102
|
-
// this.items = [...this.items, { x:3, y:0, w:3, id:String(ids++) }];
|
|
103
|
-
this.items.push({ x:3, y:0, w:3, id:String(ids++) });
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
public delete() {
|
|
107
|
-
this.items.pop();
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
public modify() {
|
|
111
|
-
// this will only update the DOM attr (from the ngFor loop in our template above)
|
|
112
|
-
// but not trigger gridstackItems.changes for GS to auto-update, so call GS update() instead
|
|
113
|
-
// this.items[0].w = 2;
|
|
114
|
-
const n = this.grid.engine.nodes[0];
|
|
115
|
-
if (n?.el) this.grid.update(n.el, {w:3});
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
public newLayout() {
|
|
119
|
-
this.items = [ // test updating existing and creating new one
|
|
120
|
-
{x:0, y:1, id:'1'},
|
|
121
|
-
{x:1, y:1, id:'2'},
|
|
122
|
-
// {x:2, y:1, id:3}, // delete item
|
|
123
|
-
{x:3, y:0, w:3}, // new item
|
|
124
|
-
];
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// ngFor unique node id to have correct match between our items used and GS
|
|
128
|
-
identify(index: number, w: GridStackWidget) {
|
|
129
|
-
return w.id;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Example using Angular ngFor to loop through items and create DOM items - this uses a custom command.
|
|
3
|
-
* NOTE: see the simpler and better (tracks all changes) angular-ng-for-test
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { Component, AfterViewInit, Input, ViewChildren, QueryList, ElementRef } from '@angular/core';
|
|
7
|
-
import { Subject, zip } from "rxjs";
|
|
8
|
-
|
|
9
|
-
import { GridItemHTMLElement, GridStack, GridStackWidget } from 'gridstack';
|
|
10
|
-
|
|
11
|
-
@Component({
|
|
12
|
-
selector: "angular-ng-for-cmd-test",
|
|
13
|
-
template: `
|
|
14
|
-
<p><b>ngFor CMD</b>: Example using Angular ngFor to loop through items, but uses an explicity command to let us update GS (see automatic better way)</p>
|
|
15
|
-
<button (click)="add()">add item</button>
|
|
16
|
-
<button (click)="delete()">remove item</button>
|
|
17
|
-
<button (click)="modify()">modify item</button>
|
|
18
|
-
<div class="grid-stack">
|
|
19
|
-
<!-- using angular templating to create DOM, otherwise an easier way is to simply call grid.load(items) -->
|
|
20
|
-
<div
|
|
21
|
-
*ngFor="let n of items; let i = index; trackBy: identify"
|
|
22
|
-
[id]="i"
|
|
23
|
-
class="grid-stack-item"
|
|
24
|
-
[attr.gs-x]="n.x"
|
|
25
|
-
[attr.gs-y]="n.y"
|
|
26
|
-
[attr.gs-w]="n.w"
|
|
27
|
-
[attr.gs-h]="n.h"
|
|
28
|
-
#gridStackItem
|
|
29
|
-
>
|
|
30
|
-
<div class="grid-stack-item-content">item {{ i }}</div>
|
|
31
|
-
</div>
|
|
32
|
-
</div>
|
|
33
|
-
`,
|
|
34
|
-
// gridstack.min.css and other custom styles should be included in global styles.scss or here
|
|
35
|
-
})
|
|
36
|
-
export class AngularNgForCmdTestComponent implements AfterViewInit {
|
|
37
|
-
/** list of HTML items that we track to know when the DOM has been updated to make/remove GS widgets */
|
|
38
|
-
@ViewChildren("gridStackItem") gridstackItems!: QueryList<ElementRef<GridItemHTMLElement>>;
|
|
39
|
-
|
|
40
|
-
/** set the items to display. */
|
|
41
|
-
@Input() public items: GridStackWidget[] = [
|
|
42
|
-
{x: 0, y: 0},
|
|
43
|
-
{x: 1, y: 1},
|
|
44
|
-
{x: 2, y: 2},
|
|
45
|
-
];
|
|
46
|
-
|
|
47
|
-
private grid!: GridStack;
|
|
48
|
-
private widgetToMake: Subject<{
|
|
49
|
-
action: "add" | "remove" | "update";
|
|
50
|
-
id: number;
|
|
51
|
-
}> = new Subject(); // consider to use a state management like ngrx component store to do this
|
|
52
|
-
|
|
53
|
-
constructor() {}
|
|
54
|
-
|
|
55
|
-
// wait until after DOM is ready to init gridstack - can't be ngOnInit() as angular ngFor needs to run first!
|
|
56
|
-
public ngAfterViewInit() {
|
|
57
|
-
this.grid = GridStack.init({
|
|
58
|
-
margin: 5,
|
|
59
|
-
float: true,
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
// To sync dom manipulation done by Angular and widget manipulation done by gridstack we need to zip the observables
|
|
63
|
-
zip(this.gridstackItems.changes, this.widgetToMake).subscribe(
|
|
64
|
-
([changedWidget, widgetToMake]) => {
|
|
65
|
-
if (widgetToMake.action === "add") {
|
|
66
|
-
this.grid.makeWidget(`#${widgetToMake.id}`);
|
|
67
|
-
} else if (widgetToMake.action === "remove") {
|
|
68
|
-
const id = String(widgetToMake.id);
|
|
69
|
-
// Note: DOM element has been removed by Angular already so look for it through the engine node list
|
|
70
|
-
const removeEl = this.grid.engine.nodes.find((n) => n.el?.id === id)?.el;
|
|
71
|
-
if (removeEl) this.grid.removeWidget(removeEl);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
);
|
|
75
|
-
|
|
76
|
-
// TODO: the problem with this code is that our items list does NOT reflect changes made by GS (user directly changing,
|
|
77
|
-
// or conflict during initial layout) and believe the other ngFor example (which does track changes) is also cleaner
|
|
78
|
-
// as it doesn't require user creating special action commands nor track 'both' changes using zip().
|
|
79
|
-
// TODO: identify() uses index which is not guaranteed to match between invocations (insert/delete in
|
|
80
|
-
// middle of list instead of end as demo does)
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* CRUD operations
|
|
85
|
-
*/
|
|
86
|
-
public add() {
|
|
87
|
-
this.items = [...this.items, { x: 3, y: 0, w: 3 }];
|
|
88
|
-
this.widgetToMake.next({ action: "add", id: this.items.length - 1 });
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
public delete() {
|
|
92
|
-
this.items.pop();
|
|
93
|
-
this.widgetToMake.next({ action: "remove", id: this.items.length });
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// a change of a widget doesn´t change to amount of items in ngFor therefore we don´t need to do it through the zip function above
|
|
97
|
-
public modify() {
|
|
98
|
-
const updateEl = this.grid.getGridItems().find((el) => el.id === `${0}`);
|
|
99
|
-
this.grid.update(updateEl!, { w: 2 });
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// ngFor lookup indexing
|
|
103
|
-
identify(index: number) {
|
|
104
|
-
return index;
|
|
105
|
-
}
|
|
106
|
-
}
|