Skip to content

Commit e77579e

Browse files
authored
Merge pull request #2255 from adumesny/master
Angular demo update
2 parents 6dbfe51 + 4bc23c3 commit e77579e

File tree

5 files changed

+95
-36
lines changed

5 files changed

+95
-36
lines changed

demo/angular/src/app/app.component.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Component } from '@angular/core';
22
import { GridStackOptions, GridStackWidget } from 'gridstack';
3-
import { GridstackComponent, elementCB, nodesCB } from './gridstack.component';
3+
import { GridstackComponent, NgGridStackWidget, elementCB, nodesCB } from './gridstack.component';
44

55
// unique ids sets for each item for correct ngFor updating
66
let ids = 1;
@@ -30,8 +30,8 @@ export class AppComponent {
3030
}
3131

3232
// nested grid options
33-
public sub1: GridStackWidget[] = [ {x:0, y:0}, {x:1, y:0}, {x:2, y:0}, {x:3, y:0}, {x:0, y:1}, {x:1, y:1}];
34-
public sub2: GridStackWidget[] = [ {x:0, y:0}, {x:0, y:1, w:2}];
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}];
3535
public subOptions: GridStackOptions = {
3636
cellHeight: 50, // should be 50 - top/bottom
3737
column: 'auto', // size to match container. make sure to include gridstack-extra.min.css
@@ -54,8 +54,8 @@ export class AppComponent {
5454

5555
constructor() {
5656
// give them content and unique id to make sure we track them during changes below...
57-
[...this.items, ...this.sub1, ...this.sub2].forEach(w => {
58-
w.content = `item ${ids}`;
57+
[...this.items, ...this.sub1, ...this.sub2].forEach((w: NgGridStackWidget) => {
58+
if (!w.type && !w.subGrid) w.content = `item ${ids}`;
5959
w.id = String(ids++);
6060
});
6161
}

demo/angular/src/app/app.module.ts

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1-
import { NgModule } from '@angular/core';
2-
import { BrowserModule } from '@angular/platform-browser';
3-
4-
import { AppComponent } from './app.component';
5-
import { GridstackItemComponent } from './gridstack-item.component';
6-
import { GridstackComponent } from './gridstack.component';
7-
import { AngularNgForTestComponent } from './ngFor';
8-
import { AngularNgForCmdTestComponent } from './ngFor_cmd';
9-
import { AngularSimpleComponent } from './simple';
10-
1+
import { NgModule } from '@angular/core';
2+
import { BrowserModule } from '@angular/platform-browser';
3+
4+
import { AppComponent } from './app.component';
5+
import { GridstackItemComponent } from './gridstack-item.component';
6+
import { GridstackComponent } from './gridstack.component';
7+
import { AngularNgForTestComponent } from './ngFor';
8+
import { AngularNgForCmdTestComponent } from './ngFor_cmd';
9+
import { AngularSimpleComponent } from './simple';
10+
import { AComponent, BComponent, CComponent } from './dummy.component';
11+
1112
@NgModule({
1213
declarations: [
1314
AngularNgForCmdTestComponent,
@@ -16,6 +17,9 @@ import { AngularSimpleComponent } from './simple';
1617
AppComponent,
1718
GridstackComponent,
1819
GridstackItemComponent,
20+
AComponent,
21+
BComponent,
22+
CComponent,
1923
],
2024
imports: [
2125
BrowserModule
@@ -26,5 +30,5 @@ import { AngularSimpleComponent } from './simple';
2630
],
2731
providers: [],
2832
bootstrap: [AppComponent]
29-
})
30-
export class AppModule { }
33+
})
34+
export class AppModule { }
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/**
2+
* gridstack.component.ts 7.3.0-dev
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, Type } from '@angular/core';
9+
10+
@Component({
11+
selector: 'app-a',
12+
template: 'Comp A',
13+
})
14+
export class AComponent {
15+
}
16+
17+
@Component({
18+
selector: 'app-b',
19+
template: 'Comp B',
20+
})
21+
export class BComponent {
22+
}
23+
24+
@Component({
25+
selector: 'app-c',
26+
template: 'Comp C',
27+
})
28+
export class CComponent {
29+
}
30+
31+
/**
32+
* stores the selector -> Type mapping, so we can create items dynamically from a string.
33+
* Unfortunately Ng doesn't provide public access to that mapping.
34+
*/
35+
export const selectorToComponent: {[key: string]: Type<Object>} = {
36+
'app-a': AComponent,
37+
'app-b': BComponent,
38+
'app-c': CComponent,
39+
};

demo/angular/src/app/gridstack-item.component.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,12 @@ export interface GridItemCompHTMLElement extends GridItemHTMLElement {
1818
selector: 'gridstack-item',
1919
template: `
2020
<div class="grid-stack-item-content">
21-
<!-- this is where you would create the right component based on some internal type or id. doing .content for demo purpose -->
21+
<!-- TODO: this is where you would create the right component based on some internal type or id IFF !this.options.subGrid
22+
Doing options.content for demo purpose -->
2223
{{options.content}}
24+
<!-- any static (defined in dom) content goes here -->
2325
<ng-content></ng-content>
24-
<!-- where dynamic items go (like sub-grids) -->
26+
<!-- where dynamic items go (like sub-grids, other dynamic NgComponents, etc...) -->
2527
<ng-template #container></ng-template>
2628
</div>`,
2729
styles: [`

demo/angular/src/app/gridstack.component.ts

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,20 @@ import { takeUntil } from 'rxjs/operators';
1010
import { GridHTMLElement, GridItemHTMLElement, GridStack, GridStackNode, GridStackOptions, GridStackWidget } from 'gridstack';
1111

1212
import { GridItemCompHTMLElement, GridstackItemComponent } from './gridstack-item.component';
13+
import { selectorToComponent } from './dummy.component';
1314

1415
/** events handlers emitters signature for different events */
1516
export type eventCB = {event: Event};
1617
export type elementCB = {event: Event, el: GridItemHTMLElement};
1718
export type nodesCB = {event: Event, nodes: GridStackNode[]};
1819
export type droppedCB = {event: Event, previousNode: GridStackNode, newNode: GridStackNode};
1920

21+
22+
/** extends to store Ng Component selector, instead/inAddition to content */
23+
export interface NgGridStackWidget extends GridStackWidget {
24+
type?: string; // component type to create as content
25+
}
26+
2027
/** store element to Ng Class pointer back */
2128
export interface GridCompHTMLElement extends GridHTMLElement {
2229
_gridComp?: GridstackComponent;
@@ -96,7 +103,7 @@ export class GridstackComponent implements OnInit, AfterContentInit, OnDestroy {
96103
public ngOnInit(): void {
97104
// inject our own addRemove so we can create GridItemComponent instead of simple divs
98105
const opts: GridStackOptions = this._options || {};
99-
opts.addRemoveCB = GridstackComponent._addRemoveCB;
106+
opts.addRemoveCB = addRemoveCB;
100107

101108
// init ourself before any template children are created since we track them below anyway - no need to double create+update widgets
102109
this.loaded = !!this.options?.children?.length;
@@ -162,24 +169,31 @@ export class GridstackComponent implements OnInit, AfterContentInit, OnDestroy {
162169
.on('resizestart', (event: Event, el: GridItemHTMLElement) => this.zone.run(() => this.resizeStartCB.emit({event, el})))
163170
.on('resizestop', (event: Event, el: GridItemHTMLElement) => this.zone.run(() => this.resizeStopCB.emit({event, el})))
164171
}
172+
}
165173

166-
/** called by GS when a new item needs to be created, which we do as a Angular component, or deleted (skip) */
167-
private static _addRemoveCB(parent: GridCompHTMLElement | HTMLElement, w: GridStackWidget | GridStackOptions, add: boolean, isGrid: boolean): HTMLElement | undefined {
168-
if (add) {
169-
if (!parent) return;
170-
// create the grid item dynamically - see https://angular.io/docs/ts/latest/cookbook/dynamic-component-loader.html
171-
if (isGrid) {
172-
const gridItemComp = (parent.parentElement as GridItemCompHTMLElement)._gridItemComp;
173-
const grid = gridItemComp?.container?.createComponent(GridstackComponent)?.instance;
174-
if (grid) grid.options = w as GridStackOptions;
175-
return grid?.el;
176-
} else {
177-
// TODO: use GridStackWidget to define what type of component to create as child, or do it in GridstackItemComponent template...
178-
const gridComp = (parent as GridCompHTMLElement)._gridComp;
179-
const gridItem = gridComp?.container?.createComponent(GridstackItemComponent)?.instance;
180-
return gridItem?.el;
174+
/** called by GS when a new item needs to be created, which we do as a Angular component, or deleted (skip) */
175+
function addRemoveCB(parent: GridCompHTMLElement | HTMLElement, w: NgGridStackWidget | GridStackOptions, add: boolean, isGrid: boolean): HTMLElement | undefined {
176+
if (add) {
177+
if (!parent) return;
178+
// create the grid item dynamically - see https://angular.io/docs/ts/latest/cookbook/dynamic-component-loader.html
179+
if (isGrid) {
180+
const gridItemComp = (parent.parentElement as GridItemCompHTMLElement)._gridItemComp;
181+
const grid = gridItemComp?.container?.createComponent(GridstackComponent)?.instance;
182+
if (grid) grid.options = w as GridStackOptions;
183+
return grid?.el;
184+
} else {
185+
const gridComp = (parent as GridCompHTMLElement)._gridComp;
186+
const gridItem = gridComp?.container?.createComponent(GridstackItemComponent)?.instance;
187+
188+
// IFF we're not a subGrid, define what type of component to create as child, OR you can do it GridstackItemComponent template, but this is more generic
189+
const type = (w as NgGridStackWidget).type;
190+
if (!w.subGrid && type && selectorToComponent[type]) {
191+
gridItem?.container?.createComponent(selectorToComponent[type]);
181192
}
193+
194+
return gridItem?.el;
182195
}
183-
return;
184196
}
197+
return;
185198
}
199+

0 commit comments

Comments
 (0)