1
- import { Component } from '@angular/core' ;
2
- import { GridStackOptions , GridStackWidget } from 'gridstack' ;
1
+ import { Component , OnInit , ViewChild , ElementRef } from '@angular/core' ;
2
+ import { GridStack , GridStackOptions , GridStackWidget } from 'gridstack' ;
3
3
import { GridstackComponent , NgGridStackWidget , elementCB , nodesCB } from './gridstack.component' ;
4
4
5
5
// unique ids sets for each item for correct ngFor updating
@@ -9,9 +9,14 @@ let ids = 1;
9
9
templateUrl : './app.component.html' ,
10
10
styleUrls : [ './app.component.css' ]
11
11
} )
12
- export class AppComponent {
12
+ export class AppComponent implements OnInit {
13
+
14
+ @ViewChild ( GridstackComponent ) gridComp ?: GridstackComponent ;
15
+ @ViewChild ( 'origTextArea' , { static : true } ) origTextEl ?: ElementRef < HTMLTextAreaElement > ;
16
+ @ViewChild ( 'textArea' , { static : true } ) textEl ?: ElementRef < HTMLTextAreaElement > ;
17
+
13
18
// which sample to show
14
- public show = 5 ;
19
+ public show = 6 ; // nested
15
20
16
21
/** sample grid options and items to load... */
17
22
public items : GridStackWidget [ ] = [
@@ -30,36 +35,61 @@ export class AppComponent {
30
35
}
31
36
32
37
// nested grid options
33
- public sub1 : NgGridStackWidget [ ] = [ { x :0 , y :0 , type :'app-a' } , { x :1 , y :0 , type :'app-b' } , { x :2 , y :0 , type :'app-c' } , { x :3 , y :0 } , { x :0 , y :1 } , { x :1 , y :1 } ] ;
34
- public sub2 : NgGridStackWidget [ ] = [ { x :0 , y :0 } , { x :0 , y :1 , w :2 } ] ;
35
- public subOptions : GridStackOptions = {
38
+ private subOptions : GridStackOptions = {
36
39
cellHeight : 50 , // should be 50 - top/bottom
37
40
column : 'auto' , // size to match container. make sure to include gridstack-extra.min.css
38
41
acceptWidgets : true , // will accept .grid-stack-item by default
39
42
margin : 5 ,
40
43
} ;
44
+ private sub1 : NgGridStackWidget [ ] = [ { x :0 , y :0 , type :'app-a' } , { x :1 , y :0 , type :'app-b' } , { x :2 , y :0 , type :'app-c' } , { x :3 , y :0 } , { x :0 , y :1 } , { x :1 , y :1 } ] ;
45
+ private sub2 : NgGridStackWidget [ ] = [ { x :0 , y :0 } , { x :0 , y :1 , w :2 } ] ;
46
+ private subChildren : NgGridStackWidget [ ] = [
47
+ { x :0 , y :0 , content : 'regular item' } ,
48
+ { x :1 , y :0 , w :4 , h :4 , subGrid : { children : this . sub1 , id :'sub1_grid' , class : 'sub1' , ...this . subOptions } } ,
49
+ { x :5 , y :0 , w :3 , h :4 , subGrid : { children : this . sub2 , id :'sub2_grid' , class : 'sub2' , ...this . subOptions } } ,
50
+ ]
41
51
public nestedGridOptions : GridStackOptions = { // main grid options
42
52
cellHeight : 50 ,
43
53
margin : 5 ,
44
54
minRow : 2 , // don't collapse when empty
45
55
disableOneColumnMode : true ,
46
56
acceptWidgets : true ,
47
57
id : 'main' ,
48
- children : [
49
- { x :0 , y :0 , content : 'regular item' , id : 0 } ,
50
- { x :1 , y :0 , w :4 , h :4 , subGrid : { children : this . sub1 , id :'sub1_grid' , class : 'sub1' , ...this . subOptions } } ,
51
- { x :5 , y :0 , w :3 , h :4 , subGrid : { children : this . sub2 , id :'sub2_grid' , class : 'sub2' , ...this . subOptions } } ,
52
- ]
58
+ children : this . subChildren
53
59
} ;
60
+ private serializedData ?: GridStackOptions ;
54
61
55
62
constructor ( ) {
56
63
// give them content and unique id to make sure we track them during changes below...
57
- [ ...this . items , ...this . sub1 , ...this . sub2 ] . forEach ( ( w : NgGridStackWidget ) => {
64
+ [ ...this . items , ...this . subChildren , ... this . sub1 , ...this . sub2 ] . forEach ( ( w : NgGridStackWidget ) => {
58
65
if ( ! w . type && ! w . subGrid ) w . content = `item ${ ids } ` ;
59
66
w . id = String ( ids ++ ) ;
60
67
} ) ;
61
68
}
62
69
70
+ ngOnInit ( ) : void {
71
+ this . onShow ( this . show ) ;
72
+
73
+ // TEST
74
+ // setTimeout(() => {
75
+ // if (!this.gridComp) return;
76
+ // this.saveGrid();
77
+ // this.clearGrid();
78
+ // // this.loadGrid();
79
+ // }, 500)
80
+ }
81
+
82
+ public onShow ( val : number ) {
83
+ this . show = val ;
84
+ const data = val === 6 ? this . nestedGridOptions : this . gridOptionsFull ;
85
+ if ( this . origTextEl ) this . origTextEl . nativeElement . value = JSON . stringify ( data , null , ' ' ) ;
86
+
87
+ // if (val === 6 && !this.gridComp) {
88
+ // const cont: HTMLElement | null = document.querySelector('.grid-container');
89
+ // if (cont) GridStack.addGrid(cont, this.serializedData);
90
+ // }
91
+ }
92
+
63
93
/** called whenever items change size/position/etc.. */
64
94
public onChange ( data : nodesCB ) {
65
95
// TODO: update our TEMPLATE list to match ?
@@ -74,19 +104,26 @@ export class AppComponent {
74
104
/**
75
105
* TEST dynamic grid operations - uses grid API directly (since we don't track structure that gets out of sync)
76
106
*/
77
- public add ( gridComp : GridstackComponent ) {
107
+ public add ( ) {
78
108
// TODO: BUG the content doesn't appear until widget is moved around (or another created). Need to force
79
109
// angular detection changes...
80
- gridComp . grid ?. addWidget ( { x :3 , y :0 , w :2 , content :`item ${ ids } ` , id :String ( ids ++ ) } ) ;
110
+ this . gridComp ? .grid ?. addWidget ( { x :3 , y :0 , w :2 , content :`item ${ ids } ` , id :String ( ids ++ ) } ) ;
81
111
}
82
- public delete ( gridComp : GridstackComponent ) {
83
- gridComp . grid ?. removeWidget ( gridComp . grid . engine . nodes [ 0 ] ?. el ! ) ;
112
+ public delete ( ) {
113
+ let grid = this . gridComp ?. grid ;
114
+ if ( ! grid ) return ;
115
+ let node = grid . engine . nodes [ 0 ] ;
116
+ if ( node ?. subGrid ) {
117
+ grid = node . subGrid as GridStack ;
118
+ node = grid ?. engine . nodes [ 0 ] ;
119
+ }
120
+ if ( node ) grid . removeWidget ( node . el ! ) ;
84
121
}
85
- public modify ( gridComp : GridstackComponent ) {
86
- gridComp . grid ?. update ( gridComp . grid . engine . nodes [ 0 ] ?. el ! , { w :3 } )
122
+ public modify ( ) {
123
+ this . gridComp ? .grid ?. update ( this . gridComp ? .grid . engine . nodes [ 0 ] ?. el ! , { w :3 } )
87
124
}
88
- public newLayout ( gridComp : GridstackComponent ) {
89
- gridComp . grid ?. load ( [
125
+ public newLayout ( ) {
126
+ this . gridComp ? .grid ?. load ( [
90
127
{ x :0 , y :1 , id :'1' , minW :1 , w :1 } , // new size/constrain
91
128
{ x :1 , y :1 , id :'2' } ,
92
129
// {x:2, y:1, id:'3'}, // delete item
@@ -105,10 +142,10 @@ export class AppComponent {
105
142
public deleteNgFor ( ) {
106
143
this . items . pop ( ) ;
107
144
}
108
- public modifyNgFor ( gridComp : GridstackComponent ) {
145
+ public modifyNgFor ( ) {
109
146
// this will not update the DOM nor trigger gridstackItems.changes for GS to auto-update, so set new option of the gridItem instead
110
147
// this.items[0].w = 3;
111
- const gridItem = gridComp . gridstackItems ?. get ( 0 ) ;
148
+ const gridItem = this . gridComp ? .gridstackItems ?. get ( 0 ) ;
112
149
if ( gridItem ) gridItem . options = { w :3 } ;
113
150
}
114
151
public newLayoutNgFor ( ) {
@@ -119,6 +156,18 @@ export class AppComponent {
119
156
{ x :3 , y :0 , w :2 , content :'new item' } , // new item
120
157
] ;
121
158
}
159
+ public clearGrid ( ) {
160
+ if ( ! this . gridComp ) return ;
161
+ this . gridComp . grid ?. removeAll ( true ) ;
162
+ }
163
+ public saveGrid ( ) {
164
+ this . serializedData = this . gridComp ?. grid ?. save ( false , true ) as GridStackOptions || '' ; // no content, full options
165
+ if ( this . textEl ) this . textEl . nativeElement . value = JSON . stringify ( this . serializedData , null , ' ' ) ;
166
+ }
167
+ public loadGrid ( ) {
168
+ if ( ! this . gridComp ) return ;
169
+ GridStack . addGrid ( this . gridComp . el , this . serializedData ) ;
170
+ }
122
171
123
172
// ngFor TEMPLATE unique node id to have correct match between our items used and GS
124
173
public identify ( index : number , w : GridStackWidget ) {
0 commit comments