diff --git a/examples/app1/src/app/app.module.ts b/examples/app1/src/app/app.module.ts
index 5c56a06..973ce95 100644
--- a/examples/app1/src/app/app.module.ts
+++ b/examples/app1/src/app/app.module.ts
@@ -10,9 +10,10 @@ import { AppRootComponent } from './root/root.component';
import { DemoCommonModule } from '@demo/common';
import { NgxPlanetModule } from 'ngx-planet';
import { UserModule } from './user/user.module';
+import { ProjectsComponent } from './projects/projects.component';
@NgModule({
- declarations: [AppComponent, AppRootComponent, DashboardComponent],
+ declarations: [AppComponent, AppRootComponent, DashboardComponent, ProjectsComponent],
imports: [
BrowserModule,
RouterModule.forRoot(routers),
diff --git a/examples/app1/src/app/app.routing.ts b/examples/app1/src/app/app.routing.ts
index 6708b2f..fd50bf0 100644
--- a/examples/app1/src/app/app.routing.ts
+++ b/examples/app1/src/app/app.routing.ts
@@ -2,6 +2,7 @@ import { DashboardComponent } from './dashboard/dashboard.component';
import { Route } from '@angular/router';
import { AppRootComponent } from './root/root.component';
import { EmptyComponent } from 'ngx-planet';
+import { ProjectsComponent } from './projects/projects.component';
export const routers: Route[] = [
{
@@ -20,6 +21,10 @@ export const routers: Route[] = [
{
path: 'users',
loadChildren: () => import('./user/user.module').then(mod => mod.UserModule)
+ },
+ {
+ path: 'projects',
+ component: ProjectsComponent
}
// {
// path: 'users',
diff --git a/examples/app1/src/app/dashboard/dashboard.component.html b/examples/app1/src/app/dashboard/dashboard.component.html
index da318f6..fec665b 100644
--- a/examples/app1/src/app/dashboard/dashboard.component.html
+++ b/examples/app1/src/app/dashboard/dashboard.component.html
@@ -17,8 +17,8 @@
count: {{ counter.count }}
-
-
+
+
diff --git a/examples/app1/src/app/dashboard/dashboard.component.ts b/examples/app1/src/app/dashboard/dashboard.component.ts
index b0f5ec8..b00c436 100644
--- a/examples/app1/src/app/dashboard/dashboard.component.ts
+++ b/examples/app1/src/app/dashboard/dashboard.component.ts
@@ -1,4 +1,4 @@
-import { Component, Inject, ViewChild, ElementRef } from '@angular/core';
+import { Component, Inject, ViewChild, ElementRef, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { CounterService } from '../counter.service';
import { AppRootContext } from '@demo/common';
@@ -9,7 +9,7 @@ import { ThyDialog } from 'ngx-tethys';
selector: 'app-dashboard',
templateUrl: './dashboard.component.html'
})
-export class DashboardComponent {
+export class DashboardComponent implements OnInit {
@ViewChild('container', { static: true }) containerElementRef: ElementRef;
private componentRef: PlanetComponentRef;
@@ -24,15 +24,21 @@ export class DashboardComponent {
private planetComponentLoader: PlanetComponentLoader
) {}
+ ngOnInit() {}
+
openADetail() {
this.globalEventDispatcher.dispatch('openADetail');
}
openApp2Component() {
- this.componentRef = this.planetComponentLoader.load('app2', 'project1', {
- container: this.containerElementRef,
- initialState: {}
- });
+ this.planetComponentLoader
+ .load('app2', 'project1', {
+ container: this.containerElementRef,
+ initialState: {}
+ })
+ .subscribe(componentRef => {
+ this.componentRef = componentRef;
+ });
}
disposeApp2Component() {
diff --git a/examples/app1/src/app/projects/projects.component.ts b/examples/app1/src/app/projects/projects.component.ts
new file mode 100644
index 0000000..7084178
--- /dev/null
+++ b/examples/app1/src/app/projects/projects.component.ts
@@ -0,0 +1,32 @@
+import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
+import { PlanetComponentLoader } from 'ngx-planet';
+
+@Component({
+ selector: 'app-projects',
+ template: `
+
+
+
+
+ `
+})
+export class ProjectsComponent implements OnInit {
+ @ViewChild('container', { static: true }) elementRef: ElementRef;
+
+ loadingDone = false;
+
+ constructor(private planetComponentLoader: PlanetComponentLoader) {}
+
+ ngOnInit() {
+ this.planetComponentLoader
+ .load('app2', 'project1', {
+ container: this.elementRef
+ })
+ .subscribe(componentRef => {
+ this.loadingDone = true;
+ componentRef.componentInstance.click.subscribe(() => {
+ console.log('project item clicked');
+ });
+ });
+ }
+}
diff --git a/examples/app1/src/app/root/root.component.html b/examples/app1/src/app/root/root.component.html
index 80c58ae..2a4b9d4 100644
--- a/examples/app1/src/app/root/root.component.html
+++ b/examples/app1/src/app/root/root.component.html
@@ -8,6 +8,7 @@
App1 Dashboard
App1 Users
+ App2 Projects
diff --git a/examples/app2/src/app/projects/project-list.component.ts b/examples/app2/src/app/projects/project-list.component.ts
index ccfd1eb..94ea586 100644
--- a/examples/app2/src/app/projects/project-list.component.ts
+++ b/examples/app2/src/app/projects/project-list.component.ts
@@ -43,13 +43,12 @@ export class ProjectListComponent implements OnInit, DoCheck {
openDetail(event: ThyGridRowEvent) {
this.router.navigateByUrl(`/app2/projects/${event.row.id}`);
+ this.click.emit();
// this.dialog.open(ProjectDetailComponent, {
// hasBackdrop: true,
// backdropClosable: true,
// closeOnNavigation: true
// });
-
- // this.click.emit();
}
ngDoCheck() {
diff --git a/package-lock.json b/package-lock.json
index 0a02841..a1ddda9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -457,8 +457,7 @@
"ansi-regex": {
"version": "2.1.1",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"aproba": {
"version": "1.2.0",
@@ -479,14 +478,12 @@
"balanced-match": {
"version": "1.0.0",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -501,20 +498,17 @@
"code-point-at": {
"version": "1.1.0",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"core-util-is": {
"version": "1.0.2",
@@ -631,8 +625,7 @@
"inherits": {
"version": "2.0.4",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"ini": {
"version": "1.3.5",
@@ -644,7 +637,6 @@
"version": "1.0.0",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@@ -659,7 +651,6 @@
"version": "3.0.4",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@@ -667,14 +658,12 @@
"minimist": {
"version": "0.0.8",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"minipass": {
"version": "2.9.0",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
@@ -693,7 +682,6 @@
"version": "0.5.1",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"minimist": "0.0.8"
}
@@ -783,8 +771,7 @@
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"object-assign": {
"version": "4.1.1",
@@ -796,7 +783,6 @@
"version": "1.4.0",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"wrappy": "1"
}
@@ -882,8 +868,7 @@
"safe-buffer": {
"version": "5.1.2",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"safer-buffer": {
"version": "2.1.2",
@@ -919,7 +904,6 @@
"version": "1.0.2",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@@ -939,7 +923,6 @@
"version": "3.0.1",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@@ -983,14 +966,12 @@
"wrappy": {
"version": "1.0.2",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"yallist": {
"version": "3.1.1",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
}
}
},
@@ -8690,8 +8671,7 @@
"ansi-regex": {
"version": "2.1.1",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"aproba": {
"version": "1.2.0",
@@ -8712,14 +8692,12 @@
"balanced-match": {
"version": "1.0.0",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -8734,20 +8712,17 @@
"code-point-at": {
"version": "1.1.0",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"core-util-is": {
"version": "1.0.2",
@@ -8864,8 +8839,7 @@
"inherits": {
"version": "2.0.4",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"ini": {
"version": "1.3.5",
@@ -8877,7 +8851,6 @@
"version": "1.0.0",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@@ -8892,7 +8865,6 @@
"version": "3.0.4",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@@ -8900,14 +8872,12 @@
"minimist": {
"version": "0.0.8",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"minipass": {
"version": "2.9.0",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
@@ -8926,7 +8896,6 @@
"version": "0.5.1",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"minimist": "0.0.8"
}
@@ -9016,8 +8985,7 @@
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"object-assign": {
"version": "4.1.1",
@@ -9029,7 +8997,6 @@
"version": "1.4.0",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"wrappy": "1"
}
@@ -9115,8 +9082,7 @@
"safe-buffer": {
"version": "5.1.2",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"safer-buffer": {
"version": "2.1.2",
@@ -9152,7 +9118,6 @@
"version": "1.0.2",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@@ -9172,7 +9137,6 @@
"version": "3.0.1",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@@ -9216,14 +9180,12 @@
"wrappy": {
"version": "1.0.2",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"yallist": {
"version": "3.1.1",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
}
}
},
@@ -10293,8 +10255,7 @@
"ansi-regex": {
"version": "2.1.1",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"aproba": {
"version": "1.2.0",
@@ -10315,14 +10276,12 @@
"balanced-match": {
"version": "1.0.0",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -10337,20 +10296,17 @@
"code-point-at": {
"version": "1.1.0",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"core-util-is": {
"version": "1.0.2",
@@ -10467,8 +10423,7 @@
"inherits": {
"version": "2.0.4",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"ini": {
"version": "1.3.5",
@@ -10480,7 +10435,6 @@
"version": "1.0.0",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@@ -10495,7 +10449,6 @@
"version": "3.0.4",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@@ -10503,14 +10456,12 @@
"minimist": {
"version": "0.0.8",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"minipass": {
"version": "2.9.0",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
@@ -10529,7 +10480,6 @@
"version": "0.5.1",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"minimist": "0.0.8"
}
@@ -10619,8 +10569,7 @@
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"object-assign": {
"version": "4.1.1",
@@ -10632,7 +10581,6 @@
"version": "1.4.0",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"wrappy": "1"
}
@@ -10718,8 +10666,7 @@
"safe-buffer": {
"version": "5.1.2",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"safer-buffer": {
"version": "2.1.2",
@@ -10755,7 +10702,6 @@
"version": "1.0.2",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@@ -10775,7 +10721,6 @@
"version": "3.0.1",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@@ -10819,14 +10764,12 @@
"wrappy": {
"version": "1.0.2",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"yallist": {
"version": "3.1.1",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
}
}
},
@@ -14256,9 +14199,9 @@
}
},
"sortablejs": {
- "version": "1.10.2",
- "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.10.2.tgz",
- "integrity": "sha512-YkPGufevysvfwn5rfdlGyrGjt7/CRHwvRPogD/lC+TnvcN29jDpCifKP+rBqf+LRldfXSTh+0CGLcSg0VIxq3A=="
+ "version": "1.8.4",
+ "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.8.4.tgz",
+ "integrity": "sha512-Brqnzelu1AhFuc0Fn3N/qFex1tlIiuQIUsfu2J8luJ4cRgXYkWrByxa+y5mWEBlj8A0YoABukflIJwvHyrwJ6Q=="
},
"source-list-map": {
"version": "2.0.1",
@@ -15683,8 +15626,7 @@
"ansi-regex": {
"version": "2.1.1",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"aproba": {
"version": "1.2.0",
@@ -15705,14 +15647,12 @@
"balanced-match": {
"version": "1.0.0",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -15727,20 +15667,17 @@
"code-point-at": {
"version": "1.1.0",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"core-util-is": {
"version": "1.0.2",
@@ -15857,8 +15794,7 @@
"inherits": {
"version": "2.0.4",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"ini": {
"version": "1.3.5",
@@ -15870,7 +15806,6 @@
"version": "1.0.0",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@@ -15885,7 +15820,6 @@
"version": "3.0.4",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@@ -15893,14 +15827,12 @@
"minimist": {
"version": "0.0.8",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"minipass": {
"version": "2.9.0",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
@@ -15919,7 +15851,6 @@
"version": "0.5.1",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"minimist": "0.0.8"
}
@@ -16009,8 +15940,7 @@
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"object-assign": {
"version": "4.1.1",
@@ -16022,7 +15952,6 @@
"version": "1.4.0",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"wrappy": "1"
}
@@ -16108,8 +16037,7 @@
"safe-buffer": {
"version": "5.1.2",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"safer-buffer": {
"version": "2.1.2",
@@ -16145,7 +16073,6 @@
"version": "1.0.2",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@@ -16165,7 +16092,6 @@
"version": "3.0.1",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@@ -16209,14 +16135,12 @@
"wrappy": {
"version": "1.0.2",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"yallist": {
"version": "3.1.1",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
}
}
},
@@ -16531,8 +16455,7 @@
"ansi-regex": {
"version": "2.1.1",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"aproba": {
"version": "1.2.0",
@@ -16553,14 +16476,12 @@
"balanced-match": {
"version": "1.0.0",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -16575,20 +16496,17 @@
"code-point-at": {
"version": "1.1.0",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"core-util-is": {
"version": "1.0.2",
@@ -16705,8 +16623,7 @@
"inherits": {
"version": "2.0.4",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"ini": {
"version": "1.3.5",
@@ -16718,7 +16635,6 @@
"version": "1.0.0",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@@ -16733,7 +16649,6 @@
"version": "3.0.4",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@@ -16741,14 +16656,12 @@
"minimist": {
"version": "0.0.8",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"minipass": {
"version": "2.9.0",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
@@ -16767,7 +16680,6 @@
"version": "0.5.1",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"minimist": "0.0.8"
}
@@ -16857,8 +16769,7 @@
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"object-assign": {
"version": "4.1.1",
@@ -16870,7 +16781,6 @@
"version": "1.4.0",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"wrappy": "1"
}
@@ -16956,8 +16866,7 @@
"safe-buffer": {
"version": "5.1.2",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"safer-buffer": {
"version": "2.1.2",
@@ -16993,7 +16902,6 @@
"version": "1.0.2",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@@ -17013,7 +16921,6 @@
"version": "3.0.1",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@@ -17057,14 +16964,12 @@
"wrappy": {
"version": "1.0.2",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"yallist": {
"version": "3.1.1",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
}
}
},
diff --git a/package.json b/package.json
index bd86f1b..5667752 100644
--- a/package.json
+++ b/package.json
@@ -55,7 +55,7 @@
"ngx-bootstrap": "^5.2.0",
"ngx-tethys": "^7.6.16",
"rxjs": "~6.4.0",
- "sortablejs": "^1.10.1",
+ "sortablejs": "1.8.4",
"tslib": "^1.10.0",
"zone.js": "~0.9.1",
"bootstrap": "4.3.1"
diff --git a/packages/planet/src/application/planet-application-ref.ts b/packages/planet/src/application/planet-application-ref.ts
index 9d61c67..0a4c9a8 100644
--- a/packages/planet/src/application/planet-application-ref.ts
+++ b/packages/planet/src/application/planet-application-ref.ts
@@ -10,11 +10,13 @@ import { Observable, from } from 'rxjs';
declare const window: any;
export interface GlobalPlanet {
apps: { [key: string]: PlanetApplicationRef };
+ registerApps: PlanetApplication[];
portalApplication: PlanetPortalApplication;
}
const globalPlanet: GlobalPlanet = (window.planet = window.planet || {
- apps: {}
+ apps: {},
+ registerApps: []
});
export type BootstrapAppModule = (portalApp?: PlanetPortalApplication) => Promise>;
@@ -88,12 +90,12 @@ export class PlanetApplicationRef {
});
}
- registerComponentFactory(componentFactory: PlantComponentFactory) {
- this.componentFactory = componentFactory;
+ getComponentFactory() {
+ return this.componentFactory;
}
- loadPlantComponent(componentName: string, config: PlantComponentConfig) {
- return this.componentFactory(componentName, config);
+ registerComponentFactory(componentFactory: PlantComponentFactory) {
+ this.componentFactory = componentFactory;
}
destroy(): void {
diff --git a/packages/planet/src/application/planet-application.service.spec.ts b/packages/planet/src/application/planet-application.service.spec.ts
index 71e0cd6..2c77aa7 100644
--- a/packages/planet/src/application/planet-application.service.spec.ts
+++ b/packages/planet/src/application/planet-application.service.spec.ts
@@ -1,6 +1,6 @@
import { TestBed } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
-import { PlanetApplicationService } from './planet-application.service';
+import { PlanetApplicationService, getPlanetApplicationByName } from './planet-application.service';
import { SwitchModes } from '../planet.class';
import { HttpClient } from '@angular/common/http';
import { app1, app2, app2WithPreload } from '../test/applications';
@@ -154,4 +154,13 @@ describe('PlanetApplicationService', () => {
expect(appsToPreload).toEqual([]);
});
});
+
+ describe('getPlanetApplicationByName', () => {
+ it('should get planet application by name', () => {
+ planetApplicationService.register(app1);
+ const app = getPlanetApplicationByName(app1.name);
+ expect(app).toBe(app1);
+ expect(getPlanetApplicationByName(app2.name)).toEqual(undefined);
+ });
+ });
});
diff --git a/packages/planet/src/application/planet-application.service.ts b/packages/planet/src/application/planet-application.service.ts
index f68aac1..a3ba236 100644
--- a/packages/planet/src/application/planet-application.service.ts
+++ b/packages/planet/src/application/planet-application.service.ts
@@ -5,6 +5,7 @@ import { shareReplay, map, switchMap, startWith } from 'rxjs/operators';
import { coerceArray } from '../helpers';
import { Observable, of } from 'rxjs';
import { AssetsLoadResult, AssetsLoader } from '../assets-loader';
+import { globalPlanet } from './planet-application-ref';
@Injectable({
providedIn: 'root'
@@ -25,6 +26,7 @@ export class PlanetApplicationService {
this.apps.push(app);
this.appsMap[app.name] = app;
});
+ globalPlanet.registerApps = this.apps;
}
registerByUrl(url: string): Observable {
@@ -48,11 +50,12 @@ export class PlanetApplicationService {
this.apps = this.apps.filter(app => {
return app.name !== name;
});
+ globalPlanet.registerApps = this.apps;
}
}
getAppsByMatchedUrl(url: string): PlanetApplication[] {
- return this.apps.filter(app => {
+ return this.getApps().filter(app => {
if (app.routerPathPrefix instanceof RegExp) {
return app.routerPathPrefix.test(url);
} else {
@@ -62,7 +65,7 @@ export class PlanetApplicationService {
}
getAppByMatchedUrl(url: string): PlanetApplication {
- return this.apps.find(app => {
+ return this.getApps().find(app => {
if (app.routerPathPrefix instanceof RegExp) {
return app.routerPathPrefix.test(url);
} else {
@@ -72,7 +75,7 @@ export class PlanetApplicationService {
}
getAppsToPreload(excludeAppNames?: string[]) {
- return this.apps.filter(app => {
+ return this.getApps().filter(app => {
if (excludeAppNames) {
return app.preload && !excludeAppNames.includes(app.name);
} else {
@@ -85,3 +88,9 @@ export class PlanetApplicationService {
return this.apps;
}
}
+
+export function getPlanetApplicationByName(name: string) {
+ return globalPlanet.registerApps.find(app => {
+ return app.name === name;
+ });
+}
diff --git a/packages/planet/src/component/planet-component-loader.spec.ts b/packages/planet/src/component/planet-component-loader.spec.ts
new file mode 100644
index 0000000..844b69c
--- /dev/null
+++ b/packages/planet/src/component/planet-component-loader.spec.ts
@@ -0,0 +1,140 @@
+import { TestBed, inject, tick, fakeAsync } from '@angular/core/testing';
+import { Compiler, Injector, Type, NgModuleRef } from '@angular/core';
+import { app1Name, App1Module, App1ProjectsComponent } from './test/app1.module';
+import { app2Name, App2Module } from './test/app2.module';
+import { defineApplication, getPlanetApplicationRef } from '../application/planet-application-ref';
+import { PlanetPortalApplication } from '../application/portal-application';
+import { PlanetComponentLoader } from './planet-component-loader';
+import { PlanetApplicationLoader } from '../application/planet-application-loader';
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { RouterModule } from '@angular/router';
+import { of } from 'rxjs';
+import { tap } from 'rxjs/operators';
+import { PlantComponentConfig } from './plant-component.config';
+
+describe('PlanetComponentLoader', () => {
+ let compiler: Compiler;
+ let injector: Injector;
+
+ function defineAndBootstrapApplication(name: string, appModule: Type) {
+ const ngModuleFactory = compiler.compileModuleSync(appModule);
+ const ngModuleRef = ngModuleFactory.create(injector);
+ defineApplication(name, (portalApp?: PlanetPortalApplication) => {
+ return new Promise(resolve => {
+ resolve(ngModuleRef);
+ });
+ });
+ const appRef = getPlanetApplicationRef(name);
+ const portalApplication = new PlanetPortalApplication();
+ appRef.bootstrap(portalApplication);
+ return ngModuleRef;
+ }
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ imports: [HttpClientTestingModule, RouterModule.forRoot([])]
+ });
+ });
+
+ afterEach(() => {
+ (window as any).planet.apps = {};
+ });
+
+ beforeEach(inject([Compiler, Injector], (_compiler: Compiler, _injector: Injector) => {
+ compiler = _compiler;
+ injector = _injector;
+ }));
+
+ it('should register component success', fakeAsync(() => {
+ // mock app1 and app2 bootstrap
+ const app1ModuleRef = defineAndBootstrapApplication(app1Name, App1Module);
+ registerAppComponents(app1ModuleRef);
+ const app1Ref = getPlanetApplicationRef(app1Name);
+ expect(app1Ref.getComponentFactory()).toBeTruthy();
+ }));
+
+ it('should app2 load app1 component', fakeAsync(() => {
+ // mock app1 and app2 bootstrap
+ const app1ModuleRef = defineAndBootstrapApplication(app1Name, App1Module);
+ const app2ModuleRef = defineAndBootstrapApplication(app2Name, App2Module);
+ tick();
+
+ expect(() => {
+ loadApp1Component(app2ModuleRef);
+ }).toThrowError(`${app1Name} not registered components`);
+
+ registerAppComponents(app1ModuleRef);
+
+ expect(() => {
+ loadApp1Component(app2ModuleRef, { container: null });
+ }).toThrowError(`config 'container' cannot be null`);
+
+ loadApp1ComponentAndExpectHtml(app2ModuleRef);
+ }));
+
+ it('should app2 load app1 component and preload app1', fakeAsync(() => {
+ // mock app2 bootstrap
+ const app2ModuleRef = defineAndBootstrapApplication(app2Name, App1Module);
+ // mock app1 preload
+ const applicationLoader = app2ModuleRef.injector.get(PlanetApplicationLoader);
+ const applicationLoaderSpy = spyOn(applicationLoader, 'preload');
+ const preload$ = of(getPlanetApplicationRef(app1Name)).pipe(
+ tap(() => {
+ const app1ModuleRef = defineAndBootstrapApplication(app1Name, App1Module);
+ registerAppComponents(app1ModuleRef);
+ })
+ );
+ applicationLoaderSpy.and.returnValue(preload$);
+ expect(applicationLoaderSpy).not.toHaveBeenCalled();
+ loadApp1ComponentAndExpectHtml(app2ModuleRef);
+ expect(applicationLoaderSpy).toHaveBeenCalled();
+ }));
+
+ it('should app2 dispose app1 component ', fakeAsync(() => {
+ // mock app1 and app2 bootstrap
+ const app1ModuleRef = defineAndBootstrapApplication(app1Name, App1Module);
+ const app2ModuleRef = defineAndBootstrapApplication(app2Name, App2Module);
+ registerAppComponents(app1ModuleRef);
+ loadApp1Component(app2ModuleRef).subscribe(componentRef => {
+ const parent = componentRef.container.parentElement;
+ componentRef.dispose();
+ expect(parent.innerHTML).toEqual('');
+ });
+ }));
+});
+
+function registerAppComponents(appModuleRef: NgModuleRef) {
+ const componentLoader = appModuleRef.injector.get(PlanetComponentLoader);
+ componentLoader.register([{ name: 'app1-projects', component: App1ProjectsComponent }]);
+ tick();
+}
+
+function loadApp1Component(appModuleRef: NgModuleRef, config?: PlantComponentConfig) {
+ const componentLoader = appModuleRef.injector.get(PlanetComponentLoader);
+ const hostElement = createComponentHostElement();
+ const result = componentLoader.load(app1Name, 'app1-projects', config ? config : { container: hostElement });
+ tick(30);
+ return result;
+}
+
+function loadApp1ComponentAndExpectHtml(app2ModuleRef: NgModuleRef) {
+ loadApp1Component(app2ModuleRef).subscribe(componentRef => {
+ expect(componentRef.container.outerHTML).toEqual(
+ ``
+ );
+ });
+}
+
+function createComponentHostElement(): HTMLElement {
+ const componentHostClass = 'component-host';
+ let element = document.body.getElementsByClassName(componentHostClass)[0];
+ if (element) {
+ element.innerHTML = '';
+ return element as HTMLElement;
+ } else {
+ element = document.createElement('DIV');
+ element.classList.add('component-host');
+ document.body.appendChild(element);
+ return element as HTMLElement;
+ }
+}
diff --git a/packages/planet/src/component/planet-component-loader.ts b/packages/planet/src/component/planet-component-loader.ts
index 111e614..cafd78b 100644
--- a/packages/planet/src/component/planet-component-loader.ts
+++ b/packages/planet/src/component/planet-component-loader.ts
@@ -1,9 +1,14 @@
-import { Injectable, ApplicationRef, NgModuleRef, NgZone, ChangeDetectorRef, ElementRef } from '@angular/core';
+import { Injectable, ApplicationRef, NgModuleRef, NgZone, ElementRef, Inject } from '@angular/core';
import { ComponentType, DomPortalOutlet, ComponentPortal, PortalInjector } from '@angular/cdk/portal';
-import { globalPlanet } from '../application/planet-application-ref';
+import { globalPlanet, PlanetApplicationRef } from '../application/planet-application-ref';
import { PlanetComponentRef } from './planet-component-ref';
import { PlantComponentConfig } from './plant-component.config';
import { coerceArray } from '../helpers';
+import { getPlanetApplicationByName } from '../application/planet-application.service';
+import { PlanetApplicationLoader } from '../application/planet-application-loader';
+import { delay, map, shareReplay, finalize } from 'rxjs/operators';
+import { of, Observable } from 'rxjs';
+import { DOCUMENT } from '@angular/common';
export interface PlanetComponent {
name: string;
@@ -19,14 +24,23 @@ export class PlanetComponentLoader {
constructor(
private applicationRef: ApplicationRef,
private ngModuleRef: NgModuleRef,
- private ngZone: NgZone
+ private ngZone: NgZone,
+ private applicationLoader: PlanetApplicationLoader,
+ @Inject(DOCUMENT) private document: any
) {}
- private getPlantAppRef(app: string) {
- if (globalPlanet.apps[app]) {
- return globalPlanet.apps[app];
+ private getPlantAppRef(name: string): Observable {
+ if (globalPlanet.apps[name] && globalPlanet.apps[name].appModuleRef) {
+ return of(globalPlanet.apps[name]);
} else {
- throwAppNotDefineError(app);
+ const app = getPlanetApplicationByName(name);
+ return this.applicationLoader.preload(app).pipe(
+ // Because register use 'setTimeout',so delay 20
+ delay(20),
+ map(() => {
+ return globalPlanet.apps[name];
+ })
+ );
}
}
@@ -40,17 +54,25 @@ export class PlanetComponentLoader {
}
private getContainerElement(config: PlantComponentConfig): HTMLElement {
- if (config.container) {
+ if (!config.container) {
+ throw new Error(`config 'container' cannot be null`);
+ } else {
if ((config.container as ElementRef).nativeElement) {
return (config.container as ElementRef).nativeElement;
} else {
return config.container as HTMLElement;
}
- } else {
- throw new Error(`config 'container' cannot be null`);
}
}
+ private createContainerElement(config: PlantComponentConfig) {
+ const container = this.getContainerElement(config);
+ const element = this.document.createElement('div');
+ element.classList.add('planet-component-container');
+ container.appendChild(element);
+ return element;
+ }
+
private attachComponent(
plantComponent: PlanetComponent,
appModuleRef: NgModuleRef,
@@ -60,7 +82,7 @@ export class PlanetComponentLoader {
const componentFactoryResolver = appModuleRef.componentFactoryResolver;
const appRef = this.applicationRef;
const injector = this.createInjector(appModuleRef, plantComponentRef);
- const container = this.getContainerElement(config);
+ const container = this.createContainerElement(config);
let portalOutlet = this.domPortalOutletCache.get(container);
if (portalOutlet) {
portalOutlet.detach();
@@ -85,17 +107,18 @@ export class PlanetComponentLoader {
private registerComponentFactory(componentOrComponents: PlanetComponent | PlanetComponent[]) {
const app = this.ngModuleRef.instance.appName;
- const planetAppRef = this.getPlantAppRef(app);
- planetAppRef.registerComponentFactory((componentName: string, config: PlantComponentConfig) => {
- const components = coerceArray(componentOrComponents);
- const component = components.find(item => item.name === componentName);
- if (component) {
- return this.ngZone.run(() => {
- return this.attachComponent(component, planetAppRef.appModuleRef, config);
- });
- } else {
- throw Error(`unregistered component ${componentName} in app ${app}`);
- }
+ this.getPlantAppRef(app).subscribe(appRef => {
+ appRef.registerComponentFactory((componentName: string, config: PlantComponentConfig) => {
+ const components = coerceArray(componentOrComponents);
+ const component = components.find(item => item.name === componentName);
+ if (component) {
+ return this.ngZone.run(() => {
+ return this.attachComponent(component, appRef.appModuleRef, config);
+ });
+ } else {
+ throw Error(`unregistered component ${componentName} in app ${app}`);
+ }
+ });
});
}
@@ -105,17 +128,22 @@ export class PlanetComponentLoader {
});
}
- load(
- app: string,
- componentName: string,
- config: PlantComponentConfig,
- error: (error) => void = e => {}
- ) {
- const planetAppRef = this.getPlantAppRef(app);
- return planetAppRef.loadPlantComponent(componentName, config);
+ load(app: string, componentName: string, config: PlantComponentConfig) {
+ const result = this.getPlantAppRef(app).pipe(
+ map(appRef => {
+ const componentFactory = appRef.getComponentFactory();
+ if (componentFactory) {
+ return componentFactory(componentName, config);
+ } else {
+ throw new Error(`${app} not registered components`);
+ }
+ }),
+ finalize(() => {
+ this.applicationRef.tick();
+ }),
+ shareReplay()
+ );
+ result.subscribe();
+ return result;
}
}
-
-function throwAppNotDefineError(app: string) {
- throw new Error(`${app} app is not define`);
-}
diff --git a/packages/planet/src/component/test/app1.module.ts b/packages/planet/src/component/test/app1.module.ts
new file mode 100644
index 0000000..a7f5028
--- /dev/null
+++ b/packages/planet/src/component/test/app1.module.ts
@@ -0,0 +1,35 @@
+import { Component, NgModule } from '@angular/core';
+import { RouterModule } from '@angular/router';
+import { PlanetComponentLoader } from '../planet-component-loader';
+import { of } from 'rxjs';
+import { PlanetApplicationLoader } from '../../application/planet-application-loader';
+
+export const app1Name = 'app1';
+
+@Component({
+ selector: 'app1-projects',
+ template: `
+ projects is work
+ `
+})
+export class App1ProjectsComponent {}
+
+@NgModule({
+ declarations: [App1ProjectsComponent],
+ entryComponents: [App1ProjectsComponent],
+ imports: [RouterModule.forChild([])],
+ providers: [
+ PlanetComponentLoader,
+ {
+ provide: PlanetApplicationLoader,
+ useValue: {
+ preload: () => {}
+ }
+ }
+ ]
+})
+export class App1Module {
+ constructor(private componentLoader: PlanetComponentLoader) {
+ // componentLoader.register([{ name: 'app1-projects', component: App1ProjectsComponent }]);
+ }
+}
diff --git a/packages/planet/src/component/test/app2.module.ts b/packages/planet/src/component/test/app2.module.ts
new file mode 100644
index 0000000..852be6b
--- /dev/null
+++ b/packages/planet/src/component/test/app2.module.ts
@@ -0,0 +1,25 @@
+import { Component, NgModule } from '@angular/core';
+import { RouterModule } from '@angular/router';
+import { PlanetApplicationLoader } from '../../application/planet-application-loader';
+import { of } from 'rxjs';
+import { PlanetComponentLoader } from '../planet-component-loader';
+
+export const app2Name = 'app2';
+
+@NgModule({
+ declarations: [],
+ entryComponents: [],
+ imports: [RouterModule.forChild([])],
+ providers: [
+ PlanetComponentLoader,
+ {
+ provide: PlanetApplicationLoader,
+ useValue: {
+ preload: () => {}
+ }
+ }
+ ]
+})
+export class App2Module {
+ constructor() {}
+}