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' ;
33import { GridstackComponent , NgGridStackWidget , elementCB , nodesCB } from './gridstack.component' ;
44
55// unique ids sets for each item for correct ngFor updating
@@ -9,9 +9,14 @@ let ids = 1;
99 templateUrl : './app.component.html' ,
1010 styleUrls : [ './app.component.css' ]
1111} )
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+
1318 // which sample to show
14- public show = 5 ;
19+ public show = 6 ; // nested
1520
1621 /** sample grid options and items to load... */
1722 public items : GridStackWidget [ ] = [
@@ -30,36 +35,61 @@ export class AppComponent {
3035 }
3136
3237 // 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 = {
3639 cellHeight : 50 , // should be 50 - top/bottom
3740 column : 'auto' , // size to match container. make sure to include gridstack-extra.min.css
3841 acceptWidgets : true , // will accept .grid-stack-item by default
3942 margin : 5 ,
4043 } ;
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+ ]
4151 public nestedGridOptions : GridStackOptions = { // main grid options
4252 cellHeight : 50 ,
4353 margin : 5 ,
4454 minRow : 2 , // don't collapse when empty
4555 disableOneColumnMode : true ,
4656 acceptWidgets : true ,
4757 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
5359 } ;
60+ private serializedData ?: GridStackOptions ;
5461
5562 constructor ( ) {
5663 // 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 ) => {
5865 if ( ! w . type && ! w . subGrid ) w . content = `item ${ ids } ` ;
5966 w . id = String ( ids ++ ) ;
6067 } ) ;
6168 }
6269
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+
6393 /** called whenever items change size/position/etc.. */
6494 public onChange ( data : nodesCB ) {
6595 // TODO: update our TEMPLATE list to match ?
@@ -74,19 +104,26 @@ export class AppComponent {
74104 /**
75105 * TEST dynamic grid operations - uses grid API directly (since we don't track structure that gets out of sync)
76106 */
77- public add ( gridComp : GridstackComponent ) {
107+ public add ( ) {
78108 // TODO: BUG the content doesn't appear until widget is moved around (or another created). Need to force
79109 // 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 ++ ) } ) ;
81111 }
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 ! ) ;
84121 }
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 } )
87124 }
88- public newLayout ( gridComp : GridstackComponent ) {
89- gridComp . grid ?. load ( [
125+ public newLayout ( ) {
126+ this . gridComp ? .grid ?. load ( [
90127 { x :0 , y :1 , id :'1' , minW :1 , w :1 } , // new size/constrain
91128 { x :1 , y :1 , id :'2' } ,
92129 // {x:2, y:1, id:'3'}, // delete item
@@ -105,10 +142,10 @@ export class AppComponent {
105142 public deleteNgFor ( ) {
106143 this . items . pop ( ) ;
107144 }
108- public modifyNgFor ( gridComp : GridstackComponent ) {
145+ public modifyNgFor ( ) {
109146 // this will not update the DOM nor trigger gridstackItems.changes for GS to auto-update, so set new option of the gridItem instead
110147 // this.items[0].w = 3;
111- const gridItem = gridComp . gridstackItems ?. get ( 0 ) ;
148+ const gridItem = this . gridComp ? .gridstackItems ?. get ( 0 ) ;
112149 if ( gridItem ) gridItem . options = { w :3 } ;
113150 }
114151 public newLayoutNgFor ( ) {
@@ -119,6 +156,18 @@ export class AppComponent {
119156 { x :3 , y :0 , w :2 , content :'new item' } , // new item
120157 ] ;
121158 }
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+ }
122171
123172 // ngFor TEMPLATE unique node id to have correct match between our items used and GS
124173 public identify ( index : number , w : GridStackWidget ) {
0 commit comments